blob: e9767534109c9b8f3b94d3413f0e16d4f4817039 [file] [log] [blame]
Pau Espin Pedrol786a6bc2020-03-30 13:51:21 +02001# 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
20from abc import ABCMeta, abstractmethod
Pau Espin Pedrole1a58bd2020-04-10 20:46:07 +020021from ..core import log, config
Pau Espin Pedrolea8c3d42020-05-04 12:05:05 +020022from ..core import schema
Pau Espin Pedrol1abff4e2020-05-26 12:32:19 +020023from . import run_node
Pau Espin Pedrolfbb86112020-10-16 16:55:23 +020024from .gnuradio_zmq_broker import GrBroker
Pau Espin Pedrol786a6bc2020-03-30 13:51:21 +020025
Pau Espin Pedrolea8c3d42020-05-04 12:05:05 +020026def on_register_schemas():
27 resource_schema = {
28 'label': schema.STR,
29 'type': schema.STR,
Pau Espin Pedrolea8c3d42020-05-04 12:05:05 +020030 'gtp_bind_addr': schema.IPV4,
31 'id': schema.UINT,
32 'num_prb': schema.UINT,
Andre Puschmannd0682ba2020-10-15 15:46:29 +020033 'duplex': schema.STR,
34 'tdd_uldl_config': schema.UINT,
35 'tdd_special_subframe_pattern': schema.UINT,
Pau Espin Pedrolea8c3d42020-05-04 12:05:05 +020036 'transmission_mode': schema.LTE_TRANSMISSION_MODE,
Andre Puschmanna54ca0b2021-04-14 23:24:04 +020037 'rx_ant': schema.STR,
Pau Espin Pedrolea8c3d42020-05-04 12:05:05 +020038 'tx_gain': schema.UINT,
39 'rx_gain': schema.UINT,
40 'rf_dev_type': schema.STR,
41 'rf_dev_args': schema.STR,
Andre Puschmannc489f192020-10-09 14:46:38 +020042 'rf_dev_sync': schema.STR,
Pau Espin Pedrole592de82020-06-15 17:01:16 +020043 'additional_args[]': schema.STR,
Andre Puschmann0cfc0842020-08-26 18:19:15 +020044 'inactivity_timer': schema.INT,
Pau Espin Pedrolea8c3d42020-05-04 12:05:05 +020045 'enable_measurements': schema.BOOL_STR,
Andre Puschmann955249d2020-07-01 15:44:09 +020046 'enable_dl_awgn': schema.BOOL_STR,
47 'dl_awgn_snr': schema.INT,
Nils Fürstea8180152020-12-03 14:14:31 +010048 'cipher_list[]': schema.CIPHER_4G,
49 'integrity_list[]': schema.INTEGRITY_4G,
Pau Espin Pedrolea8c3d42020-05-04 12:05:05 +020050 '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 Puschmann549826d2020-04-21 21:14:30 +020064 'cell_list[].rf_port': schema.UINT,
Pau Espin Pedrolea8c3d42020-05-04 12:05:05 +020065 'cell_list[].pci': schema.UINT,
Pau Espin Pedrolef7256a2020-11-09 18:52:05 +010066 '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 Pedrolea8c3d42020-05-04 12:05:05 +020070 'cell_list[].scell_list[]': schema.UINT,
Andre Puschmann6e081aa2021-05-04 16:56:25 +020071 'cell_list[].nr_scell_list[]': schema.UINT,
Pau Espin Pedrolea8c3d42020-05-04 12:05:05 +020072 'cell_list[].dl_earfcn': schema.UINT,
Andre Puschmanna7fd3942020-11-06 16:24:38 +010073 'cell_list[].root_seq_idx': schema.UINT,
74 'cell_list[].tac': schema.UINT,
Pau Espin Pedrolea8c3d42020-05-04 12:05:05 +020075 'cell_list[].dl_rfemu.type': schema.STR,
76 'cell_list[].dl_rfemu.addr': schema.IPV4,
77 'cell_list[].dl_rfemu.ports[]': schema.UINT,
Andre Puschmann6e081aa2021-05-04 16:56:25 +020078 '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 Pedrolea8c3d42020-05-04 12:05:05 +020083 }
Pau Espin Pedrol1abff4e2020-05-26 12:32:19 +020084 for key, val in run_node.RunNode.schema().items():
85 resource_schema['run_node.%s' % key] = val
Pau Espin Pedrolea8c3d42020-05-04 12:05:05 +020086 schema.register_resource_schema('enb', resource_schema)
Pau Espin Pedrol786a6bc2020-03-30 13:51:21 +020087
88class eNodeB(log.Origin, metaclass=ABCMeta):
89
90##############
91# PROTECTED
92##############
Pau Espin Pedrola442cb82020-05-05 12:54:37 +020093 def __init__(self, testenv, conf, name):
Pau Espin Pedrol786a6bc2020-03-30 13:51:21 +020094 super().__init__(log.C_RUN, '%s' % name)
95 self._conf = conf
Pau Espin Pedrol1abff4e2020-05-26 12:32:19 +020096 self._run_node = run_node.RunNode.from_conf(conf.get('run_node', {}))
Andre Puschmann4b5a09a2020-04-14 22:24:00 +020097 self._gtp_bind_addr = conf.get('gtp_bind_addr', None)
98 if self._gtp_bind_addr is None:
Pau Espin Pedrol1abff4e2020-05-26 12:32:19 +020099 self._gtp_bind_addr = self._run_node.run_addr()
Pau Espin Pedrola2d4e2f2020-10-22 15:46:42 +0200100 label = conf.get('label', None)
Andre Puschmannbfd3fe62020-12-09 21:40:46 +0100101 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 Pedrole44e76a2020-03-31 12:35:19 +0200105 self._txmode = 0
Pau Espin Pedrol491f77c2020-04-20 14:20:43 +0200106 self._id = None
Andre Puschmann6e081aa2021-05-04 16:56:25 +0200107 self._ran_config = "lte" # Used to determine whether we are in NSA
Andre Puschmannd0682ba2020-10-15 15:46:29 +0200108 self._duplex = None
Pau Espin Pedrole44e76a2020-03-31 12:35:19 +0200109 self._num_prb = 0
Pau Espin Pedrolf46ae222020-04-17 16:23:54 +0200110 self._num_cells = None
Andre Puschmann6e081aa2021-05-04 16:56:25 +0200111 self._num_nr_cells = None
Pau Espin Pedrole44e76a2020-03-31 12:35:19 +0200112 self._epc = None
Pau Espin Pedrol41091232020-10-05 19:23:38 +0200113 self.gen_conf = None
Pau Espin Pedrolfbb86112020-10-16 16:55:23 +0200114 self.gr_broker = GrBroker.ref()
115 self.gr_broker.register_enb(self)
116 self._use_gr_broker = False
Pau Espin Pedrol41091232020-10-05 19:23:38 +0200117
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 Puschmann6e081aa2021-05-04 16:56:25 +0200137 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 Pedrol41091232020-10-05 19:23:38 +0200139
140 def calc_required_zmq_ports_joined_earfcn(self, cfg_values):
Andre Puschmann6e081aa2021-05-04 16:56:25 +0200141 #gr_broker will join the earfcns, so we need to count unique earfcns (only implemented for LTE):
Pau Espin Pedrol41091232020-10-05 19:23:38 +0200142 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 Puschmann6e081aa2021-05-04 16:56:25 +0200154 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 Pedrol41091232020-10-05 19:23:38 +0200158 # 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 Pedrole44e76a2020-03-31 12:35:19 +0200167
Pau Espin Pedrolc04528c2020-04-01 13:55:51 +0200168 def configure(self, config_specifics_li):
Pau Espin Pedrole44e76a2020-03-31 12:35:19 +0200169 values = dict(enb=config.get_defaults('enb'))
Pau Espin Pedrolc04528c2020-04-01 13:55:51 +0200170 for config_specifics in config_specifics_li:
171 config.overlay(values, dict(enb=config.get_defaults(config_specifics)))
Pau Espin Pedrola442cb82020-05-05 12:54:37 +0200172 config.overlay(values, dict(enb=self.testenv.suite().config().get('enb', {})))
Pau Espin Pedrolc04528c2020-04-01 13:55:51 +0200173 for config_specifics in config_specifics_li:
Pau Espin Pedrola442cb82020-05-05 12:54:37 +0200174 config.overlay(values, dict(enb=self.testenv.suite().config().get(config_specifics, {})))
Pau Espin Pedrole44e76a2020-03-31 12:35:19 +0200175 config.overlay(values, dict(enb=self._conf))
Pau Espin Pedrol491f77c2020-04-20 14:20:43 +0200176 self._id = int(values['enb'].get('id', None))
177 assert self._id is not None
Andre Puschmannd0682ba2020-10-15 15:46:29 +0200178 self._duplex = values['enb'].get('duplex', None)
179 assert self._duplex
Pau Espin Pedrole44e76a2020-03-31 12:35:19 +0200180 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 Puschmann0cfc0842020-08-26 18:19:15 +0200185 self._inactivity_timer = int(values['enb'].get('inactivity_timer', None))
186 assert self._inactivity_timer
Pau Espin Pedrole44e76a2020-03-31 12:35:19 +0200187 assert self._epc is not None
Pau Espin Pedrol1abff4e2020-05-26 12:32:19 +0200188 config.overlay(values, dict(enb={ 'addr': self.addr() }))
Pau Espin Pedrole44e76a2020-03-31 12:35:19 +0200189 config.overlay(values, dict(enb={ 'mme_addr': self._epc.addr() }))
Andre Puschmann4b5a09a2020-04-14 22:24:00 +0200190 config.overlay(values, dict(enb={ 'gtp_bind_addr': self._gtp_bind_addr }))
Pau Espin Pedrolf46ae222020-04-17 16:23:54 +0200191 self._num_cells = int(values['enb'].get('num_cells', None))
Andre Puschmann6e081aa2021-05-04 16:56:25 +0200192 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 Pedrolf46ae222020-04-17 16:23:54 +0200195
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 Pedrol41091232020-10-05 19:23:38 +0200212 # 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 Pedrolfbb86112020-10-16 16:55:23 +0200221 self._use_gr_broker = self.using_grbroker(values)
222 if self._use_gr_broker:
Pau Espin Pedrol41091232020-10-05 19:23:38 +0200223 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 Pedrolfbb86112020-10-16 16:55:23 +0200230 self.gr_broker.start()
Pau Espin Pedrol41091232020-10-05 19:23:38 +0200231 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 Pedrole44e76a2020-03-31 12:35:19 +0200236 return values
237
Pau Espin Pedrol491f77c2020-04-20 14:20:43 +0200238 def id(self):
239 return self._id
240
Pau Espin Pedrole44e76a2020-03-31 12:35:19 +0200241 def num_ports(self):
242 if self._txmode == 1:
243 return 1
244 return 2
Pau Espin Pedrol786a6bc2020-03-30 13:51:21 +0200245
Andre Puschmann0957e9e2020-06-16 16:29:27 +0200246 def num_cells(self):
247 return self._num_cells
248
Andre Puschmann6e081aa2021-05-04 16:56:25 +0200249 def num_nr_cells(self):
250 return self._num_nr_cells
251
Pau Espin Pedrol786a6bc2020-03-30 13:51:21 +0200252########################
253# PUBLIC - INTERNAL API
254########################
255 def cleanup(self):
256 'Nothing to do by default. Subclass can override if required.'
Pau Espin Pedrol41091232020-10-05 19:23:38 +0200257 if self.gr_broker:
Pau Espin Pedrolfbb86112020-10-16 16:55:23 +0200258 self.gr_broker.unregister_enb(self)
Pau Espin Pedrol41091232020-10-05 19:23:38 +0200259 GrBroker.unref()
260 self.gr_broker = None
Pau Espin Pedrol786a6bc2020-03-30 13:51:21 +0200261
Pau Espin Pedrole44e76a2020-03-31 12:35:19 +0200262 def num_prb(self):
263 return self._num_prb
264
Andre Puschmanne2a6da62020-04-20 20:39:34 +0200265 #reference: srsLTE.git srslte_symbol_sz()
266 def num_prb2symbol_sz(self, num_prb):
Andre Puschmann0a501102020-06-02 22:35:27 +0200267 if num_prb == 6:
Andre Puschmanne2a6da62020-04-20 20:39:34 +0200268 return 128
Andre Puschmann0a501102020-06-02 22:35:27 +0200269 if num_prb == 50:
Andre Puschmanne2a6da62020-04-20 20:39:34 +0200270 return 768
Andre Puschmann0a501102020-06-02 22:35:27 +0200271 if num_prb == 75:
Andre Puschmanne2a6da62020-04-20 20:39:34 +0200272 return 1024
Andre Puschmann0a501102020-06-02 22:35:27 +0200273 return 1536
274
Andre Puschmanne2a6da62020-04-20 20:39:34 +0200275 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 Pedrol41091232020-10-05 19:23:38 +0200280 def get_zmq_rf_dev_args(self, cfg_values):
Andre Puschmanne2a6da62020-04-20 20:39:34 +0200281 base_srate = self.num_prb2base_srate(self.num_prb())
Pau Espin Pedrol41091232020-10-05 19:23:38 +0200282
Pau Espin Pedrolfbb86112020-10-16 16:55:23 +0200283 if self._use_gr_broker:
Pau Espin Pedrol4acb45a2020-10-23 13:51:03 +0200284 ul_rem_addr = self.gr_broker.addr()
Pau Espin Pedrol41091232020-10-05 19:23:38 +0200285 else:
286 ul_rem_addr = self.ue.addr()
287
Andre Puschmannf69b9482021-03-14 15:38:58 +0100288 rf_dev_args = 'fail_on_disconnect=true,log_trx_timeout=true,trx_timeout_ms=8000'
Pau Espin Pedrol41091232020-10-05 19:23:38 +0200289 idx = 0
290 cell_list = cfg_values['enb']['cell_list']
Andre Puschmanne2a6da62020-04-20 20:39:34 +0200291 # Define all 8 possible RF ports (2x CA with 2x2 MIMO)
Pau Espin Pedrol41091232020-10-05 19:23:38 +0200292 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 Puschmanne2a6da62020-04-20 20:39:34 +0200300
Andre Puschmann6e081aa2021-05-04 16:56:25 +0200301 # 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 Puschmanne2a6da62020-04-20 20:39:34 +0200308 rf_dev_args += ',id=enb,base_srate=' + str(base_srate)
Pau Espin Pedrol41091232020-10-05 19:23:38 +0200309 return rf_dev_args
Andre Puschmanne2a6da62020-04-20 20:39:34 +0200310
Pau Espin Pedrol41091232020-10-05 19:23:38 +0200311 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 Pedrolfbb86112020-10-16 16:55:23 +0200317 if self._use_gr_broker:
Pau Espin Pedrol41091232020-10-05 19:23:38 +0200318 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 Puschmann6e081aa2021-05-04 16:56:25 +0200328
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 Pedrol41091232020-10-05 19:23:38 +0200336 # remove trailing comma:
337 if rf_dev_args[0] == ',':
338 return rf_dev_args[1:]
Andre Puschmanne2a6da62020-04-20 20:39:34 +0200339 return rf_dev_args
340
Pau Espin Pedrola442cb82020-05-05 12:54:37 +0200341 def get_instance_by_type(testenv, conf):
Pau Espin Pedrol1ee5ec52020-05-04 17:16:39 +0200342 """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 Pedrola442cb82020-05-05 12:54:37 +0200355 return enb_class(testenv, conf)
Pau Espin Pedrol1ee5ec52020-05-04 17:16:39 +0200356
Pau Espin Pedrol786a6bc2020-03-30 13:51:21 +0200357###################
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 Puschmann215bec22021-01-08 12:34:48 +0100366 def stop(self):
367 pass
368
369 @abstractmethod
Pau Espin Pedrol786a6bc2020-03-30 13:51:21 +0200370 def ue_add(self, ue):
371 pass
372
373 @abstractmethod
374 def running(self):
375 pass
376
377 @abstractmethod
Andre Puschmann7d3b83e2020-09-02 22:17:54 +0200378 def ue_max_rate(self, downlink=True, num_carriers=1):
Pau Espin Pedrol786a6bc2020-03-30 13:51:21 +0200379 pass
380
Pau Espin Pedrold4404d52020-04-20 13:29:31 +0200381 @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 Pedrol786a6bc2020-03-30 13:51:21 +0200386 def addr(self):
Pau Espin Pedrol1abff4e2020-05-26 12:32:19 +0200387 return self._run_node.run_addr()
Pau Espin Pedrol786a6bc2020-03-30 13:51:21 +0200388
Andre Puschmannf249a022021-01-05 14:14:48 +0100389 @abstractmethod
390 def get_counter(self, counter_name):
391 pass
392
Andre Puschmann3ce67252021-01-29 17:45:18 +0100393 @abstractmethod
394 def get_kpis(self):
395 pass
396
397# vim: expandtab tabstop=4 shiftwidth=4