Pau Espin Pedrol | 786a6bc | 2020-03-30 13:51:21 +0200 | [diff] [blame] | 1 | # osmo_gsm_tester: base classes to share code among eNodeB subclasses. |
| 2 | # |
| 3 | # Copyright (C) 2020 by sysmocom - s.f.m.c. GmbH |
| 4 | # |
| 5 | # Author: Pau Espin Pedrol <pespin@sysmocom.de> |
| 6 | # |
| 7 | # This program is free software: you can redistribute it and/or modify |
| 8 | # it under the terms of the GNU General Public License as |
| 9 | # published by the Free Software Foundation, either version 3 of the |
| 10 | # License, or (at your option) any later version. |
| 11 | # |
| 12 | # This program is distributed in the hope that it will be useful, |
| 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | # GNU General Public License for more details. |
| 16 | # |
| 17 | # You should have received a copy of the GNU General Public License |
| 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 19 | |
| 20 | from abc import ABCMeta, abstractmethod |
Pau Espin Pedrol | e1a58bd | 2020-04-10 20:46:07 +0200 | [diff] [blame] | 21 | from ..core import log, config |
Pau Espin Pedrol | ea8c3d4 | 2020-05-04 12:05:05 +0200 | [diff] [blame] | 22 | from ..core import schema |
Pau Espin Pedrol | 1abff4e | 2020-05-26 12:32:19 +0200 | [diff] [blame] | 23 | from . import run_node |
Pau Espin Pedrol | fbb8611 | 2020-10-16 16:55:23 +0200 | [diff] [blame] | 24 | from .gnuradio_zmq_broker import GrBroker |
Pau Espin Pedrol | 786a6bc | 2020-03-30 13:51:21 +0200 | [diff] [blame] | 25 | |
Pau Espin Pedrol | ea8c3d4 | 2020-05-04 12:05:05 +0200 | [diff] [blame] | 26 | def on_register_schemas(): |
| 27 | resource_schema = { |
| 28 | 'label': schema.STR, |
| 29 | 'type': schema.STR, |
Pau Espin Pedrol | ea8c3d4 | 2020-05-04 12:05:05 +0200 | [diff] [blame] | 30 | 'gtp_bind_addr': schema.IPV4, |
| 31 | 'id': schema.UINT, |
| 32 | 'num_prb': schema.UINT, |
Andre Puschmann | d0682ba | 2020-10-15 15:46:29 +0200 | [diff] [blame] | 33 | 'duplex': schema.STR, |
| 34 | 'tdd_uldl_config': schema.UINT, |
| 35 | 'tdd_special_subframe_pattern': schema.UINT, |
Pau Espin Pedrol | ea8c3d4 | 2020-05-04 12:05:05 +0200 | [diff] [blame] | 36 | 'transmission_mode': schema.LTE_TRANSMISSION_MODE, |
Andre Puschmann | a54ca0b | 2021-04-14 23:24:04 +0200 | [diff] [blame] | 37 | 'rx_ant': schema.STR, |
Pau Espin Pedrol | ea8c3d4 | 2020-05-04 12:05:05 +0200 | [diff] [blame] | 38 | 'tx_gain': schema.UINT, |
| 39 | 'rx_gain': schema.UINT, |
| 40 | 'rf_dev_type': schema.STR, |
| 41 | 'rf_dev_args': schema.STR, |
Andre Puschmann | c489f19 | 2020-10-09 14:46:38 +0200 | [diff] [blame] | 42 | 'rf_dev_sync': schema.STR, |
Pau Espin Pedrol | e592de8 | 2020-06-15 17:01:16 +0200 | [diff] [blame] | 43 | 'additional_args[]': schema.STR, |
Andre Puschmann | 0cfc084 | 2020-08-26 18:19:15 +0200 | [diff] [blame] | 44 | 'inactivity_timer': schema.INT, |
Pau Espin Pedrol | ea8c3d4 | 2020-05-04 12:05:05 +0200 | [diff] [blame] | 45 | 'enable_measurements': schema.BOOL_STR, |
Andre Puschmann | 955249d | 2020-07-01 15:44:09 +0200 | [diff] [blame] | 46 | 'enable_dl_awgn': schema.BOOL_STR, |
| 47 | 'dl_awgn_snr': schema.INT, |
Nils Fürste | a818015 | 2020-12-03 14:14:31 +0100 | [diff] [blame] | 48 | 'cipher_list[]': schema.CIPHER_4G, |
| 49 | 'integrity_list[]': schema.INTEGRITY_4G, |
Pau Espin Pedrol | ea8c3d4 | 2020-05-04 12:05:05 +0200 | [diff] [blame] | 50 | 'a1_report_type': schema.STR, |
| 51 | 'a1_report_value': schema.INT, |
| 52 | 'a1_hysteresis': schema.INT, |
| 53 | 'a1_time_to_trigger': schema.INT, |
| 54 | 'a2_report_type': schema.STR, |
| 55 | 'a2_report_value': schema.INT, |
| 56 | 'a2_hysteresis': schema.INT, |
| 57 | 'a2_time_to_trigger': schema.INT, |
| 58 | 'a3_report_type': schema.STR, |
| 59 | 'a3_report_value': schema.INT, |
| 60 | 'a3_hysteresis': schema.INT, |
| 61 | 'a3_time_to_trigger': schema.INT, |
| 62 | 'num_cells': schema.UINT, |
| 63 | 'cell_list[].cell_id': schema.UINT, |
Andre Puschmann | 549826d | 2020-04-21 21:14:30 +0200 | [diff] [blame] | 64 | 'cell_list[].rf_port': schema.UINT, |
Pau Espin Pedrol | ea8c3d4 | 2020-05-04 12:05:05 +0200 | [diff] [blame] | 65 | 'cell_list[].pci': schema.UINT, |
Pau Espin Pedrol | ef7256a | 2020-11-09 18:52:05 +0100 | [diff] [blame] | 66 | 'cell_list[].ncell_list[].enb_id': schema.UINT, |
| 67 | 'cell_list[].ncell_list[].cell_id': schema.UINT, |
| 68 | 'cell_list[].ncell_list[].pci': schema.UINT, |
| 69 | 'cell_list[].ncell_list[].dl_earfcn': schema.UINT, |
Pau Espin Pedrol | ea8c3d4 | 2020-05-04 12:05:05 +0200 | [diff] [blame] | 70 | 'cell_list[].scell_list[]': schema.UINT, |
Andre Puschmann | 6e081aa | 2021-05-04 16:56:25 +0200 | [diff] [blame] | 71 | 'cell_list[].nr_scell_list[]': schema.UINT, |
Pau Espin Pedrol | ea8c3d4 | 2020-05-04 12:05:05 +0200 | [diff] [blame] | 72 | 'cell_list[].dl_earfcn': schema.UINT, |
Andre Puschmann | a7fd394 | 2020-11-06 16:24:38 +0100 | [diff] [blame] | 73 | 'cell_list[].root_seq_idx': schema.UINT, |
| 74 | 'cell_list[].tac': schema.UINT, |
Pau Espin Pedrol | ea8c3d4 | 2020-05-04 12:05:05 +0200 | [diff] [blame] | 75 | 'cell_list[].dl_rfemu.type': schema.STR, |
| 76 | 'cell_list[].dl_rfemu.addr': schema.IPV4, |
| 77 | 'cell_list[].dl_rfemu.ports[]': schema.UINT, |
Andre Puschmann | 6e081aa | 2021-05-04 16:56:25 +0200 | [diff] [blame] | 78 | 'num_nr_cells': schema.UINT, |
| 79 | 'nr_cell_list[].rf_port': schema.UINT, |
| 80 | 'nr_cell_list[].cell_id': schema.UINT, |
| 81 | 'nr_cell_list[].band': schema.UINT, |
| 82 | 'nr_cell_list[].dl_nr_arfcn': schema.UINT, |
Pau Espin Pedrol | ea8c3d4 | 2020-05-04 12:05:05 +0200 | [diff] [blame] | 83 | } |
Pau Espin Pedrol | 1abff4e | 2020-05-26 12:32:19 +0200 | [diff] [blame] | 84 | for key, val in run_node.RunNode.schema().items(): |
| 85 | resource_schema['run_node.%s' % key] = val |
Pau Espin Pedrol | ea8c3d4 | 2020-05-04 12:05:05 +0200 | [diff] [blame] | 86 | schema.register_resource_schema('enb', resource_schema) |
Pau Espin Pedrol | 786a6bc | 2020-03-30 13:51:21 +0200 | [diff] [blame] | 87 | |
| 88 | class eNodeB(log.Origin, metaclass=ABCMeta): |
| 89 | |
| 90 | ############## |
| 91 | # PROTECTED |
| 92 | ############## |
Pau Espin Pedrol | a442cb8 | 2020-05-05 12:54:37 +0200 | [diff] [blame] | 93 | def __init__(self, testenv, conf, name): |
Pau Espin Pedrol | 786a6bc | 2020-03-30 13:51:21 +0200 | [diff] [blame] | 94 | super().__init__(log.C_RUN, '%s' % name) |
| 95 | self._conf = conf |
Pau Espin Pedrol | 1abff4e | 2020-05-26 12:32:19 +0200 | [diff] [blame] | 96 | self._run_node = run_node.RunNode.from_conf(conf.get('run_node', {})) |
Andre Puschmann | 4b5a09a | 2020-04-14 22:24:00 +0200 | [diff] [blame] | 97 | self._gtp_bind_addr = conf.get('gtp_bind_addr', None) |
| 98 | if self._gtp_bind_addr is None: |
Pau Espin Pedrol | 1abff4e | 2020-05-26 12:32:19 +0200 | [diff] [blame] | 99 | self._gtp_bind_addr = self._run_node.run_addr() |
Pau Espin Pedrol | a2d4e2f | 2020-10-22 15:46:42 +0200 | [diff] [blame] | 100 | label = conf.get('label', None) |
Andre Puschmann | bfd3fe6 | 2020-12-09 21:40:46 +0100 | [diff] [blame] | 101 | if label is not None: |
| 102 | self.set_name('%s_%s_%s' % (name, label, self._run_node.run_addr())) |
| 103 | else: |
| 104 | self.set_name('%s_%s' % (name, self._run_node.run_addr())) |
Pau Espin Pedrol | e44e76a | 2020-03-31 12:35:19 +0200 | [diff] [blame] | 105 | self._txmode = 0 |
Pau Espin Pedrol | 491f77c | 2020-04-20 14:20:43 +0200 | [diff] [blame] | 106 | self._id = None |
Andre Puschmann | 6e081aa | 2021-05-04 16:56:25 +0200 | [diff] [blame] | 107 | self._ran_config = "lte" # Used to determine whether we are in NSA |
Andre Puschmann | d0682ba | 2020-10-15 15:46:29 +0200 | [diff] [blame] | 108 | self._duplex = None |
Pau Espin Pedrol | e44e76a | 2020-03-31 12:35:19 +0200 | [diff] [blame] | 109 | self._num_prb = 0 |
Pau Espin Pedrol | f46ae22 | 2020-04-17 16:23:54 +0200 | [diff] [blame] | 110 | self._num_cells = None |
Andre Puschmann | 6e081aa | 2021-05-04 16:56:25 +0200 | [diff] [blame] | 111 | self._num_nr_cells = None |
Pau Espin Pedrol | e44e76a | 2020-03-31 12:35:19 +0200 | [diff] [blame] | 112 | self._epc = None |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 113 | self.gen_conf = None |
Pau Espin Pedrol | fbb8611 | 2020-10-16 16:55:23 +0200 | [diff] [blame] | 114 | self.gr_broker = GrBroker.ref() |
| 115 | self.gr_broker.register_enb(self) |
| 116 | self._use_gr_broker = False |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 117 | |
| 118 | def using_grbroker(self, cfg_values): |
| 119 | # whether we are to use Grbroker in between ENB and UE. |
| 120 | # Initial checks: |
| 121 | if cfg_values['enb'].get('rf_dev_type') != 'zmq': |
| 122 | return False |
| 123 | cell_list = cfg_values['enb']['cell_list'] |
| 124 | use_match = False |
| 125 | notuse_match = False |
| 126 | for cell in cell_list: |
| 127 | if cell.get('dl_rfemu', False) and cell['dl_rfemu'].get('type', None) == 'gnuradio_zmq': |
| 128 | use_match = True |
| 129 | else: |
| 130 | notuse_match = True |
| 131 | if use_match and notuse_match: |
| 132 | raise log.Error('Some Cells are configured to use gnuradio_zmq and some are not, unsupported') |
| 133 | return use_match |
| 134 | |
| 135 | def calc_required_zmq_ports(self, cfg_values): |
| 136 | cell_list = cfg_values['enb']['cell_list'] |
Andre Puschmann | 6e081aa | 2021-05-04 16:56:25 +0200 | [diff] [blame] | 137 | nr_cell_list = cfg_values['enb']['nr_cell_list'] |
| 138 | return len(cell_list) * self.num_ports() + len(nr_cell_list) # *2 if LTE MIMO |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 139 | |
| 140 | def calc_required_zmq_ports_joined_earfcn(self, cfg_values): |
Andre Puschmann | 6e081aa | 2021-05-04 16:56:25 +0200 | [diff] [blame] | 141 | #gr_broker will join the earfcns, so we need to count unique earfcns (only implemented for LTE): |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 142 | cell_list = cfg_values['enb']['cell_list'] |
| 143 | earfcn_li = [] |
| 144 | [earfcn_li.append(int(cell['dl_earfcn'])) for cell in cell_list if int(cell['dl_earfcn']) not in earfcn_li] |
| 145 | return len(earfcn_li) * self.num_ports() # *2 if MIMO |
| 146 | |
| 147 | |
| 148 | def assign_enb_zmq_ports(self, cfg_values, port_name, base_port): |
| 149 | port_offset = 0 |
| 150 | cell_list = cfg_values['enb']['cell_list'] |
| 151 | for cell in cell_list: |
| 152 | cell[port_name] = base_port + port_offset |
| 153 | port_offset += self.num_ports() |
Andre Puschmann | 6e081aa | 2021-05-04 16:56:25 +0200 | [diff] [blame] | 154 | nr_cell_list = cfg_values['enb']['nr_cell_list'] |
| 155 | for nr_cell in nr_cell_list: |
| 156 | nr_cell[port_name] = base_port + port_offset |
| 157 | port_offset += 1 |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 158 | # TODO: do we need to assign cell_list back? |
| 159 | |
| 160 | def assign_enb_zmq_ports_joined_earfcn(self, cfg_values, port_name, base_port): |
| 161 | # TODO: Set in cell one bind port per unique earfcn, this is where UE will connect to when we use grbroker. |
| 162 | cell_list = cfg_values['enb']['cell_list'] |
| 163 | earfcn_li = [] |
| 164 | [earfcn_li.append(int(cell['dl_earfcn'])) for cell in cell_list if int(cell['dl_earfcn']) not in earfcn_li] |
| 165 | for cell in cell_list: |
| 166 | cell[port_name] = base_port + earfcn_li.index(int(cell['dl_earfcn'])) * self.num_ports() |
Pau Espin Pedrol | e44e76a | 2020-03-31 12:35:19 +0200 | [diff] [blame] | 167 | |
Pau Espin Pedrol | c04528c | 2020-04-01 13:55:51 +0200 | [diff] [blame] | 168 | def configure(self, config_specifics_li): |
Pau Espin Pedrol | e44e76a | 2020-03-31 12:35:19 +0200 | [diff] [blame] | 169 | values = dict(enb=config.get_defaults('enb')) |
Pau Espin Pedrol | c04528c | 2020-04-01 13:55:51 +0200 | [diff] [blame] | 170 | for config_specifics in config_specifics_li: |
| 171 | config.overlay(values, dict(enb=config.get_defaults(config_specifics))) |
Pau Espin Pedrol | a442cb8 | 2020-05-05 12:54:37 +0200 | [diff] [blame] | 172 | config.overlay(values, dict(enb=self.testenv.suite().config().get('enb', {}))) |
Pau Espin Pedrol | c04528c | 2020-04-01 13:55:51 +0200 | [diff] [blame] | 173 | for config_specifics in config_specifics_li: |
Pau Espin Pedrol | a442cb8 | 2020-05-05 12:54:37 +0200 | [diff] [blame] | 174 | config.overlay(values, dict(enb=self.testenv.suite().config().get(config_specifics, {}))) |
Pau Espin Pedrol | e44e76a | 2020-03-31 12:35:19 +0200 | [diff] [blame] | 175 | config.overlay(values, dict(enb=self._conf)) |
Pau Espin Pedrol | 491f77c | 2020-04-20 14:20:43 +0200 | [diff] [blame] | 176 | self._id = int(values['enb'].get('id', None)) |
| 177 | assert self._id is not None |
Andre Puschmann | d0682ba | 2020-10-15 15:46:29 +0200 | [diff] [blame] | 178 | self._duplex = values['enb'].get('duplex', None) |
| 179 | assert self._duplex |
Pau Espin Pedrol | e44e76a | 2020-03-31 12:35:19 +0200 | [diff] [blame] | 180 | self._num_prb = int(values['enb'].get('num_prb', None)) |
| 181 | assert self._num_prb |
| 182 | self._txmode = int(values['enb'].get('transmission_mode', None)) |
| 183 | assert self._txmode |
| 184 | config.overlay(values, dict(enb={ 'num_ports': self.num_ports() })) |
Andre Puschmann | 0cfc084 | 2020-08-26 18:19:15 +0200 | [diff] [blame] | 185 | self._inactivity_timer = int(values['enb'].get('inactivity_timer', None)) |
| 186 | assert self._inactivity_timer |
Pau Espin Pedrol | e44e76a | 2020-03-31 12:35:19 +0200 | [diff] [blame] | 187 | assert self._epc is not None |
Pau Espin Pedrol | 1abff4e | 2020-05-26 12:32:19 +0200 | [diff] [blame] | 188 | config.overlay(values, dict(enb={ 'addr': self.addr() })) |
Pau Espin Pedrol | e44e76a | 2020-03-31 12:35:19 +0200 | [diff] [blame] | 189 | config.overlay(values, dict(enb={ 'mme_addr': self._epc.addr() })) |
Andre Puschmann | 4b5a09a | 2020-04-14 22:24:00 +0200 | [diff] [blame] | 190 | config.overlay(values, dict(enb={ 'gtp_bind_addr': self._gtp_bind_addr })) |
Pau Espin Pedrol | f46ae22 | 2020-04-17 16:23:54 +0200 | [diff] [blame] | 191 | self._num_cells = int(values['enb'].get('num_cells', None)) |
Andre Puschmann | 6e081aa | 2021-05-04 16:56:25 +0200 | [diff] [blame] | 192 | self._num_nr_cells = int(values['enb'].get('num_nr_cells', None)) |
| 193 | assert self._num_cells is not None |
| 194 | assert self._num_nr_cells is not None |
Pau Espin Pedrol | f46ae22 | 2020-04-17 16:23:54 +0200 | [diff] [blame] | 195 | |
| 196 | # adjust cell_list to num_cells length: |
| 197 | len_cell_list = len(values['enb']['cell_list']) |
| 198 | if len_cell_list >= self._num_cells: |
| 199 | values['enb']['cell_list'] = values['enb']['cell_list'][:self._num_cells] |
| 200 | else: |
| 201 | raise log.Error('enb.cell_list items (%d) < enb.num_cells (%d) attribute!' % (len_cell_list, self._num_cells)) |
| 202 | # adjust scell list (to only contain values available in cell_list): |
| 203 | cell_id_list = [c['cell_id'] for c in values['enb']['cell_list']] |
| 204 | for i in range(len(values['enb']['cell_list'])): |
| 205 | scell_list_old = values['enb']['cell_list'][i]['scell_list'] |
| 206 | scell_list_new = [] |
| 207 | for scell_id in scell_list_old: |
| 208 | if scell_id in cell_id_list: |
| 209 | scell_list_new.append(scell_id) |
| 210 | values['enb']['cell_list'][i]['scell_list'] = scell_list_new |
| 211 | |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 212 | # Assign ZMQ ports to each Cell/EARFCN. |
| 213 | if values['enb'].get('rf_dev_type') == 'zmq': |
| 214 | resourcep = self.testenv.suite().resource_pool() |
| 215 | num_ports = self.calc_required_zmq_ports(values) |
| 216 | num_ports_joined_earfcn = self.calc_required_zmq_ports_joined_earfcn(values) |
| 217 | ue_bind_port = self.ue.zmq_base_bind_port() |
| 218 | enb_bind_port = resourcep.next_zmq_port_range(self, num_ports) |
| 219 | self.assign_enb_zmq_ports(values, 'zmq_enb_bind_port', enb_bind_port) |
| 220 | # If we are to use a GrBroker, then initialize here to have remote zmq ports available: |
Pau Espin Pedrol | fbb8611 | 2020-10-16 16:55:23 +0200 | [diff] [blame] | 221 | self._use_gr_broker = self.using_grbroker(values) |
| 222 | if self._use_gr_broker: |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 223 | zmq_enb_peer_port = resourcep.next_zmq_port_range(self, num_ports) |
| 224 | self.assign_enb_zmq_ports(values, 'zmq_enb_peer_port', zmq_enb_peer_port) # These are actually bound to GrBroker |
| 225 | self.assign_enb_zmq_ports_joined_earfcn(values, 'zmq_ue_bind_port', ue_bind_port) # This is were GrBroker binds on the UE side |
| 226 | zmq_ue_peer_port = resourcep.next_zmq_port_range(self, num_ports_joined_earfcn) |
| 227 | self.assign_enb_zmq_ports_joined_earfcn(values, 'zmq_ue_peer_port', zmq_ue_peer_port) # This is were GrBroker binds on the UE side |
| 228 | # Already set gen_conf here in advance since gr_broker needs the cell list |
| 229 | self.gen_conf = values |
Pau Espin Pedrol | fbb8611 | 2020-10-16 16:55:23 +0200 | [diff] [blame] | 230 | self.gr_broker.start() |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 231 | else: |
| 232 | self.assign_enb_zmq_ports(values, 'zmq_enb_peer_port', ue_bind_port) |
| 233 | self.assign_enb_zmq_ports(values, 'zmq_ue_bind_port', ue_bind_port) #If no broker we need to match amount of ports |
| 234 | self.assign_enb_zmq_ports(values, 'zmq_ue_peer_port', enb_bind_port) |
| 235 | |
Pau Espin Pedrol | e44e76a | 2020-03-31 12:35:19 +0200 | [diff] [blame] | 236 | return values |
| 237 | |
Pau Espin Pedrol | 491f77c | 2020-04-20 14:20:43 +0200 | [diff] [blame] | 238 | def id(self): |
| 239 | return self._id |
| 240 | |
Pau Espin Pedrol | e44e76a | 2020-03-31 12:35:19 +0200 | [diff] [blame] | 241 | def num_ports(self): |
| 242 | if self._txmode == 1: |
| 243 | return 1 |
| 244 | return 2 |
Pau Espin Pedrol | 786a6bc | 2020-03-30 13:51:21 +0200 | [diff] [blame] | 245 | |
Andre Puschmann | 0957e9e | 2020-06-16 16:29:27 +0200 | [diff] [blame] | 246 | def num_cells(self): |
| 247 | return self._num_cells |
| 248 | |
Andre Puschmann | 6e081aa | 2021-05-04 16:56:25 +0200 | [diff] [blame] | 249 | def num_nr_cells(self): |
| 250 | return self._num_nr_cells |
| 251 | |
Pau Espin Pedrol | 786a6bc | 2020-03-30 13:51:21 +0200 | [diff] [blame] | 252 | ######################## |
| 253 | # PUBLIC - INTERNAL API |
| 254 | ######################## |
| 255 | def cleanup(self): |
| 256 | 'Nothing to do by default. Subclass can override if required.' |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 257 | if self.gr_broker: |
Pau Espin Pedrol | fbb8611 | 2020-10-16 16:55:23 +0200 | [diff] [blame] | 258 | self.gr_broker.unregister_enb(self) |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 259 | GrBroker.unref() |
| 260 | self.gr_broker = None |
Pau Espin Pedrol | 786a6bc | 2020-03-30 13:51:21 +0200 | [diff] [blame] | 261 | |
Pau Espin Pedrol | e44e76a | 2020-03-31 12:35:19 +0200 | [diff] [blame] | 262 | def num_prb(self): |
| 263 | return self._num_prb |
| 264 | |
Andre Puschmann | e2a6da6 | 2020-04-20 20:39:34 +0200 | [diff] [blame] | 265 | #reference: srsLTE.git srslte_symbol_sz() |
| 266 | def num_prb2symbol_sz(self, num_prb): |
Andre Puschmann | 0a50110 | 2020-06-02 22:35:27 +0200 | [diff] [blame] | 267 | if num_prb == 6: |
Andre Puschmann | e2a6da6 | 2020-04-20 20:39:34 +0200 | [diff] [blame] | 268 | return 128 |
Andre Puschmann | 0a50110 | 2020-06-02 22:35:27 +0200 | [diff] [blame] | 269 | if num_prb == 50: |
Andre Puschmann | e2a6da6 | 2020-04-20 20:39:34 +0200 | [diff] [blame] | 270 | return 768 |
Andre Puschmann | 0a50110 | 2020-06-02 22:35:27 +0200 | [diff] [blame] | 271 | if num_prb == 75: |
Andre Puschmann | e2a6da6 | 2020-04-20 20:39:34 +0200 | [diff] [blame] | 272 | return 1024 |
Andre Puschmann | 0a50110 | 2020-06-02 22:35:27 +0200 | [diff] [blame] | 273 | return 1536 |
| 274 | |
Andre Puschmann | e2a6da6 | 2020-04-20 20:39:34 +0200 | [diff] [blame] | 275 | raise log.Error('invalid num_prb %r', num_prb) |
| 276 | |
| 277 | def num_prb2base_srate(self, num_prb): |
| 278 | return self.num_prb2symbol_sz(num_prb) * 15 * 1000 |
| 279 | |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 280 | def get_zmq_rf_dev_args(self, cfg_values): |
Andre Puschmann | e2a6da6 | 2020-04-20 20:39:34 +0200 | [diff] [blame] | 281 | base_srate = self.num_prb2base_srate(self.num_prb()) |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 282 | |
Pau Espin Pedrol | fbb8611 | 2020-10-16 16:55:23 +0200 | [diff] [blame] | 283 | if self._use_gr_broker: |
Pau Espin Pedrol | 4acb45a | 2020-10-23 13:51:03 +0200 | [diff] [blame] | 284 | ul_rem_addr = self.gr_broker.addr() |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 285 | else: |
| 286 | ul_rem_addr = self.ue.addr() |
| 287 | |
Andre Puschmann | f69b948 | 2021-03-14 15:38:58 +0100 | [diff] [blame] | 288 | rf_dev_args = 'fail_on_disconnect=true,log_trx_timeout=true,trx_timeout_ms=8000' |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 289 | idx = 0 |
| 290 | cell_list = cfg_values['enb']['cell_list'] |
Andre Puschmann | e2a6da6 | 2020-04-20 20:39:34 +0200 | [diff] [blame] | 291 | # Define all 8 possible RF ports (2x CA with 2x2 MIMO) |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 292 | for cell in cell_list: |
| 293 | rf_dev_args += ',tx_port%u=tcp://%s:%u' %(idx, self.addr(), cell['zmq_enb_bind_port'] + 0) |
| 294 | if self.num_ports() > 1: |
| 295 | rf_dev_args += ',tx_port%u=tcp://%s:%u' %(idx + 1, self.addr(), cell['zmq_enb_bind_port'] + 1) |
| 296 | rf_dev_args += ',rx_port%u=tcp://%s:%u' %(idx, ul_rem_addr, cell['zmq_enb_peer_port'] + 0) |
| 297 | if self.num_ports() > 1: |
| 298 | rf_dev_args += ',rx_port%u=tcp://%s:%u' %(idx + 1, ul_rem_addr, cell['zmq_enb_peer_port'] + 1) |
| 299 | idx += self.num_ports() |
Andre Puschmann | e2a6da6 | 2020-04-20 20:39:34 +0200 | [diff] [blame] | 300 | |
Andre Puschmann | 6e081aa | 2021-05-04 16:56:25 +0200 | [diff] [blame] | 301 | # Only single antenna supported for NR cells |
| 302 | nr_cell_list = cfg_values['enb']['nr_cell_list'] |
| 303 | for nr_cell in nr_cell_list: |
| 304 | rf_dev_args += ',tx_port%u=tcp://%s:%u' % (idx, self.addr(), nr_cell['zmq_enb_bind_port'] + 0) |
| 305 | rf_dev_args += ',rx_port%u=tcp://%s:%u' % (idx, ul_rem_addr, nr_cell['zmq_enb_peer_port'] + 0) |
| 306 | idx += 1 |
| 307 | |
Andre Puschmann | e2a6da6 | 2020-04-20 20:39:34 +0200 | [diff] [blame] | 308 | rf_dev_args += ',id=enb,base_srate=' + str(base_srate) |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 309 | return rf_dev_args |
Andre Puschmann | e2a6da6 | 2020-04-20 20:39:34 +0200 | [diff] [blame] | 310 | |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 311 | def get_zmq_rf_dev_args_for_ue(self, ue): |
| 312 | cell_list = self.gen_conf['enb']['cell_list'] |
| 313 | rf_dev_args = '' |
| 314 | idx = 0 |
| 315 | earfcns_done = [] |
| 316 | for cell in cell_list: |
Pau Espin Pedrol | fbb8611 | 2020-10-16 16:55:23 +0200 | [diff] [blame] | 317 | if self._use_gr_broker: |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 318 | if cell['dl_earfcn'] in earfcns_done: |
| 319 | continue |
| 320 | earfcns_done.append(cell['dl_earfcn']) |
| 321 | rf_dev_args += ',tx_port%u=tcp://%s:%u' %(idx, ue.addr(), cell['zmq_ue_bind_port'] + 0) |
| 322 | if self.num_ports() > 1: |
| 323 | rf_dev_args += ',tx_port%u=tcp://%s:%u' %(idx + 1, ue.addr(), cell['zmq_ue_bind_port'] + 1) |
| 324 | rf_dev_args += ',rx_port%u=tcp://%s:%u' %(idx, self.addr(), cell['zmq_ue_peer_port'] + 0) |
| 325 | if self.num_ports() > 1: |
| 326 | rf_dev_args += ',rx_port%u=tcp://%s:%u' %(idx + 1, self.addr(), cell['zmq_ue_peer_port'] + 1) |
| 327 | idx += self.num_ports() |
Andre Puschmann | 6e081aa | 2021-05-04 16:56:25 +0200 | [diff] [blame] | 328 | |
| 329 | # NR cells again only with single antenna support |
| 330 | nr_cell_list = self.gen_conf['enb']['nr_cell_list'] |
| 331 | for nr_cell in nr_cell_list: |
| 332 | rf_dev_args += ',tx_port%u=tcp://%s:%u' %(idx, ue.addr(), nr_cell['zmq_ue_bind_port'] + 0) |
| 333 | rf_dev_args += ',rx_port%u=tcp://%s:%u' %(idx, self.addr(), nr_cell['zmq_ue_peer_port'] + 0) |
| 334 | idx += 1 |
| 335 | |
Pau Espin Pedrol | 4109123 | 2020-10-05 19:23:38 +0200 | [diff] [blame] | 336 | # remove trailing comma: |
| 337 | if rf_dev_args[0] == ',': |
| 338 | return rf_dev_args[1:] |
Andre Puschmann | e2a6da6 | 2020-04-20 20:39:34 +0200 | [diff] [blame] | 339 | return rf_dev_args |
| 340 | |
Pau Espin Pedrol | a442cb8 | 2020-05-05 12:54:37 +0200 | [diff] [blame] | 341 | def get_instance_by_type(testenv, conf): |
Pau Espin Pedrol | 1ee5ec5 | 2020-05-04 17:16:39 +0200 | [diff] [blame] | 342 | """Allocate a ENB child class based on type. Opts are passed to the newly created object.""" |
| 343 | enb_type = conf.get('type') |
| 344 | if enb_type is None: |
| 345 | raise RuntimeError('ENB type is not defined!') |
| 346 | |
| 347 | if enb_type == 'amarisoftenb': |
| 348 | from .enb_amarisoft import AmarisoftENB |
| 349 | enb_class = AmarisoftENB |
| 350 | elif enb_type == 'srsenb': |
| 351 | from .enb_srs import srsENB |
| 352 | enb_class = srsENB |
| 353 | else: |
| 354 | raise log.Error('ENB type not supported:', enb_type) |
Pau Espin Pedrol | a442cb8 | 2020-05-05 12:54:37 +0200 | [diff] [blame] | 355 | return enb_class(testenv, conf) |
Pau Espin Pedrol | 1ee5ec5 | 2020-05-04 17:16:39 +0200 | [diff] [blame] | 356 | |
Pau Espin Pedrol | 786a6bc | 2020-03-30 13:51:21 +0200 | [diff] [blame] | 357 | ################### |
| 358 | # PUBLIC (test API included) |
| 359 | ################### |
| 360 | @abstractmethod |
| 361 | def start(self, epc): |
| 362 | 'Starts ENB, it will connect to "epc"' |
| 363 | pass |
| 364 | |
| 365 | @abstractmethod |
Andre Puschmann | 215bec2 | 2021-01-08 12:34:48 +0100 | [diff] [blame] | 366 | def stop(self): |
| 367 | pass |
| 368 | |
| 369 | @abstractmethod |
Pau Espin Pedrol | 786a6bc | 2020-03-30 13:51:21 +0200 | [diff] [blame] | 370 | def ue_add(self, ue): |
| 371 | pass |
| 372 | |
| 373 | @abstractmethod |
| 374 | def running(self): |
| 375 | pass |
| 376 | |
| 377 | @abstractmethod |
Andre Puschmann | 7d3b83e | 2020-09-02 22:17:54 +0200 | [diff] [blame] | 378 | def ue_max_rate(self, downlink=True, num_carriers=1): |
Pau Espin Pedrol | 786a6bc | 2020-03-30 13:51:21 +0200 | [diff] [blame] | 379 | pass |
| 380 | |
Pau Espin Pedrol | d4404d5 | 2020-04-20 13:29:31 +0200 | [diff] [blame] | 381 | @abstractmethod |
| 382 | def get_rfemu(self, cell=0, dl=True): |
| 383 | 'Get rfemu.RFemulation subclass implementation object for given cell index and direction.' |
| 384 | pass |
| 385 | |
Pau Espin Pedrol | 786a6bc | 2020-03-30 13:51:21 +0200 | [diff] [blame] | 386 | def addr(self): |
Pau Espin Pedrol | 1abff4e | 2020-05-26 12:32:19 +0200 | [diff] [blame] | 387 | return self._run_node.run_addr() |
Pau Espin Pedrol | 786a6bc | 2020-03-30 13:51:21 +0200 | [diff] [blame] | 388 | |
Andre Puschmann | f249a02 | 2021-01-05 14:14:48 +0100 | [diff] [blame] | 389 | @abstractmethod |
| 390 | def get_counter(self, counter_name): |
| 391 | pass |
| 392 | |
Andre Puschmann | 3ce6725 | 2021-01-29 17:45:18 +0100 | [diff] [blame] | 393 | @abstractmethod |
| 394 | def get_kpis(self): |
| 395 | pass |
| 396 | |
| 397 | # vim: expandtab tabstop=4 shiftwidth=4 |