From 786a6bcd2099462e94b4335d952f2032f3c2e0e2 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Mon, 30 Mar 2020 13:51:21 +0200 Subject: [PATCH] Introduce initial Amarisoft ENB support * object class expects the amarisoft software to be placed in directory provided by env var AMARISOFT_PATH_ENB. On local runs, it will run the software from there. On remote runs it will copy over that directory to the slave. * Configuration provided works with 6 PRBs, but probably won't work for other values (yet). * ZMQ support not yet available, only UHD. One can select the Amarisoft ENB by declaring it in resources.conf: """ - label: AmarisoftENB-B200 type: amarisoftenb rf_dev_type: uhd rf_dev_args: "type=b200,serial=317B9FE,recv_frame_size=9232,send_frame_size=9232" remote_user: jenkins addr: 10.12.1.206 """ And running: """ $ export AMARISOFT_PATH_ENB=/path/to/binaries $ osmo-gsm-tester.py ... -s 4g:amarisoftenb-rftype@uhd+srsue-rftype@UHD+mod-enb-nprb@6 -t ping """ Change-Id: I1ddf4962ea6438ad977382ab201b724028ca46b3 --- example/defaults.conf | 13 +- example/scenarios/amarisoftenb-rftype@.conf | 4 + src/osmo_gsm_tester/amarisoft_enb.py | 242 ++++++++++++ src/osmo_gsm_tester/enb.py | 67 ++++ src/osmo_gsm_tester/resource.py | 3 +- src/osmo_gsm_tester/srs_enb.py | 16 +- .../templates/amarisoft_drb.cfg.tmpl | 364 ++++++++++++++++++ .../templates/amarisoft_enb.cfg.tmpl | 192 +++++++++ .../templates/amarisoft_rf_driver.cfg.tmpl | 20 + .../templates/amarisoft_sib1.asn.tmpl | 42 ++ .../templates/amarisoft_sib23.asn.tmpl | 116 ++++++ suites/4g/suite.conf | 1 - 12 files changed, 1064 insertions(+), 16 deletions(-) create mode 100644 example/scenarios/amarisoftenb-rftype@.conf create mode 100644 src/osmo_gsm_tester/amarisoft_enb.py create mode 100644 src/osmo_gsm_tester/enb.py create mode 100644 src/osmo_gsm_tester/templates/amarisoft_drb.cfg.tmpl create mode 100644 src/osmo_gsm_tester/templates/amarisoft_enb.cfg.tmpl create mode 100644 src/osmo_gsm_tester/templates/amarisoft_rf_driver.cfg.tmpl create mode 100644 src/osmo_gsm_tester/templates/amarisoft_sib1.asn.tmpl create mode 100644 src/osmo_gsm_tester/templates/amarisoft_sib23.asn.tmpl diff --git a/example/defaults.conf b/example/defaults.conf index 2708b180..bcd1fa23 100644 --- a/example/defaults.conf +++ b/example/defaults.conf @@ -99,14 +99,21 @@ srsepc: rlc_drb_mode: UM enable_pcap: false -srsenb: +enb: mcc: 901 mnc: 70 - num_prb: 100 transmission_mode: 1 - enable_pcap: false num_cells: 1 +srsenb: + num_prb: 100 + enable_pcap: false + +amarisoftenb: + license_server_addr: 10.12.1.139 + num_prb: 100 + enable_pcap: false + srsue: enable_pcap: false airplane_t_on_ms: -1 diff --git a/example/scenarios/amarisoftenb-rftype@.conf b/example/scenarios/amarisoftenb-rftype@.conf new file mode 100644 index 00000000..137458a7 --- /dev/null +++ b/example/scenarios/amarisoftenb-rftype@.conf @@ -0,0 +1,4 @@ +resources: + enb: + - type: amarisoftenb + rf_dev_type: ${param1} diff --git a/src/osmo_gsm_tester/amarisoft_enb.py b/src/osmo_gsm_tester/amarisoft_enb.py new file mode 100644 index 00000000..e16fe7f4 --- /dev/null +++ b/src/osmo_gsm_tester/amarisoft_enb.py @@ -0,0 +1,242 @@ +# osmo_gsm_tester: specifics for running an SRS eNodeB process +# +# Copyright (C) 2020 by sysmocom - s.f.m.c. GmbH +# +# Author: Pau Espin Pedrol +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import os +import pprint + +from . import log, util, config, template, process, remote +from . import enb + +def rf_type_valid(rf_type_str): + return rf_type_str in ('uhd') + +#reference: srsLTE.git srslte_symbol_sz() +def num_prb2symbol_sz(num_prb): + if num_prb <= 6: + return 128 + if num_prb <= 15: + return 256 + if num_prb <= 25: + return 384 + if num_prb <= 50: + return 768 + if num_prb <= 75: + return 1024 + if num_prb <= 110: + return 1536 + raise log.Error('invalid num_prb %r', num_prb) + +def num_prb2base_srate(num_prb): + return num_prb2symbol_sz(num_prb) * 15 * 1000 + +class AmarisoftENB(enb.eNodeB): + + REMOTE_DIR = '/osmo-gsm-tester-amarisoftenb' + BINFILE = 'lteenb' + CFGFILE = 'amarisoft_enb.cfg' + CFGFILE_SIB1 = 'amarisoft_sib1.asn' + CFGFILE_SIB23 = 'amarisoft_sib23.asn' + CFGFILE_RF = 'amarisoft_rf_driver.cfg' + CFGFILE_DRB = 'amarisoft_drb.cfg' + LOGFILE = 'lteenb.log' + + def __init__(self, suite_run, conf): + super().__init__(suite_run, conf, 'amarisoftenb') + self.ue = None + self.epc = None + self.run_dir = None + self._bin_prefix = None + self.config_file = None + self.config_sib1_file = None + self.config_sib23_file = None + self.config_rf_file = None + self.config_drb_file = None + self.log_file = None + self.process = None + self.rem_host = None + self.remote_config_file = None + self.remote_config_sib1_file = None + self.remote_config_sib23_file = None + self.remote_config_rf_file = None + self.remote_config_drb_file = None + self.remote_log_file = None + self._num_prb = 0 + self._txmode = 0 + self.suite_run = suite_run + self.remote_user = conf.get('remote_user', None) + if not rf_type_valid(conf.get('rf_dev_type', None)): + raise log.Error('Invalid rf_dev_type=%s' % conf.get('rf_dev_type', None)) + + def bin_prefix(self): + if self._bin_prefix is None: + self._bin_prefix = os.getenv('AMARISOFT_PATH_ENB', AmarisoftENB.REMOTE_DIR) + return self._bin_prefix + + def cleanup(self): + if self.process is None: + return + if self.setup_runs_locally(): + return + # copy back files (may not exist, for instance if there was an early error of process): + try: + self.rem_host.scpfrom('scp-back-log', self.remote_log_file, self.log_file) + except Exception as e: + self.log(repr(e)) + + + def setup_runs_locally(self): + return self.remote_user is None + + def start(self, epc): + self.log('Starting AmarisoftENB') + self.epc = epc + self.run_dir = util.Dir(self.suite_run.get_test_run_dir().new_dir(self.name())) + self.configure() + self._start() + + # send t+Enter to enable console trace + self.dbg('Enabling console trace') + self.process.stdin_write('t\n') + + def _start(self): + if self.setup_runs_locally(): + env = { 'LD_LIBRARY_PATH': util.prepend_library_path(self.inst) } + binary = self.inst.child('.', AmarisoftENB.BINFILE) + self.dbg(run_dir=self.run_dir, binary=binary, env=env) + args = (binary, os.path.abspath(self.config_file)) + self.process = process.Process(self.name(), self.run_dir, args, env=env) + else: + remote_env = { 'LD_LIBRARY_PATH': self.remote_inst } + remote_binary = self.remote_inst.child('', AmarisoftENB.BINFILE) + args = (remote_binary, self.remote_config_file) + self.process = self.rem_host.RemoteProcess(AmarisoftENB.BINFILE, args, remote_env=remote_env) + + self.suite_run.remember_to_stop(self.process) + self.process.launch() + + def gen_conf_file(self, path, filename, values): + self.dbg('AmarisoftENB ' + filename + ':\n' + pprint.pformat(values)) + with open(path, 'w') as f: + r = template.render(filename, values) + self.dbg(r) + f.write(r) + + def configure(self): + + self.inst = util.Dir(os.path.abspath(self.bin_prefix())) + lib = self.inst.child('lib') + if not self.inst.isfile('', AmarisoftENB.BINFILE): + raise log.Error('No %s binary in' % AmarisoftENB.BINFILE, self.inst) + + self.config_file = self.run_dir.child(AmarisoftENB.CFGFILE) + self.config_sib1_file = self.run_dir.child(AmarisoftENB.CFGFILE_SIB1) + self.config_sib23_file = self.run_dir.child(AmarisoftENB.CFGFILE_SIB23) + self.config_rf_file = self.run_dir.child(AmarisoftENB.CFGFILE_RF) + self.config_drb_file = self.run_dir.child(AmarisoftENB.CFGFILE_DRB) + self.log_file = self.run_dir.child(AmarisoftENB.LOGFILE) + + if not self.setup_runs_locally(): + self.rem_host = remote.RemoteHost(self.run_dir, self.remote_user, self._addr) + remote_prefix_dir = util.Dir(AmarisoftENB.REMOTE_DIR) + self.remote_inst = util.Dir(remote_prefix_dir.child(os.path.basename(str(self.inst)))) + remote_run_dir = util.Dir(remote_prefix_dir.child(AmarisoftENB.BINFILE)) + + self.remote_config_file = remote_run_dir.child(AmarisoftENB.CFGFILE) + self.remote_config_sib1_file = remote_run_dir.child(AmarisoftENB.CFGFILE_SIB1) + self.remote_config_sib23_file = remote_run_dir.child(AmarisoftENB.CFGFILE_SIB23) + self.remote_config_rf_file = remote_run_dir.child(AmarisoftENB.CFGFILE_RF) + self.remote_config_drb_file = remote_run_dir.child(AmarisoftENB.CFGFILE_DRB) + self.remote_log_file = remote_run_dir.child(AmarisoftENB.LOGFILE) + + values = dict(enb=config.get_defaults('enb')) + config.overlay(values, dict(enb=config.get_defaults('amarisoftenb'))) + config.overlay(values, dict(enb=self.suite_run.config().get('enb', {}))) + config.overlay(values, dict(enb=self._conf)) + config.overlay(values, dict(enb={ 'mme_addr': self.epc.addr() })) + + self._num_prb = int(values['enb'].get('num_prb', None)) + assert self._num_prb + self._txmode = int(values['enb'].get('transmission_mode', None)) + assert self._txmode + self._num_cells = int(values['enb'].get('num_cells', None)) + assert self._num_cells + config.overlay(values, dict(enb={ 'num_ports': self.num_ports() })) + + logfile = self.log_file if self.setup_runs_locally() else self.remote_log_file + config.overlay(values, dict(enb=dict(log_filename=logfile))) + + self.gen_conf_file(self.config_file, AmarisoftENB.CFGFILE, values) + self.gen_conf_file(self.config_sib1_file, AmarisoftENB.CFGFILE_SIB1, values) + self.gen_conf_file(self.config_sib23_file, AmarisoftENB.CFGFILE_SIB23, values) + self.gen_conf_file(self.config_rf_file, AmarisoftENB.CFGFILE_RF, values) + self.gen_conf_file(self.config_drb_file, AmarisoftENB.CFGFILE_DRB, values) + + if not self.setup_runs_locally(): + self.rem_host.recreate_remote_dir(self.remote_inst) + self.rem_host.scp('scp-inst-to-remote', str(self.inst), remote_prefix_dir) + self.rem_host.recreate_remote_dir(remote_run_dir) + self.rem_host.scp('scp-cfg-to-remote', self.config_file, self.remote_config_file) + self.rem_host.scp('scp-cfg-sib1-to-remote', self.config_sib1_file, self.remote_config_sib1_file) + self.rem_host.scp('scp-cfg-sib23-to-remote', self.config_sib23_file, self.remote_config_sib23_file) + self.rem_host.scp('scp-cfg-rr-to-remote', self.config_rf_file, self.remote_config_rf_file) + self.rem_host.scp('scp-cfg-drb-to-remote', self.config_drb_file, self.remote_config_drb_file) + + def ue_add(self, ue): + if self.ue is not None: + raise log.Error("More than one UE per ENB not yet supported (ZeroMQ)") + self.ue = ue + + def running(self): + return not self.process.terminated() + + def num_prb(self): + return self._num_prb + + def num_ports(self): + if self._txmode == 1: + return 1 + return 2 + + def ue_max_rate(self, downlink=True): + # The max rate for a single UE per PRB configuration in TM1 + max_phy_rate_tm1_dl = { 6 : 3.5e6, + 15 : 11e6, + 25 : 18e6, + 50 : 36e6, + 75 : 55e6, + 100 : 75e6 } + max_phy_rate_tm1_ul = { 6 : 0.9e6, + 15 : 4.7e6, + 25 : 10e6, + 50 : 23e6, + 75 : 34e6, + 100 : 51e6 } + if downlink: + max_rate = max_phy_rate_tm1_dl[self.num_prb()] + else: + max_rate = max_phy_rate_tm1_ul[self.num_prb()] + #TODO: calculate for non-standard prb numbers. + if self._txmode > 2: + max_rate *= 2 + # We use 3 control symbols for 6, 15 and 25 PRBs which results in lower max rate + if self.num_prb() < 50: + max_rate *= 0.9 + return max_rate + +# vim: expandtab tabstop=4 shiftwidth=4 diff --git a/src/osmo_gsm_tester/enb.py b/src/osmo_gsm_tester/enb.py new file mode 100644 index 00000000..f6b77225 --- /dev/null +++ b/src/osmo_gsm_tester/enb.py @@ -0,0 +1,67 @@ +# osmo_gsm_tester: base classes to share code among eNodeB subclasses. +# +# Copyright (C) 2020 by sysmocom - s.f.m.c. GmbH +# +# Author: Pau Espin Pedrol +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from abc import ABCMeta, abstractmethod +from . import log + + +class eNodeB(log.Origin, metaclass=ABCMeta): + +############## +# PROTECTED +############## + def __init__(self, suite_run, conf, name): + super().__init__(log.C_RUN, '%s' % name) + self._conf = conf + self._addr = conf.get('addr', None) + if self._addr is None: + raise log.Error('addr not set') + self.set_name('%s_%s' % (name, self._addr)) + +######################## +# PUBLIC - INTERNAL API +######################## + def cleanup(self): + 'Nothing to do by default. Subclass can override if required.' + pass + +################### +# PUBLIC (test API included) +################### + @abstractmethod + def start(self, epc): + 'Starts ENB, it will connect to "epc"' + pass + + @abstractmethod + def ue_add(self, ue): + pass + + @abstractmethod + def running(self): + pass + + @abstractmethod + def ue_max_rate(self, downlink=True): + pass + + def addr(self): + return self._addr + +# vim: expandtab tabstop=4 shiftwidth=4 diff --git a/src/osmo_gsm_tester/resource.py b/src/osmo_gsm_tester/resource.py index bb44f39e..d14ee969 100644 --- a/src/osmo_gsm_tester/resource.py +++ b/src/osmo_gsm_tester/resource.py @@ -29,7 +29,7 @@ from . import schema from . import bts_sysmo, bts_osmotrx, bts_osmovirtual, bts_octphy, bts_nanobts, bts_oc2g from . import modem from . import ms_osmo_mobile -from . import srs_ue, srs_enb +from . import srs_ue, srs_enb, amarisoft_enb from .util import is_dict, is_list @@ -140,6 +140,7 @@ KNOWN_BTS_TYPES = { KNOWN_ENB_TYPES = { 'srsenb': srs_enb.srsENB, + 'amarisoftenb': amarisoft_enb.AmarisoftENB, } KNOWN_MS_TYPES = { diff --git a/src/osmo_gsm_tester/srs_enb.py b/src/osmo_gsm_tester/srs_enb.py index 772b447e..f5d3fdf7 100644 --- a/src/osmo_gsm_tester/srs_enb.py +++ b/src/osmo_gsm_tester/srs_enb.py @@ -21,6 +21,7 @@ import os import pprint from . import log, util, config, template, process, remote +from . import enb def rf_type_valid(rf_type_str): return rf_type_str in ('zmq', 'UHD', 'soapy', 'bladeRF') @@ -44,7 +45,7 @@ def num_prb2symbol_sz(num_prb): def num_prb2base_srate(num_prb): return num_prb2symbol_sz(num_prb) * 15 * 1000 -class srsENB(log.Origin): +class srsENB(enb.eNodeB): REMOTE_DIR = '/osmo-gsm-tester-srsenb' BINFILE = 'srsenb' @@ -56,12 +57,7 @@ class srsENB(log.Origin): PCAPFILE = 'srsenb.pcap' def __init__(self, suite_run, conf): - super().__init__(log.C_RUN, 'srsenb') - self._conf = conf - self._addr = conf.get('addr', None) - if self._addr is None: - raise log.Error('addr not set') - self.set_name('srsenb_%s' % self._addr) + super().__init__(suite_run, conf, srsENB.BINFILE) self.ue = None self.epc = None self.run_dir = None @@ -188,7 +184,8 @@ class srsENB(log.Origin): def gen_conf_file(self, path, filename): self.dbg(config_file=path) - values = dict(enb=config.get_defaults('srsenb')) + values = dict(enb=config.get_defaults('enb')) + config.overlay(values, dict(enb=config.get_defaults('srsenb'))) config.overlay(values, dict(enb=self.suite_run.config().get('enb', {}))) config.overlay(values, dict(enb=self._conf)) config.overlay(values, dict(enb={ 'mme_addr': self.epc.addr() })) @@ -245,9 +242,6 @@ class srsENB(log.Origin): def running(self): return not self.process.terminated() - def addr(self): - return self._addr - def num_prb(self): return self._num_prb diff --git a/src/osmo_gsm_tester/templates/amarisoft_drb.cfg.tmpl b/src/osmo_gsm_tester/templates/amarisoft_drb.cfg.tmpl new file mode 100644 index 00000000..a2000631 --- /dev/null +++ b/src/osmo_gsm_tester/templates/amarisoft_drb.cfg.tmpl @@ -0,0 +1,364 @@ +/* DRB configuration for each QCI value. If no corresponding QCI is + found, QCI = 9 is used instead. + QCI characteristics in TS 23.203 table 6.1.7 */ +[ + /**************************************** GBR */ + { + qci: 1, /* UM - real time (RTP for VOIP) */ + pdcp_config: { + discardTimer: 100, /* in ms, 0 means infinity */ + pdcp_SN_Size: 7, + /* ROHC header compression */ + /* + headerCompression: { + maxCID: 15, + profile0x0001: true, // RTP profile + profile0x0002: true, // UDP profile + profile0x0004: false, // IP profile + }, + */ + }, + rlc_config: { + ul_um: { + sn_FieldLength: 5, + }, + dl_um: { + sn_FieldLength: 5, + t_Reordering: 45, /* should be > to max_harq_tx * HARQ latency */ + }, + }, + logical_channel_config: { + /* Note: SRB1 has priority 1, SRB2 has priority 3. + We start from 4 for priority 0.5 and increase the value */ + priority: 7, + prioritisedBitRate: 0, /* in kb/s, -1 means infinity */ + bucketSizeDuration: 100, /* in ms */ + logicalChannelGroup: 1, + logicalChannelSR_Mask: false, + logicalChannelSR_Prohibit: false, + }, + }, + { + qci: 2, /* UM - real time (video) */ + pdcp_config: { + discardTimer: 150, /* in ms, 0 means infinity */ + pdcp_SN_Size: 12, + }, + rlc_config: { + ul_um: { + sn_FieldLength: 10, + }, + dl_um: { + sn_FieldLength: 10, + t_Reordering: 45, /* should be > to max_harq_tx * HARQ latency */ + }, + }, + logical_channel_config: { + priority: 9, + prioritisedBitRate: 0, /* in kb/s, -1 means infinity */ + bucketSizeDuration: 100, /* in ms */ + logicalChannelGroup: 1, + logicalChannelSR_Mask: false, + logicalChannelSR_Prohibit: false, + }, + }, + { + qci: 3, /* UM - real time (gaming) */ + pdcp_config: { + discardTimer: 100, /* in ms, 0 means infinity */ + pdcp_SN_Size: 12, + }, + rlc_config: { + ul_um: { + sn_FieldLength: 10, + }, + dl_um: { + sn_FieldLength: 10, + t_Reordering: 45, /* should be > to max_harq_tx * HARQ latency */ + }, + }, + logical_channel_config: { + priority: 8, + prioritisedBitRate: 0, /* in kb/s, -1 means infinity */ + bucketSizeDuration: 100, /* in ms */ + logicalChannelGroup: 1, + logicalChannelSR_Mask: false, + logicalChannelSR_Prohibit: false, + }, + }, + { + qci: 4, /* AM - Non-Conversational Video (Buffered Streaming) */ + pdcp_config: { + discardTimer: 0, /* in ms, 0 means infinity */ + statusReportRequired: true, + }, + rlc_config: { + ul_am: { + t_PollRetransmit: 80, /* in ms */ + pollPDU: 64, + pollByte: 125, /* in kBytes, 0 means infinity */ + maxRetxThreshold: 32, + }, + dl_am: { + t_Reordering: 45, /* in ms, should be > to max_harq_tx * HARQ latency */ + t_StatusProhibit: 60, /* in ms */ + }, + }, + logical_channel_config: { + priority: 10, + prioritisedBitRate: 8, /* in kb/s, -1 means infinity */ + bucketSizeDuration: 100, /* in ms */ + logicalChannelGroup: 1, + logicalChannelSR_Mask: false, + logicalChannelSR_Prohibit: false, + }, + }, + { + qci: 65, /* UM - real time (MC-PTT voice) */ + pdcp_config: { + discardTimer: 100, /* in ms, 0 means infinity */ + pdcp_SN_Size: 7, + /* ROHC header compression */ + /* + headerCompression: { + maxCID: 15, + profile0x0001: true, // RTP profile + profile0x0002: true, // UDP profile + profile0x0004: false, // IP profile + }, + */ + }, + rlc_config: { + ul_um: { + sn_FieldLength: 5, + }, + dl_um: { + sn_FieldLength: 5, + t_Reordering: 45, /* should be > to max_harq_tx * HARQ latency */ + }, + }, + logical_channel_config: { + /* Note: SRB1 has priority 1, SRB2 has priority 3. We add an + offset of 4 to the standard priorities */ + priority: 5, + prioritisedBitRate: 0, /* in kb/s, -1 means infinity */ + bucketSizeDuration: 100, /* in ms */ + logicalChannelGroup: 1, + logicalChannelSR_Mask: false, + logicalChannelSR_Prohibit: false, + }, + }, + { + qci: 66, /* UM - real time (non MC-PTT voice) */ + pdcp_config: { + discardTimer: 150, /* in ms, 0 means infinity */ + pdcp_SN_Size: 12, + }, + rlc_config: { + ul_um: { + sn_FieldLength: 10, + }, + dl_um: { + sn_FieldLength: 10, + t_Reordering: 45, /* should be > to max_harq_tx * HARQ latency */ + }, + }, + logical_channel_config: { + /* Note: SRB1 has priority 1, SRB2 has priority 3. + We start from 4 for priority 0.5, ... */ + priority: 7, + prioritisedBitRate: 0, /* in kb/s, -1 means infinity */ + bucketSizeDuration: 100, /* in ms */ + logicalChannelGroup: 1, + logicalChannelSR_Mask: false, + logicalChannelSR_Prohibit: false, + }, + }, + /**************************************** non GBR */ + { + qci: 5, /* AM - high priority (SIP) */ + pdcp_config: { + discardTimer: 0, /* in ms, 0 means infinity */ + statusReportRequired: true, + }, + rlc_config: { + ul_am: { + t_PollRetransmit: 80, /* in ms */ + pollPDU: 64, + pollByte: 125, /* in kBytes, 0 means infinity */ + maxRetxThreshold: 32, + }, + dl_am: { + t_Reordering: 45, /* in ms, should be > to max_harq_tx * HARQ latency */ + t_StatusProhibit: 60, /* in ms */ + }, + }, + logical_channel_config: { + priority: 6, + prioritisedBitRate: 8, /* in kb/s, -1 means infinity */ + bucketSizeDuration: 100, /* in ms */ + logicalChannelGroup: 1, + logicalChannelSR_Mask: false, + logicalChannelSR_Prohibit: false, + }, + }, + { + qci: 6, /* AM - Video (buffered streaming) */ + pdcp_config: { + discardTimer: 0, /* in ms, 0 means infinity */ + statusReportRequired: true, + }, + rlc_config: { + ul_am: { + t_PollRetransmit: 80, /* in ms */ + pollPDU: 64, + pollByte: 125, /* in kBytes, 0 means infinity */ + maxRetxThreshold: 32, + }, + dl_am: { + t_Reordering: 45, /* in ms, should be > to max_harq_tx * HARQ latency */ + t_StatusProhibit: 60, /* in ms */ + }, + }, + logical_channel_config: { + priority: 12, + prioritisedBitRate: 8, /* in kb/s, -1 means infinity */ + bucketSizeDuration: 100, /* in ms */ + logicalChannelGroup: 2, + logicalChannelSR_Mask: false, + logicalChannelSR_Prohibit: false, + }, + }, + { + qci: 7, /* UM - voice, video (live streaming), interactive gaming */ + pdcp_config: { + discardTimer: 100, /* in ms, 0 means infinity */ + pdcp_SN_Size: 12, + }, + rlc_config: { + ul_um: { + sn_FieldLength: 10, + }, + dl_um: { + sn_FieldLength: 10, + t_Reordering: 45, /* should be > to max_harq_tx * HARQ latency */ + }, + }, + logical_channel_config: { + priority: 13, + prioritisedBitRate: 0, /* in kb/s, -1 means infinity */ + bucketSizeDuration: 100, /* in ms */ + logicalChannelGroup: 2, + logicalChannelSR_Mask: false, + logicalChannelSR_Prohibit: false, + }, + }, + { + qci: 8, /* AM - best effort (Internet traffic) */ + pdcp_config: { + discardTimer: 0, /* in ms, 0 means infinity */ + statusReportRequired: true, + }, + rlc_config: { + ul_am: { + t_PollRetransmit: 80, /* in ms */ + pollPDU: 64, + pollByte: 125, /* in kBytes, 0 means infinity */ + maxRetxThreshold: 32, + }, + dl_am: { + t_Reordering: 45, /* in ms, should be > to max_harq_tx * HARQ latency */ + t_StatusProhibit: 60, /* in ms */ + }, + }, + logical_channel_config: { + priority: 14, + prioritisedBitRate: 8, /* in kb/s, -1 means infinity */ + bucketSizeDuration: 100, /* in ms */ + logicalChannelGroup: 2, + logicalChannelSR_Mask: false, + logicalChannelSR_Prohibit: false, + }, + }, + { + qci: 9, /* AM - best effort (Internet traffic) */ + pdcp_config: { + discardTimer: 0, /* in ms, 0 means infinity */ + statusReportRequired: true, + }, + rlc_config: { + ul_am: { + t_PollRetransmit: 80, /* in ms */ + pollPDU: 64, + pollByte: 125, /* in kBytes, 0 means infinity */ + maxRetxThreshold: 32, + }, + dl_am: { + t_Reordering: 45, /* in ms, should be > to max_harq_tx * HARQ latency */ + t_StatusProhibit: 60, /* in ms */ + }, + }, + logical_channel_config: { + priority: 15, + prioritisedBitRate: 8, /* in kb/s, -1 means infinity */ + bucketSizeDuration: 100, /* in ms */ + logicalChannelGroup: 3, + logicalChannelSR_Mask: false, + logicalChannelSR_Prohibit: false, + }, + }, + { + qci: 69, /* AM - high priority (MC-PTT signalling) */ + pdcp_config: { + discardTimer: 0, /* in ms, 0 means infinity */ + statusReportRequired: true, + }, + rlc_config: { + ul_am: { + t_PollRetransmit: 80, /* in ms */ + pollPDU: 64, + pollByte: 125, /* in kBytes, 0 means infinity */ + maxRetxThreshold: 32, + }, + dl_am: { + t_Reordering: 45, /* in ms, should be > to max_harq_tx * HARQ latency */ + t_StatusProhibit: 60, /* in ms */ + }, + }, + logical_channel_config: { + priority: 4, + prioritisedBitRate: 8, /* in kb/s, -1 means infinity */ + bucketSizeDuration: 100, /* in ms */ + logicalChannelGroup: 1, + logicalChannelSR_Mask: false, + logicalChannelSR_Prohibit: false, + }, + }, + { + qci: 70, /* AM - MC data */ + pdcp_config: { + discardTimer: 0, /* in ms, 0 means infinity */ + statusReportRequired: true, + }, + rlc_config: { + ul_am: { + t_PollRetransmit: 80, /* in ms */ + pollPDU: 64, + pollByte: 125, /* in kBytes, 0 means infinity */ + maxRetxThreshold: 32, + }, + dl_am: { + t_Reordering: 45, /* in ms, should be > to max_harq_tx * HARQ latency */ + t_StatusProhibit: 60, /* in ms */ + }, + }, + logical_channel_config: { + priority: 11, + prioritisedBitRate: 8, /* in kb/s, -1 means infinity */ + bucketSizeDuration: 100, /* in ms */ + logicalChannelGroup: 2, + logicalChannelSR_Mask: false, + logicalChannelSR_Prohibit: false, + }, + }, +] diff --git a/src/osmo_gsm_tester/templates/amarisoft_enb.cfg.tmpl b/src/osmo_gsm_tester/templates/amarisoft_enb.cfg.tmpl new file mode 100644 index 00000000..73b4fd23 --- /dev/null +++ b/src/osmo_gsm_tester/templates/amarisoft_enb.cfg.tmpl @@ -0,0 +1,192 @@ +/* lteenb configuration file version 2018-10-18 + * Copyright (C) 2015-2018 Amarisoft + */ +{ + + license_server: { + server_addr: "${enb.license_server_addr}", + name: "amarisoft", + }, + + + /* Log filter: syntax: layer.field=value[,...] + + Possible layers are phy, mac, rlc, pdcp, rrc, nas, s1ap, x2ap, gtpu and + all. The 'all' layer is used to address all the layers at the + same time. + + field values: + + - 'level': the log level of each layer can be set to 'none', + 'error', 'info' or 'debug'. Use 'debug' to log all the messages. + + - 'max_size': set the maximum size of the hex dump. 0 means no + hex dump. -1 means no limit. + */ + //log_options: "all.level=debug,all.max_size=32", + log_options: "all.level=error,all.max_size=0,nas.level=debug,nas.max_size=1,s1ap.level=debug,s1ap.max_size=1,x2ap.level=debug,x2ap.max_size=1,rrc.level=debug,rrc.max_size=1", + log_filename: "${enb.log_filename}", + + /* Enable remote API and Web interface */ + com_addr: "${enb.addr}:9001", + + /* RF driver configuration */ + include "amarisoft_rf_driver.cfg", + + mme_list: [ + { + /* address of MME for S1AP connection. Must be modified if the MME + runs on a different host. */ + mme_addr: "${enb.mme_addr}", + }, + ], + /* GTP bind address (=address of the ethernet interface connected to + the MME). Must be modified if the MME runs on a different host. */ + gtp_addr: "${enb.addr}", + + /* high 20 bits of SIB1.cellIdentifier */ + enb_id: 0x19B, + + /* list of cells */ + cell_list: [ + { + /* Broadcasted PLMN identities */ + plmn_list: [ + "${enb.mcc}${enb.mnc}", + ], + + //dl_earfcn: 300, /* DL center frequency: 2132 MHz (Band 1) */ + //dl_earfcn: 900, /* DL center frequency: 1960 MHz (Band 2) */ + //dl_earfcn: 1575, /* DL center frequency: 1842.5 MHz (Band 3) */ + //dl_earfcn: 2150, /* DL center frequency: 2130 MHz (Band 4) */ + //dl_earfcn: 2525, /* DL center frequency: 881.5 MHz (Band 5) */ + dl_earfcn: 2850, /* DL center frequency: 2680 MHz (Band 7) */ + //dl_earfcn: 6300, /* 806 MHz (Band 20) */ + //dl_earfcn: 38050, /* 2600 MHz (band 38) */ + //dl_earfcn: 40620, /* 2593 MHz (band 41) */ + //dl_earfcn: 42590, /* 3500 MHz (band 42) */ + + n_id_cell: 1, + cell_id: 0x01, + tac: 0x0001, + root_sequence_index: 204, /* PRACH root sequence index */ + }, + ], /* cell_list */ + + /* default cell parameters */ + cell_default: { + n_antenna_dl: 1, /* number of DL antennas */ + n_antenna_ul: 1, /* number of UL antennas */ + n_rb_dl: ${enb.num_prb}, /* Bandwidth: 25: 5 MHz, 50: 10 MHz, 75: 15 MHz, 100: 20 MHz */ + cyclic_prefix: "normal", + + phich_duration: "normal", + phich_resource: "1", /* ratio of NG */ + + /* System Information Block type 1 */ + sib1: "amarisoft_sib1.asn", + + /* other SIBs, in same order as the scheduling list in SIB 1 */ + sib_sched_list: [ "amarisoft_sib23.asn" ], + + si_coderate: 0.30, /* maximum code rate for SI/RA/P-RNTI messages */ + si_pdcch_format: 2, /* 2 or 3. Log2 of the number of CCEs for PDCCH + for SI/RA/P-RNTI */ + + n_symb_cch: 0, /* number of symbols for CCH (0 = auto) */ + + /* PDSCH dedicated config (currently same for all UEs) */ + pdsch_dedicated: { + p_a: 0, + }, + + /* If defined, force for number of CCEs for UE specific PDCCH to + 2^pdcch_format. Otherwise it is computed from the reported + CQI. Range: 0 to 3. */ + pdcch_format: 1, + + /* if defined, force the PDSCH MCS for all UEs. Otherwise it is + computed from the reported CQI */ + /* pdsch_mcs: 12, */ + + /* PUSCH dedicated config (currently same for all UEs) */ + pusch_dedicated: { + beta_offset_ack_index: 9, + beta_offset_ri_index: 6, + beta_offset_cqi_index: 6, + }, + + /* MCS for Msg3 (=CCCH RRC Connection Request) */ + pusch_msg3_mcs: 0, + + /* this CQI value is assumed when none is received from the UE */ + initial_cqi: 5, + + /* if defined, force the PUSCH MCS for all UEs. Otherwise it is + computed from the last received SRS/PUSCH. */ + // pusch_mcs: 18, + + transmission_mode: ${enb.transmission_mode}, + + /* Scheduling request period (ms). Must be >= 40 for HD-FDD */ + sr_period: 20, + + /* CQI report config */ + cqi_period: 40, /* period (ms). Must be >= 32 for HD-FDD */ + + /* RI reporting is done with a period of m_ri * cqi_period. + m_ri = 0 (default) disables RI reporting. */ +// m_ri: 8, + + /* SRS dedicated config. All UEs share these + parameters. srs_config_index and freq_domain_position are + allocated for each UE) */ + srs_dedicated: { + srs_period: 80, /* period (ms). Must be >= 40 for HD-FDD */ + srs_bandwidth: 1, + srs_hopping_bandwidth: 0, + }, + + /* MAC configuration (same for all UEs) */ + mac_config: { + ul_max_harq_tx: 5, /* max number of HARQ transmissions for uplink */ + dl_max_harq_tx: 5, /* max number of HARQ transmissions for downlink */ + }, + + /* CPU load limitation */ + pusch_max_its: 6, /* max number of turbo decoder iterations */ + + /* dynamic power control */ + dpc: true, + dpc_pusch_snr_target: 15, + dpc_pucch_snr_target: 10, + + /* RRC/UP ciphering algorithm preference. EEA0 is always the last. */ + cipher_algo_pref: [], + /* RRC integrity algorithm preference. EIA0 is always the last. */ + integ_algo_pref: [2, 1], + + /* (in ms) send RRC connection release after this time of network + inactivity */ + inactivity_timer: 10000, + + /* SRB configuration */ + srb_config: [ + { + id: 1, + maxRetxThreshold: 32, + t_Reordering: 45, + t_PollRetransmit: 60, + }, + { + id: 2 , + maxRetxThreshold: 32, + t_Reordering: 45, + t_PollRetransmit: 60, + } + ], + + /* DRB configuration */ + drb_config: "amarisoft_drb.cfg", + }, +} diff --git a/src/osmo_gsm_tester/templates/amarisoft_rf_driver.cfg.tmpl b/src/osmo_gsm_tester/templates/amarisoft_rf_driver.cfg.tmpl new file mode 100644 index 00000000..bbf9b472 --- /dev/null +++ b/src/osmo_gsm_tester/templates/amarisoft_rf_driver.cfg.tmpl @@ -0,0 +1,20 @@ +/* Parameters for b2x0 UHD device version 2018-10-18 + * Copyright (C) 2015-2018 Amarisoft + */ +rf_driver: { + name: "${enb.rf_dev_type}", + sync: "none", + + /* Use this for b2x0 devices. Bandwidth >= 10 Mhz */ + args: "${enb.rf_dev_args}", + + /* Use this for bandwidth == 5 Mhz */ + //args: "send_frame_size=1024,recv_frame_size=1024", + + /* Use this for bandwidth < 5 Mhz */ + //args: "send_frame_size=512,recv_frame_size=512", +}, + +tx_gain: 89.0, /* TX gain (in dB) B2x0: 0 to 89.8 dB */ +rx_gain: 60.0, /* RX gain (in dB) B2x0: 0 to 73 dB */ +tx_time_offset: -150, /* in samples */ diff --git a/src/osmo_gsm_tester/templates/amarisoft_sib1.asn.tmpl b/src/osmo_gsm_tester/templates/amarisoft_sib1.asn.tmpl new file mode 100644 index 00000000..0fc5f13d --- /dev/null +++ b/src/osmo_gsm_tester/templates/amarisoft_sib1.asn.tmpl @@ -0,0 +1,42 @@ +{ + message c1: systemInformationBlockType1: { + cellAccessRelatedInfo { + plmn-IdentityList { + { + plmn-Identity { /* patched by eNB */ + mcc { + 0, + 0, + 0 + }, + mnc { + 0, + 0 + } + }, + cellReservedForOperatorUse notReserved + } + }, + trackingAreaCode '0000'H, /* patched by eNB */ + cellIdentity '0000000'H, /* patched by eNB */ + cellBarred notBarred, + intraFreqReselection allowed, + csg-Indication FALSE + }, + cellSelectionInfo { + q-RxLevMin -70 + }, + p-Max 10, /* maximum power allowed for the UE (dBm) */ + freqBandIndicator 1, /* patched by eNB */ + schedulingInfoList { + { + si-Periodicity rf16, + sib-MappingInfo { + sibType3 + } + } + }, + si-WindowLength ms40, + systemInfoValueTag 8 + } +} diff --git a/src/osmo_gsm_tester/templates/amarisoft_sib23.asn.tmpl b/src/osmo_gsm_tester/templates/amarisoft_sib23.asn.tmpl new file mode 100644 index 00000000..c08b6451 --- /dev/null +++ b/src/osmo_gsm_tester/templates/amarisoft_sib23.asn.tmpl @@ -0,0 +1,116 @@ +{ + message c1: systemInformation: { + criticalExtensions systemInformation-r8: { + sib-TypeAndInfo { + sib2: { + radioResourceConfigCommon { + rach-ConfigCommon { + preambleInfo { + numberOfRA-Preambles n52 + }, + powerRampingParameters { + powerRampingStep dB2, + preambleInitialReceivedTargetPower dBm-104 + }, + ra-SupervisionInfo { + preambleTransMax n10, + ra-ResponseWindowSize sf10, + mac-ContentionResolutionTimer sf40 + }, + maxHARQ-Msg3Tx 5 + }, + bcch-Config { + modificationPeriodCoeff n4 + }, + pcch-Config { + defaultPagingCycle rf128, + nB oneT + }, + prach-Config { + rootSequenceIndex 0, /* patched by eNB */ + prach-ConfigInfo { + prach-ConfigIndex 15, /* 20 ms period, subframe 9 */ + highSpeedFlag FALSE, + zeroCorrelationZoneConfig 11, + prach-FreqOffset 0 + } + }, + pdsch-ConfigCommon { + referenceSignalPower -5, + p-b 1 + }, + pusch-ConfigCommon { + pusch-ConfigBasic { + n-SB 1, + hoppingMode interSubFrame, + pusch-HoppingOffset 2, + enable64QAM FALSE + }, + ul-ReferenceSignalsPUSCH { + groupHoppingEnabled FALSE, + groupAssignmentPUSCH 0, + sequenceHoppingEnabled FALSE, + cyclicShift 0 + } + }, + pucch-ConfigCommon { + deltaPUCCH-Shift ds2, + nRB-CQI 1, + nCS-AN 0, + n1PUCCH-AN 11 + }, + soundingRS-UL-ConfigCommon setup: { + srs-BandwidthConfig bw7, + srs-SubframeConfig sc3, + ackNackSRS-SimultaneousTransmission TRUE + }, + uplinkPowerControlCommon { + p0-NominalPUSCH -67, + alpha al07, + p0-NominalPUCCH -105, + deltaFList-PUCCH { + deltaF-PUCCH-Format1 deltaF0, + deltaF-PUCCH-Format1b deltaF3, + deltaF-PUCCH-Format2 deltaF1, + deltaF-PUCCH-Format2a deltaF2, + deltaF-PUCCH-Format2b deltaF2 + }, + deltaPreambleMsg3 4 + }, + ul-CyclicPrefixLength len1 + }, + ue-TimersAndConstants { + t300 ms200, + t301 ms200, + t310 ms200, + n310 n6, + t311 ms10000, + n311 n5 + }, + freqInfo { + additionalSpectrumEmission 1 + }, + timeAlignmentTimerCommon infinity + }, + sib3: { + cellReselectionInfoCommon { + q-Hyst dB2 + }, + cellReselectionServingFreqInfo { + s-NonIntraSearch 3, + threshServingLow 2, + cellReselectionPriority 6 + }, + intraFreqCellReselectionInfo { + q-RxLevMin -61, + p-Max 23, + s-IntraSearch 5, + presenceAntennaPort1 TRUE, + neighCellConfig '01'B, + t-ReselectionEUTRA 1 + } + } + } + } + } +} diff --git a/suites/4g/suite.conf b/suites/4g/suite.conf index 59e393aa..c1086bcb 100644 --- a/suites/4g/suite.conf +++ b/suites/4g/suite.conf @@ -3,7 +3,6 @@ resources: - times: 1 enb: - times: 1 - type: srsenb modem: - times: 1 type: srsue