<p>pespin <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-gsm-tester/+/17139">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  pespin: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Initial srsLTE support<br><br>2 tests (iperf3, ping) working against a full srs{UE,ENB,EPC} network<br>using ZeroMQ backend for RF (so no real RF support yet, that will come<br>next).<br><br>Related: OS##4295, OS#4296<br><br>Change-Id: I290c0d79258a9f94f00c7ff2e1c6c5579c0e32f4<br>---<br>M example/defaults.conf<br>M example/resources.conf.prod<br>M src/osmo_gsm_tester/resource.py<br>A src/osmo_gsm_tester/srs_enb.py<br>A src/osmo_gsm_tester/srs_epc.py<br>A src/osmo_gsm_tester/srs_ue.py<br>M src/osmo_gsm_tester/suite.py<br>A src/osmo_gsm_tester/templates/srsenb.conf.tmpl<br>A src/osmo_gsm_tester/templates/srsenb_drb.conf.tmpl<br>A src/osmo_gsm_tester/templates/srsenb_rr.conf.tmpl<br>A src/osmo_gsm_tester/templates/srsenb_sib.conf.tmpl<br>A src/osmo_gsm_tester/templates/srsepc.conf.tmpl<br>A src/osmo_gsm_tester/templates/srsepc_user_db.csv.tmpl<br>A src/osmo_gsm_tester/templates/srsue.conf.tmpl<br>A suites/4g/iperf3.py<br>D suites/4g/mo_mt_sms.py<br>A suites/4g/ping.py<br>M suites/4g/suite.conf<br>18 files changed, 1,769 insertions(+), 24 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/example/defaults.conf b/example/defaults.conf</span><br><span>index 353cf9b..f32e1f5 100644</span><br><span>--- a/example/defaults.conf</span><br><span>+++ b/example/defaults.conf</span><br><span>@@ -92,3 +92,11 @@</span><br><span>   max_trx: 1</span><br><span>   trx_list:</span><br><span>   - nominal_power: 25</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+srsepc:</span><br><span style="color: hsl(120, 100%, 40%);">+  mcc: 901</span><br><span style="color: hsl(120, 100%, 40%);">+  mnc: 70</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+srsenb:</span><br><span style="color: hsl(120, 100%, 40%);">+  mcc: 901</span><br><span style="color: hsl(120, 100%, 40%);">+  mnc: 70</span><br><span>diff --git a/example/resources.conf.prod b/example/resources.conf.prod</span><br><span>index 992a694..943160b 100644</span><br><span>--- a/example/resources.conf.prod</span><br><span>+++ b/example/resources.conf.prod</span><br><span>@@ -11,6 +11,12 @@</span><br><span> - addr: 10.42.42.9</span><br><span> - addr: 10.42.42.10</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+run_node:</span><br><span style="color: hsl(120, 100%, 40%);">+- run_type: ssh</span><br><span style="color: hsl(120, 100%, 40%);">+  run_addr: 10.42.42.118</span><br><span style="color: hsl(120, 100%, 40%);">+  ssh_user: jenkins</span><br><span style="color: hsl(120, 100%, 40%);">+  ssh_addr: 10.42.42.116</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> bts:</span><br><span> - label: sysmoBTS 1002</span><br><span>   type: osmo-bts-sysmo</span><br><span>@@ -148,6 +154,12 @@</span><br><span>   direct_pcu: true</span><br><span>   ciphers: [a5_0, a5_1, a5_3]</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+enb:</span><br><span style="color: hsl(120, 100%, 40%);">+- label: srsENB-zmq</span><br><span style="color: hsl(120, 100%, 40%);">+  type: srsenb</span><br><span style="color: hsl(120, 100%, 40%);">+  remote_user: jenkins</span><br><span style="color: hsl(120, 100%, 40%);">+  addr: 10.42.42.117</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> arfcn:</span><br><span>   - arfcn: 512</span><br><span>     band: GSM-1800</span><br><span>@@ -227,5 +239,14 @@</span><br><span>   ciphers: [a5_0, a5_1]</span><br><span>   features: ['sms', 'voice', 'ussd', 'gprs', 'sim']</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+- label: srsUE-zmq_1</span><br><span style="color: hsl(120, 100%, 40%);">+  type: srsue</span><br><span style="color: hsl(120, 100%, 40%);">+  remote_user: jenkins</span><br><span style="color: hsl(120, 100%, 40%);">+  addr: 10.42.42.116</span><br><span style="color: hsl(120, 100%, 40%);">+  imsi: '001010123456789'</span><br><span style="color: hsl(120, 100%, 40%);">+  ki: '00112233445566778899aabbccddeeff'</span><br><span style="color: hsl(120, 100%, 40%);">+  auth_algo: 'xor'</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> osmocon_phone:</span><br><span>   - serial_device: '/dev/serial/by-id/usb-Silicon_Labs_CP2104_USB_to_UART_Bridge_Controller_00897B41-if00-port0'</span><br><span>diff --git a/src/osmo_gsm_tester/resource.py b/src/osmo_gsm_tester/resource.py</span><br><span>index 0cdcb8a..0804591 100644</span><br><span>--- a/src/osmo_gsm_tester/resource.py</span><br><span>+++ b/src/osmo_gsm_tester/resource.py</span><br><span>@@ -29,6 +29,7 @@</span><br><span> from . import bts_sysmo, bts_osmotrx, bts_osmovirtual, bts_octphy, bts_nanobts, bts_oc2g</span><br><span> from . import modem</span><br><span> from . import ms_osmo_mobile</span><br><span style="color: hsl(120, 100%, 40%);">+from . import srs_ue, srs_enb</span><br><span> </span><br><span> from .util import is_dict, is_list</span><br><span> </span><br><span>@@ -45,7 +46,8 @@</span><br><span> R_ARFCN = 'arfcn'</span><br><span> R_MODEM = 'modem'</span><br><span> R_OSMOCON = 'osmocon_phone'</span><br><span style="color: hsl(0, 100%, 40%);">-R_ALL = (R_IP_ADDRESS, R_RUN_NODE, R_BTS, R_ARFCN, R_MODEM, R_OSMOCON)</span><br><span style="color: hsl(120, 100%, 40%);">+R_ENB = 'enb'</span><br><span style="color: hsl(120, 100%, 40%);">+R_ALL = (R_IP_ADDRESS, R_RUN_NODE, R_BTS, R_ARFCN, R_MODEM, R_OSMOCON, R_ENB)</span><br><span> </span><br><span> RESOURCES_SCHEMA = {</span><br><span>         'ip_address[].addr': schema.IPV4,</span><br><span>@@ -83,6 +85,11 @@</span><br><span>         'bts[].osmo_trx.max_trxd_version': schema.UINT,</span><br><span>         'bts[].osmo_trx.channels[].rx_path': schema.STR,</span><br><span>         'bts[].osmo_trx.channels[].tx_path': schema.STR,</span><br><span style="color: hsl(120, 100%, 40%);">+        'enb[].label': schema.STR,</span><br><span style="color: hsl(120, 100%, 40%);">+        'enb[].type': schema.STR,</span><br><span style="color: hsl(120, 100%, 40%);">+        'enb[].remote_user': schema.STR,</span><br><span style="color: hsl(120, 100%, 40%);">+        'enb[].addr': schema.IPV4,</span><br><span style="color: hsl(120, 100%, 40%);">+        'enb[].band': schema.BAND,</span><br><span>         'arfcn[].arfcn': schema.INT,</span><br><span>         'arfcn[].band': schema.BAND,</span><br><span>         'modem[].type': schema.STR,</span><br><span>@@ -91,6 +98,8 @@</span><br><span>         'modem[].imsi': schema.IMSI,</span><br><span>         'modem[].ki': schema.KI,</span><br><span>         'modem[].auth_algo': schema.AUTH_ALGO,</span><br><span style="color: hsl(120, 100%, 40%);">+        'modem[].remote_user': schema.STR,</span><br><span style="color: hsl(120, 100%, 40%);">+        'modem[].addr': schema.IPV4,</span><br><span>         'modem[].ciphers[]': schema.CIPHER,</span><br><span>         'modem[].features[]': schema.MODEM_FEATURE,</span><br><span>         'osmocon_phone[].serial_device': schema.STR,</span><br><span>@@ -115,12 +124,16 @@</span><br><span>         'nanobts': bts_nanobts.NanoBts,</span><br><span>     }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+KNOWN_ENB_TYPES = {</span><br><span style="color: hsl(120, 100%, 40%);">+        'srsenb': srs_enb.srsENB,</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> KNOWN_MS_TYPES = {</span><br><span>         # Map None to ofono for forward compability</span><br><span>         None: modem.Modem,</span><br><span>         'ofono': modem.Modem,</span><br><span>         'osmo-mobile': ms_osmo_mobile.MSOsmoMobile,</span><br><span style="color: hsl(120, 100%, 40%);">+        'srsue': srs_ue.srsUE,</span><br><span> }</span><br><span> </span><br><span> </span><br><span>diff --git a/src/osmo_gsm_tester/srs_enb.py b/src/osmo_gsm_tester/srs_enb.py</span><br><span>new file mode 100644</span><br><span>index 0000000..2b65a5b</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo_gsm_tester/srs_enb.py</span><br><span>@@ -0,0 +1,197 @@</span><br><span style="color: hsl(120, 100%, 40%);">+# osmo_gsm_tester: specifics for running an SRS eNodeB process</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Copyright (C) 2020 by sysmocom - s.f.m.c. GmbH</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Author: Pau Espin Pedrol <pespin@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# This program is free software: you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+# it under the terms of the GNU General Public License as</span><br><span style="color: hsl(120, 100%, 40%);">+# published by the Free Software Foundation, either version 3 of the</span><br><span style="color: hsl(120, 100%, 40%);">+# License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+# but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+# GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+# along with this program.  If not, see <http://www.gnu.org/licenses/>.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+import os</span><br><span style="color: hsl(120, 100%, 40%);">+import pprint</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from . import log, util, config, template, process, remote</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class srsENB(log.Origin):</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    REMOTE_DIR = '/osmo-gsm-tester-srsenb'</span><br><span style="color: hsl(120, 100%, 40%);">+    BINFILE = 'srsenb'</span><br><span style="color: hsl(120, 100%, 40%);">+    CFGFILE = 'srsenb.conf'</span><br><span style="color: hsl(120, 100%, 40%);">+    CFGFILE_SIB = 'srsenb_sib.conf'</span><br><span style="color: hsl(120, 100%, 40%);">+    CFGFILE_RR = 'srsenb_rr.conf'</span><br><span style="color: hsl(120, 100%, 40%);">+    CFGFILE_DRB = 'srsenb_drb.conf'</span><br><span style="color: hsl(120, 100%, 40%);">+    LOGFILE = 'srsenb.log'</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, suite_run, conf):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(log.C_RUN, 'srsenb')</span><br><span style="color: hsl(120, 100%, 40%);">+        self._addr = conf.get('addr', None)</span><br><span style="color: hsl(120, 100%, 40%);">+        if self._addr is None:</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error('addr not set')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.set_name('srsenb_%s' % self._addr)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.ue = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.epc = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.run_dir = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.config_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.config_sib_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.config_rr_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.config_drb_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_config_file =  None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_config_sib_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_config_rr_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_config_drb_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_log_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.suite_run = suite_run</span><br><span style="color: hsl(120, 100%, 40%);">+        self.nof_prb=100</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.nof_prb == 75:</span><br><span style="color: hsl(120, 100%, 40%);">+          self.base_srate=15.36e6</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+          self.base_srate=23.04e6</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_user = conf.get('remote_user', None)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def cleanup(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.process is None:</span><br><span style="color: hsl(120, 100%, 40%);">+            return</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.setup_runs_locally():</span><br><span style="color: hsl(120, 100%, 40%);">+            return</span><br><span style="color: hsl(120, 100%, 40%);">+        # copy back files (may not exist, for instance if there was an early error of process):</span><br><span style="color: hsl(120, 100%, 40%);">+        try:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.rem_host.scpfrom('scp-back-log', self.remote_log_file, self.log_file)</span><br><span style="color: hsl(120, 100%, 40%);">+        except Exception as e:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.log(repr(e))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def setup_runs_locally(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        return self.remote_user is None</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def start(self, epc):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log('Starting srsENB')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.epc = epc</span><br><span style="color: hsl(120, 100%, 40%);">+        self.run_dir = util.Dir(self.suite_run.get_test_run_dir().new_dir(self.name()))</span><br><span style="color: hsl(120, 100%, 40%);">+        self.configure()</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.remote_user:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.start_remotely()</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.start_locally()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def start_remotely(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.inst = util.Dir(os.path.abspath(self.suite_run.trial.get_inst('srslte')))</span><br><span style="color: hsl(120, 100%, 40%);">+        lib = self.inst.child('lib')</span><br><span style="color: hsl(120, 100%, 40%);">+        if not os.path.isdir(lib):</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error('No lib/ in', self.inst)</span><br><span style="color: hsl(120, 100%, 40%);">+        if not self.inst.isfile('bin', srsENB.BINFILE):</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error('No %s binary in' % srsENB.BINFILE, self.inst)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host = remote.RemoteHost(self.run_dir, self.remote_user, self._addr)</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_prefix_dir = util.Dir(srsENB.REMOTE_DIR)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_inst = util.Dir(remote_prefix_dir.child(os.path.basename(str(self.inst))))</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_run_dir = util.Dir(remote_prefix_dir.child(srsENB.BINFILE))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_config_file = remote_run_dir.child(srsENB.CFGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_config_sib_file = remote_run_dir.child(srsENB.CFGFILE_SIB)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_config_rr_file = remote_run_dir.child(srsENB.CFGFILE_RR)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_config_drb_file = remote_run_dir.child(srsENB.CFGFILE_DRB)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_log_file = remote_run_dir.child(srsENB.LOGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.recreate_remote_dir(self.remote_inst)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.scp('scp-inst-to-remote', str(self.inst), remote_prefix_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.create_remote_dir(remote_run_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.scp('scp-cfg-to-remote', self.config_file, self.remote_config_file)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.scp('scp-cfg-sib-to-remote', self.config_sib_file, self.remote_config_sib_file)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.scp('scp-cfg-rr-to-remote', self.config_rr_file, self.remote_config_rr_file)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.scp('scp-cfg-drb-to-remote', self.config_drb_file, self.remote_config_drb_file)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_env = { 'LD_LIBRARY_PATH': self.remote_inst.child('lib') }</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_binary = self.remote_inst.child('bin', srsENB.BINFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        args = (remote_binary, self.remote_config_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                '--enb_files.sib_config=' + self.remote_config_sib_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                '--enb_files.rr_config=' + self.remote_config_rr_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                '--enb_files.drb_config=' + self.remote_config_drb_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                '--rf.device_name=zmq',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--rf.device_args="fail_on_disconnect=true,tx_port=tcp://'+ self.addr() +':2000,rx_port=tcp://'+ self.ue.addr() +':2001,id=enb,base_srate='+ str(self.base_srate) + '"',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--expert.nof_phy_threads=1',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--expert.rrc_inactivity_timer=1500',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--enb.n_prb=' + str(self.nof_prb),</span><br><span style="color: hsl(120, 100%, 40%);">+                '--log.filename=' + self.remote_log_file)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process = self.rem_host.RemoteProcessFixIgnoreSIGHUP(srsENB.BINFILE, util.Dir(srsENB.REMOTE_DIR), args, remote_env=remote_env)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.suite_run.remember_to_stop(self.process)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process.launch()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def start_locally(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        inst = util.Dir(os.path.abspath(self.suite_run.trial.get_inst('srslte')))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        binary = inst.child('bin', BINFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        if not os.path.isfile(binary):</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error('Binary missing:', binary)</span><br><span style="color: hsl(120, 100%, 40%);">+        lib = inst.child('lib')</span><br><span style="color: hsl(120, 100%, 40%);">+        if not os.path.isdir(lib):</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error('No lib/ in', inst)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        env = { 'LD_LIBRARY_PATH': util.prepend_library_path(lib) }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.dbg(run_dir=self.run_dir, binary=binary, env=env)</span><br><span style="color: hsl(120, 100%, 40%);">+        args = (binary, os.path.abspath(self.config_file),</span><br><span style="color: hsl(120, 100%, 40%);">+                '--enb_files.sib_config=' + os.path.abspath(self.config_sib_file),</span><br><span style="color: hsl(120, 100%, 40%);">+                '--enb_files.rr_config=' + os.path.abspath(self.config_rr_file),</span><br><span style="color: hsl(120, 100%, 40%);">+                '--enb_files.drb_config=' + os.path.abspath(self.config_drb_file),</span><br><span style="color: hsl(120, 100%, 40%);">+                '--rf.device_name=zmq',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--rf.device_args="fail_on_disconnect=true,tx_port=tcp://'+ self.addr() +':2000,rx_port=tcp://'+ self.ue.addr() +':2001,id=enb,base_srate='+ str(self.base_srate) + '"',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--expert.nof_phy_threads=1',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--expert.rrc_inactivity_timer=1500',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--enb.n_prb=' + str(self.nof_prb),</span><br><span style="color: hsl(120, 100%, 40%);">+                '--log.filename=' + self.log_file)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process = process.Process(self.name(), self.run_dir, args, env=env)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.suite_run.remember_to_stop(self.process)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process.launch()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def gen_conf_file(self, path, filename):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.dbg(config_file=path)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        values = dict(enb=config.get_defaults('srsenb'))</span><br><span style="color: hsl(120, 100%, 40%);">+        config.overlay(values, self.suite_run.config())</span><br><span style="color: hsl(120, 100%, 40%);">+        config.overlay(values, dict(enb={ 'run_addr': self.addr(),</span><br><span style="color: hsl(120, 100%, 40%);">+                                          'mme_addr': self.epc.addr()}))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.dbg('srsENB ' + filename + ':\n' + pprint.pformat(values))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        with open(path, 'w') as f:</span><br><span style="color: hsl(120, 100%, 40%);">+            r = template.render(filename, values)</span><br><span style="color: hsl(120, 100%, 40%);">+            self.dbg(r)</span><br><span style="color: hsl(120, 100%, 40%);">+            f.write(r)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def configure(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.config_file = self.run_dir.new_file(srsENB.CFGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.config_sib_file = self.run_dir.new_file(srsENB.CFGFILE_SIB)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.config_rr_file = self.run_dir.new_file(srsENB.CFGFILE_RR)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.config_drb_file = self.run_dir.new_file(srsENB.CFGFILE_DRB)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log_file = self.run_dir.new_file(srsENB.LOGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.gen_conf_file(self.config_file, srsENB.CFGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.gen_conf_file(self.config_sib_file, srsENB.CFGFILE_SIB)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.gen_conf_file(self.config_rr_file, srsENB.CFGFILE_RR)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.gen_conf_file(self.config_drb_file, srsENB.CFGFILE_DRB)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def ue_add(self, ue):</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.ue is not None:</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error("More than one UE per ENB not yet supported (ZeroMQ)")</span><br><span style="color: hsl(120, 100%, 40%);">+        self.ue = ue</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def running(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        return not self.process.terminated()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def addr(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        return self._addr</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# vim: expandtab tabstop=4 shiftwidth=4</span><br><span>diff --git a/src/osmo_gsm_tester/srs_epc.py b/src/osmo_gsm_tester/srs_epc.py</span><br><span>new file mode 100644</span><br><span>index 0000000..0a0036e</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo_gsm_tester/srs_epc.py</span><br><span>@@ -0,0 +1,207 @@</span><br><span style="color: hsl(120, 100%, 40%);">+# osmo_gsm_tester: specifics for running an SRS EPC process</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Copyright (C) 2020 by sysmocom - s.f.m.c. GmbH</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Author: Pau Espin Pedrol <pespin@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# This program is free software: you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+# it under the terms of the GNU General Public License as</span><br><span style="color: hsl(120, 100%, 40%);">+# published by the Free Software Foundation, either version 3 of the</span><br><span style="color: hsl(120, 100%, 40%);">+# License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+# but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+# GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+# along with this program.  If not, see <http://www.gnu.org/licenses/>.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+import os</span><br><span style="color: hsl(120, 100%, 40%);">+import pprint</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from . import log, util, config, template, process, remote</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class srsEPC(log.Origin):</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    REMOTE_DIR = '/osmo-gsm-tester-srsepc'</span><br><span style="color: hsl(120, 100%, 40%);">+    BINFILE = 'srsepc'</span><br><span style="color: hsl(120, 100%, 40%);">+    CFGFILE = 'srsepc.conf'</span><br><span style="color: hsl(120, 100%, 40%);">+    DBFILE = 'srsepc_user_db.csv'</span><br><span style="color: hsl(120, 100%, 40%);">+    PCAPFILE = 'srsepc.pcap'</span><br><span style="color: hsl(120, 100%, 40%);">+    LOGFILE = 'srsepc.log'</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, suite_run, run_node):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(log.C_RUN, 'srsepc')</span><br><span style="color: hsl(120, 100%, 40%);">+        self._addr = run_node.run_addr()</span><br><span style="color: hsl(120, 100%, 40%);">+        self.set_name('srsepc_%s' % self._addr)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.run_dir = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.config_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.db_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.pcap_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_config_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_db_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_log_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_pcap_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.subscriber_list = []</span><br><span style="color: hsl(120, 100%, 40%);">+        self.suite_run = suite_run</span><br><span style="color: hsl(120, 100%, 40%);">+        self._run_node = run_node</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def cleanup(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.process is None:</span><br><span style="color: hsl(120, 100%, 40%);">+            return</span><br><span style="color: hsl(120, 100%, 40%);">+        if self._run_node.is_local():</span><br><span style="color: hsl(120, 100%, 40%);">+            return</span><br><span style="color: hsl(120, 100%, 40%);">+        # copy back files (may not exist, for instance if there was an early error of process):</span><br><span style="color: hsl(120, 100%, 40%);">+        try:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.rem_host.scpfrom('scp-back-log', self.remote_log_file, self.log_file)</span><br><span style="color: hsl(120, 100%, 40%);">+        except Exception as e:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.log(repr(e))</span><br><span style="color: hsl(120, 100%, 40%);">+        try:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.rem_host.scpfrom('scp-back-pcap', self.remote_pcap_file, self.pcap_file)</span><br><span style="color: hsl(120, 100%, 40%);">+        except Exception as e:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.log(repr(e))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def start(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log('Starting srsepc')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.run_dir = util.Dir(self.suite_run.get_test_run_dir().new_dir(self.name()))</span><br><span style="color: hsl(120, 100%, 40%);">+        self.configure()</span><br><span style="color: hsl(120, 100%, 40%);">+        if self._run_node.is_local():</span><br><span style="color: hsl(120, 100%, 40%);">+            self.start_locally()</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.start_remotely()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def start_remotely(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.inst = util.Dir(os.path.abspath(self.suite_run.trial.get_inst('srslte')))</span><br><span style="color: hsl(120, 100%, 40%);">+        lib = self.inst.child('lib')</span><br><span style="color: hsl(120, 100%, 40%);">+        if not os.path.isdir(lib):</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error('No lib/ in', self.inst)</span><br><span style="color: hsl(120, 100%, 40%);">+        if not self.inst.isfile('bin', srsEPC.BINFILE):</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error('No %s binary in' % srsEPC.BINFILE, self.inst)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host = remote.RemoteHost(self.run_dir, self._run_node.ssh_user(), self._run_node.ssh_addr())</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_prefix_dir = util.Dir(srsEPC.REMOTE_DIR)</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_inst = util.Dir(remote_prefix_dir.child(os.path.basename(str(self.inst))))</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_run_dir = util.Dir(remote_prefix_dir.child(srsEPC.BINFILE))</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_config_file = remote_run_dir.child(srsEPC.CFGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_db_file = remote_run_dir.child(srsEPC.DBFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_log_file = remote_run_dir.child(srsEPC.LOGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_pcap_file = remote_run_dir.child(srsEPC.PCAPFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.recreate_remote_dir(remote_inst)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.scp('scp-inst-to-remote', str(self.inst), remote_prefix_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.create_remote_dir(remote_run_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.scp('scp-cfg-to-remote', self.config_file, self.remote_config_file)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.scp('scp-db-to-remote', self.db_file, self.remote_db_file)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_lib = remote_inst.child('lib')</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_binary = remote_inst.child('bin', srsEPC.BINFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        # setting capabilities will later disable use of LD_LIBRARY_PATH from ELF loader -> modify RPATH instead.</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log('Setting RPATH for srsepc')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.change_elf_rpath(remote_binary, remote_lib)</span><br><span style="color: hsl(120, 100%, 40%);">+        # srsepc requires CAP_NET_ADMIN to create tunnel devices: ioctl(TUNSETIFF):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log('Applying CAP_NET_ADMIN capability to srsepc')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.setcap_net_admin(remote_binary)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        args = (remote_binary, self.remote_config_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                '--hss.db_file=' + self.remote_db_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                '--log.filename=' + self.remote_log_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                '--pcap.enable=true',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--pcap.filename=' + self.remote_pcap_file)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process = self.rem_host.RemoteProcess(srsEPC.BINFILE, args)</span><br><span style="color: hsl(120, 100%, 40%);">+        #self.process = self.rem_host.RemoteProcessFixIgnoreSIGHUP(srsEPC.BINFILE, remote_run_dir, args)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.suite_run.remember_to_stop(self.process)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process.launch()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def start_locally(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        inst = util.Dir(os.path.abspath(self.suite_run.trial.get_inst('srslte')))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        binary = inst.child('bin', BINFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        if not os.path.isfile(binary):</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error('Binary missing:', binary)</span><br><span style="color: hsl(120, 100%, 40%);">+        lib = inst.child('lib')</span><br><span style="color: hsl(120, 100%, 40%);">+        if not os.path.isdir(lib):</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error('No lib/ in', inst)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        env = {}</span><br><span style="color: hsl(120, 100%, 40%);">+        # setting capabilities will later disable use of LD_LIBRARY_PATH from ELF loader -> modify RPATH instead.</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log('Setting RPATH for srsepc')</span><br><span style="color: hsl(120, 100%, 40%);">+        # srsepc binary needs patchelf <= 0.9 (0.10 and current master fail) to avoid failing during patch. OS#4389, patchelf-GH#192.</span><br><span style="color: hsl(120, 100%, 40%);">+        util.change_elf_rpath(binary, util.prepend_library_path(lib), self.run_dir.new_dir('patchelf'))</span><br><span style="color: hsl(120, 100%, 40%);">+        # srsepc requires CAP_NET_ADMIN to create tunnel devices: ioctl(TUNSETIFF):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log('Applying CAP_NET_ADMIN capability to srsepc')</span><br><span style="color: hsl(120, 100%, 40%);">+        util.setcap_net_admin(binary, self.run_dir.new_dir('setcap_net_admin'))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.dbg(run_dir=self.run_dir, binary=binary, env=env)</span><br><span style="color: hsl(120, 100%, 40%);">+        args = (binary, os.path.abspath(self.config_file),</span><br><span style="color: hsl(120, 100%, 40%);">+                '--hss.db_file=' + self.db_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                '--log.filename=' + self.log_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                '--pcap.enable=true',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--pcap.filename=' + self.pcap_file)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process = process.Process(self.name(), self.run_dir, args, env=env)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.suite_run.remember_to_stop(self.process)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process.launch()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def configure(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.config_file = self.run_dir.new_file(srsEPC.CFGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.db_file = self.run_dir.new_file(srsEPC.DBFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log_file = self.run_dir.new_file(srsEPC.LOGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.pcap_file = self.run_dir.new_file(srsEPC.PCAPFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.dbg(config_file=self.config_file, db_file=self.db_file)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        values = dict(epc=config.get_defaults('srsepc'))</span><br><span style="color: hsl(120, 100%, 40%);">+        config.overlay(values, dict(epc=dict(hss=dict(subscribers=self.subscriber_list))))</span><br><span style="color: hsl(120, 100%, 40%);">+        config.overlay(values, self.suite_run.config())</span><br><span style="color: hsl(120, 100%, 40%);">+        config.overlay(values, dict(epc={'run_addr': self.addr()}))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.dbg('SRSEPC CONFIG:\n' + pprint.pformat(values))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        with open(self.config_file, 'w') as f:</span><br><span style="color: hsl(120, 100%, 40%);">+            r = template.render(srsEPC.CFGFILE, values)</span><br><span style="color: hsl(120, 100%, 40%);">+            self.dbg(r)</span><br><span style="color: hsl(120, 100%, 40%);">+            f.write(r)</span><br><span style="color: hsl(120, 100%, 40%);">+        with open(self.db_file, 'w') as f:</span><br><span style="color: hsl(120, 100%, 40%);">+            r = template.render(srsEPC.DBFILE, values)</span><br><span style="color: hsl(120, 100%, 40%);">+            self.dbg(r)</span><br><span style="color: hsl(120, 100%, 40%);">+            f.write(r)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def subscriber_add(self, modem, msisdn=None, algo_str=None):</span><br><span style="color: hsl(120, 100%, 40%);">+        if msisdn is None:</span><br><span style="color: hsl(120, 100%, 40%);">+            msisdn = self.suite_run.resources_pool.next_msisdn(modem)</span><br><span style="color: hsl(120, 100%, 40%);">+        modem.set_msisdn(msisdn)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if algo_str is None:</span><br><span style="color: hsl(120, 100%, 40%);">+            algo_str = modem.auth_algo() or util.OSMO_AUTH_ALGO_NONE</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if algo_str != util.OSMO_AUTH_ALGO_NONE and not modem.ki():</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error("Auth algo %r selected but no KI specified" % algo_str)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        subscriber_id = len(self.subscriber_list) # list index</span><br><span style="color: hsl(120, 100%, 40%);">+        self.subscriber_list.append({'id': subscriber_id, 'imsi': modem.imsi(), 'msisdn': msisdn, 'auth_algo': algo_str, 'ki': modem.ki(), 'opc': None})</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log('Add subscriber', msisdn=msisdn, imsi=modem.imsi(), subscriber_id=subscriber_id,</span><br><span style="color: hsl(120, 100%, 40%);">+                 algo_str=algo_str)</span><br><span style="color: hsl(120, 100%, 40%);">+        return subscriber_id</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def enb_is_connected(self, enb):</span><br><span style="color: hsl(120, 100%, 40%);">+        # FIXME: srspec's stdout: "S1 Setup Request - eNB Id 0x66c0", but srsenb.conf has "enb_id = 0x19B"</span><br><span style="color: hsl(120, 100%, 40%);">+        return 'S1 Setup Request - eNB Id' in (self.process.get_stdout() or '')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def running(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        return not self.process.terminated()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def addr(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        return self._addr</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def tun_addr(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        return '172.16.0.1'</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def run_node(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        return self._run_node</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# vim: expandtab tabstop=4 shiftwidth=4</span><br><span>diff --git a/src/osmo_gsm_tester/srs_ue.py b/src/osmo_gsm_tester/srs_ue.py</span><br><span>new file mode 100644</span><br><span>index 0000000..c68c726</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo_gsm_tester/srs_ue.py</span><br><span>@@ -0,0 +1,213 @@</span><br><span style="color: hsl(120, 100%, 40%);">+# osmo_gsm_tester: specifics for running an SRS UE process</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Copyright (C) 2020 by sysmocom - s.f.m.c. GmbH</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Author: Pau Espin Pedrol <pespin@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# This program is free software: you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+# it under the terms of the GNU General Public License as</span><br><span style="color: hsl(120, 100%, 40%);">+# published by the Free Software Foundation, either version 3 of the</span><br><span style="color: hsl(120, 100%, 40%);">+# License, or (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+# but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+# GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+# along with this program.  If not, see <http://www.gnu.org/licenses/>.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+import os</span><br><span style="color: hsl(120, 100%, 40%);">+import pprint</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from . import log, util, config, template, process, remote</span><br><span style="color: hsl(120, 100%, 40%);">+from .run_node import RunNode</span><br><span style="color: hsl(120, 100%, 40%);">+from .ms import MS</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class srsUE(MS):</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    REMOTE_DIR = '/osmo-gsm-tester-srsue'</span><br><span style="color: hsl(120, 100%, 40%);">+    BINFILE = 'srsue'</span><br><span style="color: hsl(120, 100%, 40%);">+    CFGFILE = 'srsue.conf'</span><br><span style="color: hsl(120, 100%, 40%);">+    PCAPFILE = 'srsue.pcap'</span><br><span style="color: hsl(120, 100%, 40%);">+    LOGFILE = 'srsue.log'</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, suite_run, conf):</span><br><span style="color: hsl(120, 100%, 40%);">+        self._addr = conf.get('addr', None)</span><br><span style="color: hsl(120, 100%, 40%);">+        if self._addr is None:</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error('addr not set')</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__('srsue_%s' % self._addr, conf)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.enb = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.run_dir = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.config_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.pcap_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_config_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_log_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_pcap_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.suite_run = suite_run</span><br><span style="color: hsl(120, 100%, 40%);">+        self.nof_prb=50</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.nof_prb == 75:</span><br><span style="color: hsl(120, 100%, 40%);">+          self.base_srate=15.36e6</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+          self.base_srate=23.04e6</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_user = conf.get('remote_user', None)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def cleanup(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.process is None:</span><br><span style="color: hsl(120, 100%, 40%);">+            return</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.setup_runs_locally():</span><br><span style="color: hsl(120, 100%, 40%);">+            return</span><br><span style="color: hsl(120, 100%, 40%);">+        # copy back files (may not exist, for instance if there was an early error of process):</span><br><span style="color: hsl(120, 100%, 40%);">+        try:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.rem_host.scpfrom('scp-back-log', self.remote_log_file, self.log_file)</span><br><span style="color: hsl(120, 100%, 40%);">+        except Exception as e:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.log(repr(e))</span><br><span style="color: hsl(120, 100%, 40%);">+        try:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.rem_host.scpfrom('scp-back-pcap', self.remote_pcap_file, self.pcap_file)</span><br><span style="color: hsl(120, 100%, 40%);">+        except Exception as e:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.log(repr(e))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def setup_runs_locally(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        return self.remote_user is None</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def netns(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        return "srsue1"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def connect(self, enb):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log('Starting srsue')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.enb = enb</span><br><span style="color: hsl(120, 100%, 40%);">+        self.run_dir = util.Dir(self.suite_run.get_test_run_dir().new_dir(self.name()))</span><br><span style="color: hsl(120, 100%, 40%);">+        self.configure()</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.setup_runs_locally():</span><br><span style="color: hsl(120, 100%, 40%);">+            self.start_locally()</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.start_remotely()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def start_remotely(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.inst = util.Dir(os.path.abspath(self.suite_run.trial.get_inst('srslte')))</span><br><span style="color: hsl(120, 100%, 40%);">+        lib = self.inst.child('lib')</span><br><span style="color: hsl(120, 100%, 40%);">+        if not os.path.isdir(lib):</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error('No lib/ in', self.inst)</span><br><span style="color: hsl(120, 100%, 40%);">+        if not self.inst.isfile('bin', srsUE.BINFILE):</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error('No %s binary in' % srsUE.BINFILE, self.inst)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host = remote.RemoteHost(self.run_dir, self.remote_user, self._addr)</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_prefix_dir = util.Dir(srsUE.REMOTE_DIR)</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_inst = util.Dir(remote_prefix_dir.child(os.path.basename(str(self.inst))))</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_run_dir = util.Dir(remote_prefix_dir.child(srsUE.BINFILE))</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_config_file = remote_run_dir.child(srsUE.CFGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_log_file = remote_run_dir.child(srsUE.LOGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.remote_pcap_file = remote_run_dir.child(srsUE.PCAPFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.recreate_remote_dir(remote_inst)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.scp('scp-inst-to-remote', str(self.inst), remote_prefix_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.create_remote_dir(remote_run_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.scp('scp-cfg-to-remote', self.config_file, self.remote_config_file)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_lib = remote_inst.child('lib')</span><br><span style="color: hsl(120, 100%, 40%);">+        remote_binary = remote_inst.child('bin', srsUE.BINFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        # setting capabilities will later disable use of LD_LIBRARY_PATH from ELF loader -> modify RPATH instead.</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log('Setting RPATH for srsue')</span><br><span style="color: hsl(120, 100%, 40%);">+        # srsue binary needs patchelf >= 0.9+52 to avoid failing during patch. OS#4389, patchelf-GH#192.</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.set_remote_env({'PATCHELF_BIN': '/opt/bin/patchelf-v0.10' })</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.change_elf_rpath(remote_binary, remote_lib)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        # srsue requires CAP_SYS_ADMIN to cjump to net network namespace: netns(CLONE_NEWNET):</span><br><span style="color: hsl(120, 100%, 40%);">+        # srsue requires CAP_NET_ADMIN to create tunnel devices: ioctl(TUNSETIFF):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log('Applying CAP_SYS_ADMIN+CAP_NET_ADMIN capability to srsue')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.setcap_netsys_admin(remote_binary)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        #'strace', '-ff',</span><br><span style="color: hsl(120, 100%, 40%);">+        args = (remote_binary, self.remote_config_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                '--rf.device_name=zmq',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--rf.device_args="tx_port=tcp://'+ self.addr() +':2001,rx_port=tcp://'+ self.enb.addr() +':2000,id=ue,base_srate='+ str(self.base_srate) + '"',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--phy.nof_phy_threads=1',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--gw.netns=' + self.netns(),</span><br><span style="color: hsl(120, 100%, 40%);">+                '--log.filename=' + 'stdout', #self.remote_log_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                '--pcap.enable=true',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--pcap.filename=' + self.remote_pcap_file)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process = self.rem_host.RemoteProcessFixIgnoreSIGHUP(srsUE.BINFILE, util.Dir(srsUE.REMOTE_DIR), args)</span><br><span style="color: hsl(120, 100%, 40%);">+        #self.process = self.rem_host.RemoteProcessFixIgnoreSIGHUP(srsUE.BINFILE, remote_run_dir, args, remote_lib)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.suite_run.remember_to_stop(self.process)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process.launch()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def start_locally(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        inst = util.Dir(os.path.abspath(self.suite_run.trial.get_inst('srslte')))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        binary = inst.child('bin', BINFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        if not os.path.isfile(binary):</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error('Binary missing:', binary)</span><br><span style="color: hsl(120, 100%, 40%);">+        lib = inst.child('lib')</span><br><span style="color: hsl(120, 100%, 40%);">+        if not os.path.isdir(lib):</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error('No lib/ in', inst)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        env = {}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        # setting capabilities will later disable use of LD_LIBRARY_PATH from ELF loader -> modify RPATH instead.</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log('Setting RPATH for srsue')</span><br><span style="color: hsl(120, 100%, 40%);">+        util.change_elf_rpath(binary, util.prepend_library_path(lib), self.run_dir.new_dir('patchelf'))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        # srsue requires CAP_SYS_ADMIN to cjump to net network namespace: netns(CLONE_NEWNET):</span><br><span style="color: hsl(120, 100%, 40%);">+        # srsue requires CAP_NET_ADMIN to create tunnel devices: ioctl(TUNSETIFF):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log('Applying CAP_SYS_ADMIN+CAP_NET_ADMIN capability to srsue')</span><br><span style="color: hsl(120, 100%, 40%);">+        util.setcap_netsys_admin(binary, self.run_dir.new_dir('setcap_netsys_admin'))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        args = (binary, os.path.abspath(self.config_file),</span><br><span style="color: hsl(120, 100%, 40%);">+                '--rf.device_name=zmq',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--rf.device_args="tx_port=tcp://'+ self.addr() +':2001,rx_port=tcp://'+ self.enb.addr() +':2000,id=ue,base_srate='+ str(self.base_srate) + '"',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--phy.nof_phy_threads=1',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--gw.netns=' + self.netns(),</span><br><span style="color: hsl(120, 100%, 40%);">+                '--log.filename=' + self.log_file,</span><br><span style="color: hsl(120, 100%, 40%);">+                '--pcap.enable=true',</span><br><span style="color: hsl(120, 100%, 40%);">+                '--pcap.filename=' + self.pcap_file)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.dbg(run_dir=self.run_dir, binary=binary, env=env)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process = process.Process(self.name(), self.run_dir, args, env=env)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.suite_run.remember_to_stop(self.process)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process.launch()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def configure(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.config_file = self.run_dir.new_file(srsUE.CFGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log_file = self.run_dir.child(srsUE.LOGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.pcap_file = self.run_dir.new_file(srsUE.PCAPFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.dbg(config_file=self.config_file)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        values = dict(ue=config.get_defaults('srsue'))</span><br><span style="color: hsl(120, 100%, 40%);">+        config.overlay(values, self.suite_run.config())</span><br><span style="color: hsl(120, 100%, 40%);">+        config.overlay(values, dict(ue=self._conf))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.dbg('SRSUE CONFIG:\n' + pprint.pformat(values))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        with open(self.config_file, 'w') as f:</span><br><span style="color: hsl(120, 100%, 40%);">+            r = template.render(srsUE.CFGFILE, values)</span><br><span style="color: hsl(120, 100%, 40%);">+            self.dbg(r)</span><br><span style="color: hsl(120, 100%, 40%);">+            f.write(r)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def is_connected(self, mcc_mnc=None):</span><br><span style="color: hsl(120, 100%, 40%);">+        return 'Network attach successful.' in (self.process.get_stdout() or '')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def is_attached(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        return self.is_connected()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def running(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        return not self.process.terminated()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def addr(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        return self._addr</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def run_node(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        # TODO: move to an object</span><br><span style="color: hsl(120, 100%, 40%);">+        return RunNode(RunNode.T_REM_SSH, self._addr, self.remote_user, self._addr)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def run_netns_wait(self, name, popen_args):</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.setup_runs_locally():</span><br><span style="color: hsl(120, 100%, 40%);">+            proc = process.NetNSProcess(name, self.run_dir.new_dir(name), self.netns(), popen_args, env={})</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+            proc = self.rem_host.RemoteNetNSProcess(name, self.netns(), popen_args, env={})</span><br><span style="color: hsl(120, 100%, 40%);">+        proc.launch_sync()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# vim: expandtab tabstop=4 shiftwidth=4</span><br><span>diff --git a/src/osmo_gsm_tester/suite.py b/src/osmo_gsm_tester/suite.py</span><br><span>index 457bfb3..c2faa36 100644</span><br><span>--- a/src/osmo_gsm_tester/suite.py</span><br><span>+++ b/src/osmo_gsm_tester/suite.py</span><br><span>@@ -25,6 +25,7 @@</span><br><span> from .event_loop import MainLoop</span><br><span> from . import osmo_nitb, osmo_hlr, osmo_mgcpgw, osmo_mgw, osmo_msc, osmo_bsc, osmo_stp, osmo_ggsn, osmo_sgsn, esme, osmocon, ms_driver, iperf3, process</span><br><span> from . import run_node</span><br><span style="color: hsl(120, 100%, 40%);">+from . import srs_epc</span><br><span> </span><br><span> class Timeout(Exception):</span><br><span>     pass</span><br><span>@@ -362,6 +363,18 @@</span><br><span>     def run_node(self, specifics=None):</span><br><span>         return run_node.RunNode.from_conf(self.reserved_resources.get(resource.R_RUN_NODE, specifics=specifics))</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+    def enb(self, specifics=None):</span><br><span style="color: hsl(120, 100%, 40%);">+        enb = enb_obj(self, self.reserved_resources.get(resource.R_ENB, specifics=specifics))</span><br><span style="color: hsl(120, 100%, 40%);">+        self.register_for_cleanup(enb)</span><br><span style="color: hsl(120, 100%, 40%);">+        return enb</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def epc(self, run_node=None):</span><br><span style="color: hsl(120, 100%, 40%);">+        if run_node is None:</span><br><span style="color: hsl(120, 100%, 40%);">+            run_node = self.run_node()</span><br><span style="color: hsl(120, 100%, 40%);">+        epc_obj = srs_epc.srsEPC(self, run_node)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.register_for_cleanup(epc_obj)</span><br><span style="color: hsl(120, 100%, 40%);">+        return epc_obj</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>     def osmocon(self, specifics=None):</span><br><span>         conf = self.reserved_resources.get(resource.R_OSMOCON, specifics=specifics)</span><br><span>         osmocon_obj = osmocon.Osmocon(self, conf=conf)</span><br><span>@@ -481,4 +494,12 @@</span><br><span>         raise RuntimeError('No such BTS type is defined: %r' % bts_type)</span><br><span>     return bts_class(suite_run, conf)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+def enb_obj(suite_run, conf):</span><br><span style="color: hsl(120, 100%, 40%);">+    enb_type = conf.get('type')</span><br><span style="color: hsl(120, 100%, 40%);">+    log.dbg('create ENB object', type=enb_type)</span><br><span style="color: hsl(120, 100%, 40%);">+    enb_class = resource.KNOWN_ENB_TYPES.get(enb_type)</span><br><span style="color: hsl(120, 100%, 40%);">+    if enb_class is None:</span><br><span style="color: hsl(120, 100%, 40%);">+        raise RuntimeError('No such ENB type is defined: %r' % enb_type)</span><br><span style="color: hsl(120, 100%, 40%);">+    return enb_class(suite_run, conf)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> # vim: expandtab tabstop=4 shiftwidth=4</span><br><span>diff --git a/src/osmo_gsm_tester/templates/srsenb.conf.tmpl b/src/osmo_gsm_tester/templates/srsenb.conf.tmpl</span><br><span>new file mode 100644</span><br><span>index 0000000..0eba35b</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo_gsm_tester/templates/srsenb.conf.tmpl</span><br><span>@@ -0,0 +1,279 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+#                   srsENB configuration file</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# eNB configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# enb_id:         20-bit eNB identifier.</span><br><span style="color: hsl(120, 100%, 40%);">+# cell_id:        8-bit cell identifier.</span><br><span style="color: hsl(120, 100%, 40%);">+# tac:            16-bit Tracking Area Code.</span><br><span style="color: hsl(120, 100%, 40%);">+# mcc:            Mobile Country Code</span><br><span style="color: hsl(120, 100%, 40%);">+# mnc:            Mobile Network Code</span><br><span style="color: hsl(120, 100%, 40%);">+# mme_addr:       IP address of MME for S1 connnection</span><br><span style="color: hsl(120, 100%, 40%);">+# gtp_bind_addr:  Local IP address to bind for GTP connection</span><br><span style="color: hsl(120, 100%, 40%);">+# s1c_bind_addr:  Local IP address to bind for S1AP connection</span><br><span style="color: hsl(120, 100%, 40%);">+# n_prb:          Number of Physical Resource Blocks (6,15,25,50,75,100)</span><br><span style="color: hsl(120, 100%, 40%);">+# tm:             Transmission mode 1-4 (TM1 default)</span><br><span style="color: hsl(120, 100%, 40%);">+# nof_ports:      Number of Tx ports (1 port default, set to 2 for TM2/3/4)</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[enb]</span><br><span style="color: hsl(120, 100%, 40%);">+enb_id = 0x19B</span><br><span style="color: hsl(120, 100%, 40%);">+cell_id = 0x01</span><br><span style="color: hsl(120, 100%, 40%);">+phy_cell_id = 1</span><br><span style="color: hsl(120, 100%, 40%);">+tac = 0x0007</span><br><span style="color: hsl(120, 100%, 40%);">+mcc = ${enb.mcc}</span><br><span style="color: hsl(120, 100%, 40%);">+mnc = ${enb.mnc}</span><br><span style="color: hsl(120, 100%, 40%);">+mme_addr = ${enb.mme_addr}</span><br><span style="color: hsl(120, 100%, 40%);">+gtp_bind_addr = ${enb.run_addr}</span><br><span style="color: hsl(120, 100%, 40%);">+s1c_bind_addr = ${enb.run_addr}</span><br><span style="color: hsl(120, 100%, 40%);">+n_prb = 50</span><br><span style="color: hsl(120, 100%, 40%);">+#tm = 4</span><br><span style="color: hsl(120, 100%, 40%);">+#nof_ports = 2</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# eNB configuration files</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# sib_config:  SIB1, SIB2 and SIB3 configuration file</span><br><span style="color: hsl(120, 100%, 40%);">+# note: when enabling mbms, use the sib.conf.mbsfn configuration file which includes SIB13</span><br><span style="color: hsl(120, 100%, 40%);">+# rr_config:   Radio Resources configuration file</span><br><span style="color: hsl(120, 100%, 40%);">+# drb_config:  DRB configuration file</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[enb_files]</span><br><span style="color: hsl(120, 100%, 40%);">+sib_config = sib.conf</span><br><span style="color: hsl(120, 100%, 40%);">+rr_config  = rr.conf</span><br><span style="color: hsl(120, 100%, 40%);">+drb_config = drb.conf</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# RF configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# dl_earfcn: EARFCN code for DL</span><br><span style="color: hsl(120, 100%, 40%);">+# tx_gain: Transmit gain (dB).</span><br><span style="color: hsl(120, 100%, 40%);">+# rx_gain: Optional receive gain (dB). If disabled, AGC if enabled</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Optional parameters:</span><br><span style="color: hsl(120, 100%, 40%);">+# dl_freq:            Override DL frequency corresponding to dl_earfcn</span><br><span style="color: hsl(120, 100%, 40%);">+# ul_freq:            Override UL frequency corresponding to dl_earfcn (must be set if dl_freq is set)</span><br><span style="color: hsl(120, 100%, 40%);">+# device_name:        Device driver family. Supported options: "auto" (uses first found), "UHD" or "bladeRF"</span><br><span style="color: hsl(120, 100%, 40%);">+# device_args:        Arguments for the device driver. Options are "auto" or any string.</span><br><span style="color: hsl(120, 100%, 40%);">+#                     Default for UHD: "recv_frame_size=9232,send_frame_size=9232"</span><br><span style="color: hsl(120, 100%, 40%);">+#                     Default for bladeRF: ""</span><br><span style="color: hsl(120, 100%, 40%);">+# #time_adv_nsamples: Transmission time advance (in number of samples) to compensate for RF delay</span><br><span style="color: hsl(120, 100%, 40%);">+#                     from antenna to timestamp insertion.</span><br><span style="color: hsl(120, 100%, 40%);">+#                     Default "auto". B210 USRP: 100 samples, bladeRF: 27.</span><br><span style="color: hsl(120, 100%, 40%);">+# burst_preamble_us:  Preamble length to transmit before start of burst.</span><br><span style="color: hsl(120, 100%, 40%);">+#                     Default "auto". B210 USRP: 400 us, bladeRF: 0 us.</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[rf]</span><br><span style="color: hsl(120, 100%, 40%);">+dl_earfcn = 3400</span><br><span style="color: hsl(120, 100%, 40%);">+tx_gain = 80</span><br><span style="color: hsl(120, 100%, 40%);">+rx_gain = 40</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#device_name = auto</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# For best performance in 2x2 MIMO and >= 15 MHz use the following device_args settings:</span><br><span style="color: hsl(120, 100%, 40%);">+#     USRP B210: num_recv_frames=64,num_send_frames=64</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# For best performance when BW<5 MHz (25 PRB), use the following device_args settings:</span><br><span style="color: hsl(120, 100%, 40%);">+#     USRP B210: send_frame_size=512,recv_frame_size=512</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#device_args = auto</span><br><span style="color: hsl(120, 100%, 40%);">+#time_adv_nsamples = auto</span><br><span style="color: hsl(120, 100%, 40%);">+#burst_preamble_us = auto</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# MAC-layer packet capture configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Packets are captured to file in the compact format decoded by</span><br><span style="color: hsl(120, 100%, 40%);">+# the Wireshark mac-lte-framed dissector and with DLT 147.</span><br><span style="color: hsl(120, 100%, 40%);">+# To use the dissector, edit the preferences for DLT_USER to</span><br><span style="color: hsl(120, 100%, 40%);">+# add an entry with DLT=147, Payload Protocol=mac-lte-framed.</span><br><span style="color: hsl(120, 100%, 40%);">+# For more information see: https://wiki.wireshark.org/MAC-LTE</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Please note that this setting will by default only capture MAC</span><br><span style="color: hsl(120, 100%, 40%);">+# frames on dedicated channels, and not SIB.  You have to build with</span><br><span style="color: hsl(120, 100%, 40%);">+# WRITE_SIB_PCAP enabled in enb/src/stack/mac/mac.cc if you want</span><br><span style="color: hsl(120, 100%, 40%);">+# SIB to be part of the MAC pcap file.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# enable:   Enable MAC layer packet captures (true/false)</span><br><span style="color: hsl(120, 100%, 40%);">+# filename: File path to use for packet captures</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[pcap]</span><br><span style="color: hsl(120, 100%, 40%);">+enable = false</span><br><span style="color: hsl(120, 100%, 40%);">+filename = /tmp/enb.pcap</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# Log configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Log levels can be set for individual layers. "all_level" sets log</span><br><span style="color: hsl(120, 100%, 40%);">+# level for all layers unless otherwise configured.</span><br><span style="color: hsl(120, 100%, 40%);">+# Format: e.g. phy_level = info</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# In the same way, packet hex dumps can be limited for each level.</span><br><span style="color: hsl(120, 100%, 40%);">+# "all_hex_limit" sets the hex limit for all layers unless otherwise</span><br><span style="color: hsl(120, 100%, 40%);">+# configured.</span><br><span style="color: hsl(120, 100%, 40%);">+# Format: e.g. phy_hex_limit = 32</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Logging layers: rf, phy, phy_lib, mac, rlc, pdcp, rrc, gtpu, s1ap, all</span><br><span style="color: hsl(120, 100%, 40%);">+# Logging levels: debug, info, warning, error, none</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# filename: File path to use for log output. Can be set to stdout</span><br><span style="color: hsl(120, 100%, 40%);">+#           to print logs to standard output</span><br><span style="color: hsl(120, 100%, 40%);">+# file_max_size: Maximum file size (in kilobytes). When passed, multiple files are created.</span><br><span style="color: hsl(120, 100%, 40%);">+#                If set to negative, a single log file will be created.</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[log]</span><br><span style="color: hsl(120, 100%, 40%);">+all_level = warning</span><br><span style="color: hsl(120, 100%, 40%);">+all_hex_limit = 32</span><br><span style="color: hsl(120, 100%, 40%);">+filename = /tmp/enb.log</span><br><span style="color: hsl(120, 100%, 40%);">+file_max_size = -1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[gui]</span><br><span style="color: hsl(120, 100%, 40%);">+enable = false</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# Scheduler configuration options</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# max_aggr_level:    Optional maximum aggregation level index (l=log2(L) can be 0, 1, 2 or 3)</span><br><span style="color: hsl(120, 100%, 40%);">+# pdsch_mcs:         Optional fixed PDSCH MCS (ignores reported CQIs if specified)</span><br><span style="color: hsl(120, 100%, 40%);">+# pdsch_max_mcs:     Optional PDSCH MCS limit</span><br><span style="color: hsl(120, 100%, 40%);">+# pusch_mcs:         Optional fixed PUSCH MCS (ignores reported CQIs if specified)</span><br><span style="color: hsl(120, 100%, 40%);">+# pusch_max_mcs:     Optional PUSCH MCS limit</span><br><span style="color: hsl(120, 100%, 40%);">+# #nof_ctrl_symbols: Number of control symbols</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[scheduler]</span><br><span style="color: hsl(120, 100%, 40%);">+#max_aggr_level   = -1</span><br><span style="color: hsl(120, 100%, 40%);">+#pdsch_mcs        = -1</span><br><span style="color: hsl(120, 100%, 40%);">+#pdsch_max_mcs    = -1</span><br><span style="color: hsl(120, 100%, 40%);">+#pusch_mcs        = -1</span><br><span style="color: hsl(120, 100%, 40%);">+pusch_max_mcs    = 16</span><br><span style="color: hsl(120, 100%, 40%);">+nof_ctrl_symbols = 3</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# eMBMS configuration options</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# enable:               Enable MBMS transmission in the eNB</span><br><span style="color: hsl(120, 100%, 40%);">+# m1u_multiaddr:        Multicast addres the M1-U socket will register to</span><br><span style="color: hsl(120, 100%, 40%);">+# m1u_if_addr:          Address of the inteferface the M1-U interface will listen for multicast packets.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[embms]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable = false</span><br><span style="color: hsl(120, 100%, 40%);">+#m1u_multiaddr = 239.255.0.1</span><br><span style="color: hsl(120, 100%, 40%);">+#m1u_if_addr = 127.0.1.201</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# Channel emulator options:</span><br><span style="color: hsl(120, 100%, 40%);">+# enable:            Enable/Disable internal Downlink/Uplink channel emulator</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# -- Fading emulator</span><br><span style="color: hsl(120, 100%, 40%);">+# fading.enable:     Enable/disable fading simulator</span><br><span style="color: hsl(120, 100%, 40%);">+# fading.model:      Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc)</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# -- Delay Emulator     delay(t) = delay_min + (delay_max - delay_min) * (1 + sin(2pi*t/period)) / 2</span><br><span style="color: hsl(120, 100%, 40%);">+#                       Maximum speed [m/s]: (delay_max - delay_min) * pi * 300 / period</span><br><span style="color: hsl(120, 100%, 40%);">+# delay.enable:      Enable/disable delay simulator</span><br><span style="color: hsl(120, 100%, 40%);">+# delay.period_s:    Delay period in seconds.</span><br><span style="color: hsl(120, 100%, 40%);">+# delay.init_time_s: Delay initial time in seconds.</span><br><span style="color: hsl(120, 100%, 40%);">+# delay.maximum_us:  Maximum delay in microseconds</span><br><span style="color: hsl(120, 100%, 40%);">+# delay.minumum_us:  Minimum delay in microseconds</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# -- Radio-Link Failure (RLF) Emulator</span><br><span style="color: hsl(120, 100%, 40%);">+# rlf.enable:        Enable/disable RLF simulator</span><br><span style="color: hsl(120, 100%, 40%);">+# rlf.t_on_ms:       Time for On state of the channel (ms)</span><br><span style="color: hsl(120, 100%, 40%);">+# rlf.t_off_ms:      Time for Off state of the channel (ms)</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# -- High Speed Train Doppler model simulator</span><br><span style="color: hsl(120, 100%, 40%);">+# hst.enable:        Enable/Disable HST simulator</span><br><span style="color: hsl(120, 100%, 40%);">+# hst.period_s:      HST simulation period in seconds</span><br><span style="color: hsl(120, 100%, 40%);">+# hst.fd_hz:         Doppler frequency in Hz</span><br><span style="color: hsl(120, 100%, 40%);">+# hst.init_time_s:   Initial time in seconds</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.dl]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.dl.fading]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+#model         = none</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.dl.delay]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+#period_s      = 3600</span><br><span style="color: hsl(120, 100%, 40%);">+#init_time_s   = 0</span><br><span style="color: hsl(120, 100%, 40%);">+#maximum_us    = 100</span><br><span style="color: hsl(120, 100%, 40%);">+#minimum_us    = 10</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.dl.rlf]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+#t_on_ms       = 10000</span><br><span style="color: hsl(120, 100%, 40%);">+#t_off_ms      = 2000</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.dl.hst]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+#period_s      = 7.2</span><br><span style="color: hsl(120, 100%, 40%);">+#fd_hz         = 750.0</span><br><span style="color: hsl(120, 100%, 40%);">+#init_time_s   = 0.0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.ul]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.ul.fading]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+#model         = none</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.ul.delay]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+#period_s      = 3600</span><br><span style="color: hsl(120, 100%, 40%);">+#init_time_s   = 0</span><br><span style="color: hsl(120, 100%, 40%);">+#maximum_us    = 100</span><br><span style="color: hsl(120, 100%, 40%);">+#minimum_us    = 10</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.ul.rlf]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+#t_on_ms       = 10000</span><br><span style="color: hsl(120, 100%, 40%);">+#t_off_ms      = 2000</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.ul.hst]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+#period_s      = 7.2</span><br><span style="color: hsl(120, 100%, 40%);">+#fd_hz         = -750.0</span><br><span style="color: hsl(120, 100%, 40%);">+#init_time_s   = 0.0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# Expert configuration options</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# pusch_max_its:        Maximum number of turbo decoder iterations (Default 4)</span><br><span style="color: hsl(120, 100%, 40%);">+# pusch_8bit_decoder:   Use 8-bit for LLR representation and turbo decoder trellis computation (Experimental)</span><br><span style="color: hsl(120, 100%, 40%);">+# nof_phy_threads:      Selects the number of PHY threads (maximum 4, minimum 1, default 2)</span><br><span style="color: hsl(120, 100%, 40%);">+# metrics_period_secs:  Sets the period at which metrics are requested from the eNB.</span><br><span style="color: hsl(120, 100%, 40%);">+# metrics_csv_enable:   Write eNB metrics to CSV file.</span><br><span style="color: hsl(120, 100%, 40%);">+# metrics_csv_filename: File path to use for CSV metrics.</span><br><span style="color: hsl(120, 100%, 40%);">+# pregenerate_signals:  Pregenerate uplink signals after attach. Improves CPU performance.</span><br><span style="color: hsl(120, 100%, 40%);">+# tx_amplitude:         Transmit amplitude factor (set 0-1 to reduce PAPR)</span><br><span style="color: hsl(120, 100%, 40%);">+# link_failure_nof_err: Number of PUSCH failures after which a radio-link failure is triggered.</span><br><span style="color: hsl(120, 100%, 40%);">+#                       a link failure is when SNR<0 and CRC=KO</span><br><span style="color: hsl(120, 100%, 40%);">+# max_prach_offset_us:  Maximum allowed RACH offset (in us)</span><br><span style="color: hsl(120, 100%, 40%);">+# eea_pref_list:        Ordered preference list for the selection of encryption algorithm (EEA) (default: EEA0, EEA2, EEA1).</span><br><span style="color: hsl(120, 100%, 40%);">+# eia_pref_list:        Ordered preference list for the selection of integrity algorithm (EIA) (default: EIA2, EIA1, EIA0).</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[expert]</span><br><span style="color: hsl(120, 100%, 40%);">+#pusch_max_its        = 8 # These are half iterations</span><br><span style="color: hsl(120, 100%, 40%);">+#pusch_8bit_decoder   = false</span><br><span style="color: hsl(120, 100%, 40%);">+#nof_phy_threads      = 3</span><br><span style="color: hsl(120, 100%, 40%);">+#metrics_period_secs  = 1</span><br><span style="color: hsl(120, 100%, 40%);">+#metrics_csv_enable   = false</span><br><span style="color: hsl(120, 100%, 40%);">+#metrics_csv_filename = /tmp/enb_metrics.csv</span><br><span style="color: hsl(120, 100%, 40%);">+#pregenerate_signals  = false</span><br><span style="color: hsl(120, 100%, 40%);">+#tx_amplitude         = 0.6</span><br><span style="color: hsl(120, 100%, 40%);">+#link_failure_nof_err = 50</span><br><span style="color: hsl(120, 100%, 40%);">+#rrc_inactivity_timer = 60000</span><br><span style="color: hsl(120, 100%, 40%);">+#max_prach_offset_us  = 30</span><br><span style="color: hsl(120, 100%, 40%);">+#eea_pref_list = EEA0, EEA2, EEA1</span><br><span style="color: hsl(120, 100%, 40%);">+#eia_pref_list = EIA2, EIA1, EIA0</span><br><span>diff --git a/src/osmo_gsm_tester/templates/srsenb_drb.conf.tmpl b/src/osmo_gsm_tester/templates/srsenb_drb.conf.tmpl</span><br><span>new file mode 100644</span><br><span>index 0000000..32b6e93</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo_gsm_tester/templates/srsenb_drb.conf.tmpl</span><br><span>@@ -0,0 +1,54 @@</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+// All times are in ms. Use -1 for infinity, where available</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+qci_config = (</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  qci=7;</span><br><span style="color: hsl(120, 100%, 40%);">+  pdcp_config = {</span><br><span style="color: hsl(120, 100%, 40%);">+    discard_timer = 100;                </span><br><span style="color: hsl(120, 100%, 40%);">+    pdcp_sn_size = 12;                  </span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  rlc_config = {</span><br><span style="color: hsl(120, 100%, 40%);">+    ul_um = {</span><br><span style="color: hsl(120, 100%, 40%);">+      sn_field_length = 10; </span><br><span style="color: hsl(120, 100%, 40%);">+    };</span><br><span style="color: hsl(120, 100%, 40%);">+    dl_um = {</span><br><span style="color: hsl(120, 100%, 40%);">+      sn_field_length = 10; </span><br><span style="color: hsl(120, 100%, 40%);">+      t_reordering    = 45;             </span><br><span style="color: hsl(120, 100%, 40%);">+    };</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+  logical_channel_config = {</span><br><span style="color: hsl(120, 100%, 40%);">+    priority = 13; </span><br><span style="color: hsl(120, 100%, 40%);">+    prioritized_bit_rate   = -1; </span><br><span style="color: hsl(120, 100%, 40%);">+    bucket_size_duration  = 100; </span><br><span style="color: hsl(120, 100%, 40%);">+    log_chan_group = 2; </span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+},</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  qci=9;</span><br><span style="color: hsl(120, 100%, 40%);">+  pdcp_config = {</span><br><span style="color: hsl(120, 100%, 40%);">+    discard_timer = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    status_report_required = true;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  rlc_config = {</span><br><span style="color: hsl(120, 100%, 40%);">+    ul_am = {</span><br><span style="color: hsl(120, 100%, 40%);">+      t_poll_retx = 120;</span><br><span style="color: hsl(120, 100%, 40%);">+      poll_pdu = 64;</span><br><span style="color: hsl(120, 100%, 40%);">+      poll_byte = 750;</span><br><span style="color: hsl(120, 100%, 40%);">+      max_retx_thresh = 16;</span><br><span style="color: hsl(120, 100%, 40%);">+    };</span><br><span style="color: hsl(120, 100%, 40%);">+    dl_am = {</span><br><span style="color: hsl(120, 100%, 40%);">+      t_reordering = 50;</span><br><span style="color: hsl(120, 100%, 40%);">+      t_status_prohibit = 50;</span><br><span style="color: hsl(120, 100%, 40%);">+    };</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+  logical_channel_config = {</span><br><span style="color: hsl(120, 100%, 40%);">+    priority = 11; </span><br><span style="color: hsl(120, 100%, 40%);">+    prioritized_bit_rate   = -1; </span><br><span style="color: hsl(120, 100%, 40%);">+    bucket_size_duration  = 100; </span><br><span style="color: hsl(120, 100%, 40%);">+    log_chan_group = 3; </span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+);</span><br><span>diff --git a/src/osmo_gsm_tester/templates/srsenb_rr.conf.tmpl b/src/osmo_gsm_tester/templates/srsenb_rr.conf.tmpl</span><br><span>new file mode 100644</span><br><span>index 0000000..1fff189</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo_gsm_tester/templates/srsenb_rr.conf.tmpl</span><br><span>@@ -0,0 +1,90 @@</span><br><span style="color: hsl(120, 100%, 40%);">+mac_cnfg =</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  phr_cnfg = </span><br><span style="color: hsl(120, 100%, 40%);">+  {</span><br><span style="color: hsl(120, 100%, 40%);">+    dl_pathloss_change = "dB3"; // Valid: 1, 3, 6 or INFINITY</span><br><span style="color: hsl(120, 100%, 40%);">+    periodic_phr_timer = 50;</span><br><span style="color: hsl(120, 100%, 40%);">+    prohibit_phr_timer = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+  ulsch_cnfg = </span><br><span style="color: hsl(120, 100%, 40%);">+  {</span><br><span style="color: hsl(120, 100%, 40%);">+    max_harq_tx = 4;</span><br><span style="color: hsl(120, 100%, 40%);">+    periodic_bsr_timer = 20; // in ms</span><br><span style="color: hsl(120, 100%, 40%);">+    retx_bsr_timer = 320;   // in ms</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+  </span><br><span style="color: hsl(120, 100%, 40%);">+  time_alignment_timer = -1; // -1 is infinity</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+phy_cnfg =</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  phich_cnfg = </span><br><span style="color: hsl(120, 100%, 40%);">+  {</span><br><span style="color: hsl(120, 100%, 40%);">+    duration  = "Normal";</span><br><span style="color: hsl(120, 100%, 40%);">+    resources = "1/6"; </span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  pusch_cnfg_ded =</span><br><span style="color: hsl(120, 100%, 40%);">+  {</span><br><span style="color: hsl(120, 100%, 40%);">+    beta_offset_ack_idx = 6;</span><br><span style="color: hsl(120, 100%, 40%);">+    beta_offset_ri_idx  = 6;</span><br><span style="color: hsl(120, 100%, 40%);">+    beta_offset_cqi_idx = 6;</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+  </span><br><span style="color: hsl(120, 100%, 40%);">+  // PUCCH-SR resources are scheduled on time-frequeny domain first, then multiplexed in the same resource. </span><br><span style="color: hsl(120, 100%, 40%);">+  sched_request_cnfg =</span><br><span style="color: hsl(120, 100%, 40%);">+  {</span><br><span style="color: hsl(120, 100%, 40%);">+    dsr_trans_max = 64;</span><br><span style="color: hsl(120, 100%, 40%);">+    period = 20;       // in ms</span><br><span style="color: hsl(120, 100%, 40%);">+    subframe = [1];    // vector of subframe indices allowed for SR transmissions </span><br><span style="color: hsl(120, 100%, 40%);">+    nof_prb = 2;       // number of PRBs on each extreme used for SR (total prb is twice this number)</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+  cqi_report_cnfg =</span><br><span style="color: hsl(120, 100%, 40%);">+  { </span><br><span style="color: hsl(120, 100%, 40%);">+    mode = "periodic";</span><br><span style="color: hsl(120, 100%, 40%);">+    simultaneousAckCQI = true; </span><br><span style="color: hsl(120, 100%, 40%);">+    period = 40; // in ms</span><br><span style="color: hsl(120, 100%, 40%);">+    subframe = [0];</span><br><span style="color: hsl(120, 100%, 40%);">+    nof_prb = 2; </span><br><span style="color: hsl(120, 100%, 40%);">+    m_ri = 8; // RI period in CQI period</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+cell_list =</span><br><span style="color: hsl(120, 100%, 40%);">+(</span><br><span style="color: hsl(120, 100%, 40%);">+  {</span><br><span style="color: hsl(120, 100%, 40%);">+    // rf_port = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    // cell_id = 0x01;</span><br><span style="color: hsl(120, 100%, 40%);">+    // tac = 0x0001;</span><br><span style="color: hsl(120, 100%, 40%);">+    // pci = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+    // root_seq_idx = 204;</span><br><span style="color: hsl(120, 100%, 40%);">+    // dl_earfcn = 3400;</span><br><span style="color: hsl(120, 100%, 40%);">+    // ul_earfcn = 474;</span><br><span style="color: hsl(120, 100%, 40%);">+    ho_active = false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    // CA cells</span><br><span style="color: hsl(120, 100%, 40%);">+    scell_list = (</span><br><span style="color: hsl(120, 100%, 40%);">+      {cell_id = 0x02; cross_carrier_scheduling = false; scheduling_cell_id = 0x02; ul_allowed = true}</span><br><span style="color: hsl(120, 100%, 40%);">+    )</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    // Cells available for handover</span><br><span style="color: hsl(120, 100%, 40%);">+    meas_cell_list =</span><br><span style="color: hsl(120, 100%, 40%);">+    (</span><br><span style="color: hsl(120, 100%, 40%);">+      {</span><br><span style="color: hsl(120, 100%, 40%);">+        eci = 0x19C02;</span><br><span style="color: hsl(120, 100%, 40%);">+        dl_earfcn = 2850;</span><br><span style="color: hsl(120, 100%, 40%);">+        pci = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+    );</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    // ReportCfg (only A3 supported)</span><br><span style="color: hsl(120, 100%, 40%);">+    meas_report_desc = {</span><br><span style="color: hsl(120, 100%, 40%);">+      a3_report_type = "RSRP";</span><br><span style="color: hsl(120, 100%, 40%);">+      a3_offset = 6;</span><br><span style="color: hsl(120, 100%, 40%);">+      a3_hysteresis = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      a3_time_to_trigger = 480;</span><br><span style="color: hsl(120, 100%, 40%);">+      rsrq_config = 4;</span><br><span style="color: hsl(120, 100%, 40%);">+    };</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+  // Add here more cells</span><br><span style="color: hsl(120, 100%, 40%);">+);</span><br><span>diff --git a/src/osmo_gsm_tester/templates/srsenb_sib.conf.tmpl b/src/osmo_gsm_tester/templates/srsenb_sib.conf.tmpl</span><br><span>new file mode 100644</span><br><span>index 0000000..201d022</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo_gsm_tester/templates/srsenb_sib.conf.tmpl</span><br><span>@@ -0,0 +1,118 @@</span><br><span style="color: hsl(120, 100%, 40%);">+sib1 =</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    intra_freq_reselection = "Allowed";</span><br><span style="color: hsl(120, 100%, 40%);">+    q_rx_lev_min = -65;</span><br><span style="color: hsl(120, 100%, 40%);">+    //p_max = 3;</span><br><span style="color: hsl(120, 100%, 40%);">+    cell_barred = "NotBarred"</span><br><span style="color: hsl(120, 100%, 40%);">+    si_window_length = 20;</span><br><span style="color: hsl(120, 100%, 40%);">+    sched_info =</span><br><span style="color: hsl(120, 100%, 40%);">+    (</span><br><span style="color: hsl(120, 100%, 40%);">+        {</span><br><span style="color: hsl(120, 100%, 40%);">+            si_periodicity = 16;</span><br><span style="color: hsl(120, 100%, 40%);">+            si_mapping_info = []; // comma-separated array of SIB-indexes (from 3 to 13). </span><br><span style="color: hsl(120, 100%, 40%);">+            // Leave empty or commented to just scheduler sib2</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+    );</span><br><span style="color: hsl(120, 100%, 40%);">+    system_info_value_tag = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+sib2 = </span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    rr_config_common_sib =</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+        rach_cnfg = </span><br><span style="color: hsl(120, 100%, 40%);">+        {</span><br><span style="color: hsl(120, 100%, 40%);">+            num_ra_preambles = 52;</span><br><span style="color: hsl(120, 100%, 40%);">+            preamble_init_rx_target_pwr = -104;</span><br><span style="color: hsl(120, 100%, 40%);">+            pwr_ramping_step = 6;  // in dB</span><br><span style="color: hsl(120, 100%, 40%);">+            preamble_trans_max = 10;</span><br><span style="color: hsl(120, 100%, 40%);">+            ra_resp_win_size = 10;  // in ms</span><br><span style="color: hsl(120, 100%, 40%);">+            mac_con_res_timer = 64; // in ms</span><br><span style="color: hsl(120, 100%, 40%);">+            max_harq_msg3_tx = 4;</span><br><span style="color: hsl(120, 100%, 40%);">+        };</span><br><span style="color: hsl(120, 100%, 40%);">+        bcch_cnfg = </span><br><span style="color: hsl(120, 100%, 40%);">+        {</span><br><span style="color: hsl(120, 100%, 40%);">+            modification_period_coeff = 16; // in ms</span><br><span style="color: hsl(120, 100%, 40%);">+        };</span><br><span style="color: hsl(120, 100%, 40%);">+        pcch_cnfg = </span><br><span style="color: hsl(120, 100%, 40%);">+        {</span><br><span style="color: hsl(120, 100%, 40%);">+            default_paging_cycle = 32; // in rf</span><br><span style="color: hsl(120, 100%, 40%);">+            nB = "1";</span><br><span style="color: hsl(120, 100%, 40%);">+        };</span><br><span style="color: hsl(120, 100%, 40%);">+        prach_cnfg =</span><br><span style="color: hsl(120, 100%, 40%);">+        {</span><br><span style="color: hsl(120, 100%, 40%);">+            root_sequence_index = 128;</span><br><span style="color: hsl(120, 100%, 40%);">+            prach_cnfg_info =</span><br><span style="color: hsl(120, 100%, 40%);">+            {</span><br><span style="color: hsl(120, 100%, 40%);">+                high_speed_flag = false;</span><br><span style="color: hsl(120, 100%, 40%);">+                prach_config_index = 3;</span><br><span style="color: hsl(120, 100%, 40%);">+                prach_freq_offset = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+                zero_correlation_zone_config = 5;</span><br><span style="color: hsl(120, 100%, 40%);">+            };</span><br><span style="color: hsl(120, 100%, 40%);">+        };</span><br><span style="color: hsl(120, 100%, 40%);">+        pdsch_cnfg = </span><br><span style="color: hsl(120, 100%, 40%);">+        {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* Warning: Currently disabled and forced to p_b=1 for TM2/3/4 and p_b=0 for TM1</span><br><span style="color: hsl(120, 100%, 40%);">+             */</span><br><span style="color: hsl(120, 100%, 40%);">+            p_b = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+            rs_power = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        };</span><br><span style="color: hsl(120, 100%, 40%);">+        pusch_cnfg = </span><br><span style="color: hsl(120, 100%, 40%);">+        {</span><br><span style="color: hsl(120, 100%, 40%);">+            n_sb = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+            hopping_mode = "inter-subframe";</span><br><span style="color: hsl(120, 100%, 40%);">+            pusch_hopping_offset = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+            enable_64_qam = false; // 64QAM PUSCH is not currently enabled</span><br><span style="color: hsl(120, 100%, 40%);">+            ul_rs = </span><br><span style="color: hsl(120, 100%, 40%);">+            {</span><br><span style="color: hsl(120, 100%, 40%);">+                cyclic_shift = 0; </span><br><span style="color: hsl(120, 100%, 40%);">+                group_assignment_pusch = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                group_hopping_enabled = false; </span><br><span style="color: hsl(120, 100%, 40%);">+                sequence_hopping_enabled = false; </span><br><span style="color: hsl(120, 100%, 40%);">+            };</span><br><span style="color: hsl(120, 100%, 40%);">+        };</span><br><span style="color: hsl(120, 100%, 40%);">+        pucch_cnfg =</span><br><span style="color: hsl(120, 100%, 40%);">+        {</span><br><span style="color: hsl(120, 100%, 40%);">+            delta_pucch_shift = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+            n_rb_cqi = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+            n_cs_an = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+            n1_pucch_an = 12;</span><br><span style="color: hsl(120, 100%, 40%);">+        };</span><br><span style="color: hsl(120, 100%, 40%);">+        ul_pwr_ctrl =</span><br><span style="color: hsl(120, 100%, 40%);">+        {</span><br><span style="color: hsl(120, 100%, 40%);">+            p0_nominal_pusch = -85;</span><br><span style="color: hsl(120, 100%, 40%);">+            alpha = 0.7;</span><br><span style="color: hsl(120, 100%, 40%);">+            p0_nominal_pucch = -107;</span><br><span style="color: hsl(120, 100%, 40%);">+            delta_flist_pucch =</span><br><span style="color: hsl(120, 100%, 40%);">+            {</span><br><span style="color: hsl(120, 100%, 40%);">+                format_1  = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+                format_1b = 3; </span><br><span style="color: hsl(120, 100%, 40%);">+                format_2  = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                format_2a = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+                format_2b = 2;</span><br><span style="color: hsl(120, 100%, 40%);">+            };</span><br><span style="color: hsl(120, 100%, 40%);">+            delta_preamble_msg3 = 6;</span><br><span style="color: hsl(120, 100%, 40%);">+        };</span><br><span style="color: hsl(120, 100%, 40%);">+        ul_cp_length = "len1";</span><br><span style="color: hsl(120, 100%, 40%);">+    };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    ue_timers_and_constants =</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+        t300 = 2000; // in ms</span><br><span style="color: hsl(120, 100%, 40%);">+        t301 = 100;  // in ms</span><br><span style="color: hsl(120, 100%, 40%);">+        t310 = 1000; // in ms</span><br><span style="color: hsl(120, 100%, 40%);">+        n310 = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+        t311 = 1000; // in ms</span><br><span style="color: hsl(120, 100%, 40%);">+        n311 = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+    };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    freqInfo = </span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+        ul_carrier_freq_present = true; </span><br><span style="color: hsl(120, 100%, 40%);">+        ul_bw_present = true; </span><br><span style="color: hsl(120, 100%, 40%);">+        additional_spectrum_emission = 1; </span><br><span style="color: hsl(120, 100%, 40%);">+    };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    time_alignment_timer = "INFINITY"; // use "sf500", "sf750", etc.</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/src/osmo_gsm_tester/templates/srsepc.conf.tmpl b/src/osmo_gsm_tester/templates/srsepc.conf.tmpl</span><br><span>new file mode 100644</span><br><span>index 0000000..8acd22f</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo_gsm_tester/templates/srsepc.conf.tmpl</span><br><span>@@ -0,0 +1,106 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+#                   srsEPC configuration file</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# MME configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# mme_code:         8-bit MME code identifies the MME within a group.</span><br><span style="color: hsl(120, 100%, 40%);">+# mme_group:        16-bit MME group identifier.</span><br><span style="color: hsl(120, 100%, 40%);">+# tac:              16-bit Tracking Area Code.</span><br><span style="color: hsl(120, 100%, 40%);">+# mcc:              Mobile Country Code</span><br><span style="color: hsl(120, 100%, 40%);">+# mnc:              Mobile Network Code</span><br><span style="color: hsl(120, 100%, 40%);">+# apn:                          Set Access Point Name (APN)</span><br><span style="color: hsl(120, 100%, 40%);">+# mme_bind_addr:    IP bind addr to listen for eNB S1-MME connnections</span><br><span style="color: hsl(120, 100%, 40%);">+# dns_addr:         DNS server address for the UEs</span><br><span style="color: hsl(120, 100%, 40%);">+# encryption_algo:  Preferred encryption algorithm for NAS layer</span><br><span style="color: hsl(120, 100%, 40%);">+#                   (default: EEA0, support: EEA1, EEA2)</span><br><span style="color: hsl(120, 100%, 40%);">+# integrity_algo:   Preferred integrity protection algorithm for NAS</span><br><span style="color: hsl(120, 100%, 40%);">+#                   (default: EIA1, support: EIA1, EIA2 (EIA0 not support)</span><br><span style="color: hsl(120, 100%, 40%);">+# paging_timer:     Value of paging timer in seconds (T3413)</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[mme]</span><br><span style="color: hsl(120, 100%, 40%);">+mme_code = 0x1a</span><br><span style="color: hsl(120, 100%, 40%);">+mme_group = 0x0001</span><br><span style="color: hsl(120, 100%, 40%);">+tac = 0x0007</span><br><span style="color: hsl(120, 100%, 40%);">+mcc = ${epc.mcc}</span><br><span style="color: hsl(120, 100%, 40%);">+mnc = ${epc.mnc}</span><br><span style="color: hsl(120, 100%, 40%);">+mme_bind_addr = ${epc.run_addr}</span><br><span style="color: hsl(120, 100%, 40%);">+apn = srsapn</span><br><span style="color: hsl(120, 100%, 40%);">+dns_addr = 8.8.8.8</span><br><span style="color: hsl(120, 100%, 40%);">+encryption_algo = EEA0</span><br><span style="color: hsl(120, 100%, 40%);">+integrity_algo = EIA1</span><br><span style="color: hsl(120, 100%, 40%);">+paging_timer = 2</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# HSS configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# db_file:         Location of .csv file that stores UEs information.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[hss]</span><br><span style="color: hsl(120, 100%, 40%);">+db_file = user_db.csv</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# SP-GW configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# gtpu_bind_addr:   GTP-U bind address.</span><br><span style="color: hsl(120, 100%, 40%);">+# sgi_if_addr:      SGi TUN interface IP address.</span><br><span style="color: hsl(120, 100%, 40%);">+# sgi_if_name:      SGi TUN interface name.</span><br><span style="color: hsl(120, 100%, 40%);">+# max_paging_queue: Maximum packets in paging queue (per UE).</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[spgw]</span><br><span style="color: hsl(120, 100%, 40%);">+gtpu_bind_addr   = ${epc.run_addr}</span><br><span style="color: hsl(120, 100%, 40%);">+sgi_if_addr      = 172.16.0.1</span><br><span style="color: hsl(120, 100%, 40%);">+sgi_if_name      = srs_spgw_sgi</span><br><span style="color: hsl(120, 100%, 40%);">+max_paging_queue = 100</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# PCAP configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Packets are captured to file in the compact format decoded by</span><br><span style="color: hsl(120, 100%, 40%);">+# the Wireshark s1ap dissector and with DLT 150.</span><br><span style="color: hsl(120, 100%, 40%);">+# To use the dissector, edit the preferences for DLT_USER to</span><br><span style="color: hsl(120, 100%, 40%);">+# add an entry with DLT=150, Payload Protocol=s1ap.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# enable:   Enable or disable the PCAP.</span><br><span style="color: hsl(120, 100%, 40%);">+# filename: File name where to save the PCAP.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[pcap]</span><br><span style="color: hsl(120, 100%, 40%);">+enable   = false</span><br><span style="color: hsl(120, 100%, 40%);">+filename = /tmp/epc.pcap</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# Log configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Log levels can be set for individual layers. "all_level" sets log</span><br><span style="color: hsl(120, 100%, 40%);">+# level for all layers unless otherwise configured.</span><br><span style="color: hsl(120, 100%, 40%);">+# Format: e.g. s1ap_level = info</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# In the same way, packet hex dumps can be limited for each level.</span><br><span style="color: hsl(120, 100%, 40%);">+# "all_hex_limit" sets the hex limit for all layers unless otherwise</span><br><span style="color: hsl(120, 100%, 40%);">+# configured.</span><br><span style="color: hsl(120, 100%, 40%);">+# Format: e.g. s1ap_hex_limit = 32</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Logging layers: nas, s1ap, mme_gtpc, spgw_gtpc, gtpu, spgw, hss, all</span><br><span style="color: hsl(120, 100%, 40%);">+# Logging levels: debug, info, warning, error, none</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# filename: File path to use for log output. Can be set to stdout</span><br><span style="color: hsl(120, 100%, 40%);">+#           to print logs to standard output</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[log]</span><br><span style="color: hsl(120, 100%, 40%);">+all_level = info</span><br><span style="color: hsl(120, 100%, 40%);">+all_hex_limit = 32</span><br><span style="color: hsl(120, 100%, 40%);">+filename = /tmp/epc.log</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#nas_level = debug</span><br><span style="color: hsl(120, 100%, 40%);">+#s1ap_level = debug</span><br><span style="color: hsl(120, 100%, 40%);">+#mme_gtpc_level = debug</span><br><span style="color: hsl(120, 100%, 40%);">+#spgw_gtpc_level = debug</span><br><span style="color: hsl(120, 100%, 40%);">+#gtpu_level = debug</span><br><span style="color: hsl(120, 100%, 40%);">+#spgw_level = debug</span><br><span style="color: hsl(120, 100%, 40%);">+#hss_level = debug</span><br><span>diff --git a/src/osmo_gsm_tester/templates/srsepc_user_db.csv.tmpl b/src/osmo_gsm_tester/templates/srsepc_user_db.csv.tmpl</span><br><span>new file mode 100644</span><br><span>index 0000000..32df58d</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo_gsm_tester/templates/srsepc_user_db.csv.tmpl</span><br><span>@@ -0,0 +1,24 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# .csv to store UE's information in HSS</span><br><span style="color: hsl(120, 100%, 40%);">+# Kept in the following format: "Name,Auth,IMSI,Key,OP_Type,OP,AMF,SQN,QCI,IP_alloc"</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Name:     Human readable name to help distinguish UE's. Ignored by the HSS</span><br><span style="color: hsl(120, 100%, 40%);">+# IMSI:     UE's IMSI value</span><br><span style="color: hsl(120, 100%, 40%);">+# Auth:     Authentication algorithm used by the UE. Valid algorithms are XOR</span><br><span style="color: hsl(120, 100%, 40%);">+#           (xor) and MILENAGE (mil)</span><br><span style="color: hsl(120, 100%, 40%);">+# Key:      UE's key, where other keys are derived from. Stored in hexadecimal</span><br><span style="color: hsl(120, 100%, 40%);">+# OP_Type:  Operator's code type, either OP or OPc</span><br><span style="color: hsl(120, 100%, 40%);">+# OP/OPc:   Operator Code/Cyphered Operator Code, stored in hexadecimal</span><br><span style="color: hsl(120, 100%, 40%);">+# AMF:      Authentication management field, stored in hexadecimal</span><br><span style="color: hsl(120, 100%, 40%);">+# SQN:      UE's Sequence number for freshness of the authentication</span><br><span style="color: hsl(120, 100%, 40%);">+# QCI:      QoS Class Identifier for the UE's default bearer.</span><br><span style="color: hsl(120, 100%, 40%);">+# IP_alloc: IP allocation stratagy for the SPGW.</span><br><span style="color: hsl(120, 100%, 40%);">+#           With 'dynamic' the SPGW will automatically allocate IPs</span><br><span style="color: hsl(120, 100%, 40%);">+#           With a valid IPv4 (e.g. '172.16.0.2') the UE will have a statically assigned IP.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Note: Lines starting by '#' are ignored and will be overwritten</span><br><span style="color: hsl(120, 100%, 40%);">+#ue2,mil,001010123456780,00112233445566778899aabbccddeeff,opc,63bfa50ee6523365ff14c1f45f88737d,8000,000000001234,7,dynamic</span><br><span style="color: hsl(120, 100%, 40%);">+#ue1,xor,001010123456789,00112233445566778899aabbccddeeff,opc,63bfa50ee6523365ff14c1f45f88737d,9001,000000001255,7,dynamic</span><br><span style="color: hsl(120, 100%, 40%);">+%for sub in epc.hss.subscribers:</span><br><span style="color: hsl(120, 100%, 40%);">+ogt${sub.id},${sub.auth_algo},${sub.imsi},${sub.ki},opc,63bfa50ee6523365ff14c1f45f88737d,8000,000000001234,7,dynamic</span><br><span style="color: hsl(120, 100%, 40%);">+%endfor</span><br><span>diff --git a/src/osmo_gsm_tester/templates/srsue.conf.tmpl b/src/osmo_gsm_tester/templates/srsue.conf.tmpl</span><br><span>new file mode 100644</span><br><span>index 0000000..5e5676d</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo_gsm_tester/templates/srsue.conf.tmpl</span><br><span>@@ -0,0 +1,347 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+#                   srsUE configuration file</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# RF configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# dl_earfcn: Downlink EARFCN code.</span><br><span style="color: hsl(120, 100%, 40%);">+# freq_offset: Uplink and Downlink optional frequency offset (in Hz)</span><br><span style="color: hsl(120, 100%, 40%);">+# tx_gain: Transmit gain (dB).</span><br><span style="color: hsl(120, 100%, 40%);">+# rx_gain: Optional receive gain (dB). If disabled, AGC if enabled</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Optional parameters:</span><br><span style="color: hsl(120, 100%, 40%);">+# dl_freq:            Override DL frequency corresponding to dl_earfcn</span><br><span style="color: hsl(120, 100%, 40%);">+# ul_freq:            Override UL frequency corresponding to dl_earfcn</span><br><span style="color: hsl(120, 100%, 40%);">+# nof_radios:         Number of available RF devices</span><br><span style="color: hsl(120, 100%, 40%);">+# nof_rf_channels:    Number of RF channels per radio</span><br><span style="color: hsl(120, 100%, 40%);">+# nof_rx_ant:         Number of RX antennas per channel</span><br><span style="color: hsl(120, 100%, 40%);">+# device_name:        Device driver family. Supported options: "auto" (uses first found), "UHD" or "bladeRF"</span><br><span style="color: hsl(120, 100%, 40%);">+# device_args:        Arguments for the device driver. Options are "auto" or any string.</span><br><span style="color: hsl(120, 100%, 40%);">+#                     Default for UHD: "recv_frame_size=9232,send_frame_size=9232"</span><br><span style="color: hsl(120, 100%, 40%);">+#                     Default for bladeRF: ""</span><br><span style="color: hsl(120, 100%, 40%);">+# device_args_2:      Arguments for the RF device driver 2.</span><br><span style="color: hsl(120, 100%, 40%);">+# device_args_3:      Arguments for the RF device driver 3.</span><br><span style="color: hsl(120, 100%, 40%);">+# time_adv_nsamples:  Transmission time advance (in number of samples) to compensate for RF delay</span><br><span style="color: hsl(120, 100%, 40%);">+#                     from antenna to timestamp insertion.</span><br><span style="color: hsl(120, 100%, 40%);">+#                     Default "auto". B210 USRP: 100 samples, bladeRF: 27.</span><br><span style="color: hsl(120, 100%, 40%);">+# burst_preamble_us:  Preamble length to transmit before start of burst.</span><br><span style="color: hsl(120, 100%, 40%);">+#                     Default "auto". B210 USRP: 400 us, bladeRF: 0 us.</span><br><span style="color: hsl(120, 100%, 40%);">+# continuous_tx:      Transmit samples continuously to the radio or on bursts (auto/yes/no).</span><br><span style="color: hsl(120, 100%, 40%);">+#                     Default is auto (yes for UHD, no for rest)</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[rf]</span><br><span style="color: hsl(120, 100%, 40%);">+dl_earfcn = 3400</span><br><span style="color: hsl(120, 100%, 40%);">+freq_offset = 0</span><br><span style="color: hsl(120, 100%, 40%);">+tx_gain = 80</span><br><span style="color: hsl(120, 100%, 40%);">+#rx_gain = 40</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#nof_radios = 1</span><br><span style="color: hsl(120, 100%, 40%);">+#nof_rx_ant = 1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# For best performance in 2x2 MIMO and >= 15 MHz use the following device_args settings:</span><br><span style="color: hsl(120, 100%, 40%);">+#     USRP B210: num_recv_frames=64,num_send_frames=64</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# For best performance when BW<5 MHz (25 PRB), use the following device_args settings:</span><br><span style="color: hsl(120, 100%, 40%);">+#     USRP B210: send_frame_size=512,recv_frame_size=512</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#device_args = auto</span><br><span style="color: hsl(120, 100%, 40%);">+#time_adv_nsamples = auto</span><br><span style="color: hsl(120, 100%, 40%);">+#burst_preamble_us = auto</span><br><span style="color: hsl(120, 100%, 40%);">+#continuous_tx     = auto</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# Packet capture configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Packet capture is supported at both MAC and NAS layers.</span><br><span style="color: hsl(120, 100%, 40%);">+# MAC-layer packets are captured to file in the compact format</span><br><span style="color: hsl(120, 100%, 40%);">+# decoded by the Wireshark mac-lte-framed dissector.</span><br><span style="color: hsl(120, 100%, 40%);">+# To use this dissector, edit the preferences for DLT_USER to</span><br><span style="color: hsl(120, 100%, 40%);">+# add an entry with DLT=147, Payload Protocol=mac-lte-framed.</span><br><span style="color: hsl(120, 100%, 40%);">+# For more information see: https://wiki.wireshark.org/MAC-LTE</span><br><span style="color: hsl(120, 100%, 40%);">+# NAS-layer packets are dissected with DLT=148, and</span><br><span style="color: hsl(120, 100%, 40%);">+# Payload Protocol = nas-eps.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# enable:       Enable MAC layer packet captures (true/false)</span><br><span style="color: hsl(120, 100%, 40%);">+# filename:     File path to use for MAC packet captures</span><br><span style="color: hsl(120, 100%, 40%);">+# nas_enable:   Enable NAS layer packet captures (true/false)</span><br><span style="color: hsl(120, 100%, 40%);">+# nas_filename: File path to use for NAS packet captures</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[pcap]</span><br><span style="color: hsl(120, 100%, 40%);">+enable = false</span><br><span style="color: hsl(120, 100%, 40%);">+filename = /tmp/ue.pcap</span><br><span style="color: hsl(120, 100%, 40%);">+nas_enable = false</span><br><span style="color: hsl(120, 100%, 40%);">+nas_filename = /tmp/nas.pcap</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# Log configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Log levels can be set for individual layers. "all_level" sets log</span><br><span style="color: hsl(120, 100%, 40%);">+# level for all layers unless otherwise configured.</span><br><span style="color: hsl(120, 100%, 40%);">+# Format: e.g. phy_level = info</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# In the same way, packet hex dumps can be limited for each level.</span><br><span style="color: hsl(120, 100%, 40%);">+# "all_hex_limit" sets the hex limit for all layers unless otherwise</span><br><span style="color: hsl(120, 100%, 40%);">+# configured.</span><br><span style="color: hsl(120, 100%, 40%);">+# Format: e.g. phy_hex_limit = 32</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Logging layers: rf, phy, mac, rlc, pdcp, rrc, nas, gw, usim, all</span><br><span style="color: hsl(120, 100%, 40%);">+# Logging levels: debug, info, warning, error, none</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# filename: File path to use for log output. Can be set to stdout</span><br><span style="color: hsl(120, 100%, 40%);">+#           to print logs to standard output</span><br><span style="color: hsl(120, 100%, 40%);">+# file_max_size: Maximum file size (in kilobytes). When passed, multiple files are created.</span><br><span style="color: hsl(120, 100%, 40%);">+#                If set to negative, a single log file will be created.</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[log]</span><br><span style="color: hsl(120, 100%, 40%);">+all_level = warning</span><br><span style="color: hsl(120, 100%, 40%);">+phy_lib_level = none</span><br><span style="color: hsl(120, 100%, 40%);">+all_hex_limit = 32</span><br><span style="color: hsl(120, 100%, 40%);">+filename = /tmp/ue.log</span><br><span style="color: hsl(120, 100%, 40%);">+file_max_size = -1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# USIM configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# mode:   USIM mode (soft/pcsc)</span><br><span style="color: hsl(120, 100%, 40%);">+# algo:   Authentication algorithm (xor/milenage)</span><br><span style="color: hsl(120, 100%, 40%);">+# op/opc: 128-bit Operator Variant Algorithm Configuration Field (hex)</span><br><span style="color: hsl(120, 100%, 40%);">+#         - Specify either op or opc (only used in milenage)</span><br><span style="color: hsl(120, 100%, 40%);">+# k:      128-bit subscriber key (hex)</span><br><span style="color: hsl(120, 100%, 40%);">+# imsi:   15 digit International Mobile Subscriber Identity</span><br><span style="color: hsl(120, 100%, 40%);">+# imei:   15 digit International Mobile Station Equipment Identity</span><br><span style="color: hsl(120, 100%, 40%);">+# pin:    PIN in case real SIM card is used</span><br><span style="color: hsl(120, 100%, 40%);">+# reader: Specify card reader by it's name as listed by 'pcsc_scan'. If empty, try all available readers.</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[usim]</span><br><span style="color: hsl(120, 100%, 40%);">+mode = soft</span><br><span style="color: hsl(120, 100%, 40%);">+algo = ${ue.auth_algo}</span><br><span style="color: hsl(120, 100%, 40%);">+#opc  = 63BFA50EE6523365FF14C1F45F88737D</span><br><span style="color: hsl(120, 100%, 40%);">+k    = ${ue.ki}</span><br><span style="color: hsl(120, 100%, 40%);">+imsi = ${ue.imsi}</span><br><span style="color: hsl(120, 100%, 40%);">+imei = 353490069873319</span><br><span style="color: hsl(120, 100%, 40%);">+#reader =</span><br><span style="color: hsl(120, 100%, 40%);">+#pin  = 1234</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# RRC configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# ue_category:       Sets UE category (range 1-5). Default: 4</span><br><span style="color: hsl(120, 100%, 40%);">+# release:           UE Release (8 to 10)</span><br><span style="color: hsl(120, 100%, 40%);">+# feature_group:     Hex value of the featureGroupIndicators field in the</span><br><span style="color: hsl(120, 100%, 40%);">+#                    UECapabilityInformation message. Default 0xe6041000</span><br><span style="color: hsl(120, 100%, 40%);">+# mbms_service_id:   MBMS service id for autostarting MBMS reception</span><br><span style="color: hsl(120, 100%, 40%);">+#                    (default -1 means disabled)</span><br><span style="color: hsl(120, 100%, 40%);">+# mbms_service_port: Port of the MBMS service</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[rrc]</span><br><span style="color: hsl(120, 100%, 40%);">+#ue_category       = 4</span><br><span style="color: hsl(120, 100%, 40%);">+#release           = 8</span><br><span style="color: hsl(120, 100%, 40%);">+#feature_group     = 0xe6041000</span><br><span style="color: hsl(120, 100%, 40%);">+#mbms_service_id   = -1</span><br><span style="color: hsl(120, 100%, 40%);">+#mbms_service_port = 4321</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# NAS configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# apn:               Set Access Point Name (APN)</span><br><span style="color: hsl(120, 100%, 40%);">+# apn_protocol:      Set APN protocol (IPv4, IPv6 or IPv4v6.)</span><br><span style="color: hsl(120, 100%, 40%);">+# user:              Username for CHAP authentication</span><br><span style="color: hsl(120, 100%, 40%);">+# pass:              Password for CHAP authentication</span><br><span style="color: hsl(120, 100%, 40%);">+# force_imsi_attach: Whether to always perform an IMSI attach</span><br><span style="color: hsl(120, 100%, 40%);">+# eia:               List of integrity algorithms included in UE capabilities</span><br><span style="color: hsl(120, 100%, 40%);">+#                      Supported: 1 - Snow3G, 2 - AES</span><br><span style="color: hsl(120, 100%, 40%);">+# eea:               List of ciphering algorithms included in UE capabilities</span><br><span style="color: hsl(120, 100%, 40%);">+#                      Supported: 0 - NULL, 1 - Snow3G, 2 - AES</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[nas]</span><br><span style="color: hsl(120, 100%, 40%);">+#apn = internetinternet</span><br><span style="color: hsl(120, 100%, 40%);">+#apn_protocol = ipv4</span><br><span style="color: hsl(120, 100%, 40%);">+#user = srsuser</span><br><span style="color: hsl(120, 100%, 40%);">+#pass = srspass</span><br><span style="color: hsl(120, 100%, 40%);">+#force_imsi_attach = false</span><br><span style="color: hsl(120, 100%, 40%);">+#eia = 1,2</span><br><span style="color: hsl(120, 100%, 40%);">+#eea = 0,1,2</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# GW configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# netns:                Network namespace to create TUN device. Default: empty</span><br><span style="color: hsl(120, 100%, 40%);">+# ip_devname:           Name of the tun_srsue device. Default: tun_srsue</span><br><span style="color: hsl(120, 100%, 40%);">+# ip_netmask:           Netmask of the tun_srsue device. Default: 255.255.255.0</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[gw]</span><br><span style="color: hsl(120, 100%, 40%);">+#netns =</span><br><span style="color: hsl(120, 100%, 40%);">+#ip_devname = tun_srsue</span><br><span style="color: hsl(120, 100%, 40%);">+#ip_netmask = 255.255.255.0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# GUI configuration</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# Simple GUI displaying PDSCH constellation and channel freq response.</span><br><span style="color: hsl(120, 100%, 40%);">+# (Requires building with srsGUI)</span><br><span style="color: hsl(120, 100%, 40%);">+# enable:               Enable the graphical interface (true/false)</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[gui]</span><br><span style="color: hsl(120, 100%, 40%);">+enable = false</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# Channel emulator options:</span><br><span style="color: hsl(120, 100%, 40%);">+# enable:            Enable/Disable internal Downlink/Uplink channel emulator</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# -- Fading emulator</span><br><span style="color: hsl(120, 100%, 40%);">+# fading.enable:     Enable/disable fading simulator</span><br><span style="color: hsl(120, 100%, 40%);">+# fading.model:      Fading model + maximum doppler (E.g. none, epa5, eva70, etu300, etc)</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# -- Delay Emulator     delay(t) = delay_min + (delay_max - delay_min) * (1 + sin(2pi*t/period)) / 2</span><br><span style="color: hsl(120, 100%, 40%);">+#                       Maximum speed [m/s]: (delay_max - delay_min) * pi * 300 / period</span><br><span style="color: hsl(120, 100%, 40%);">+# delay.enable:      Enable/disable delay simulator</span><br><span style="color: hsl(120, 100%, 40%);">+# delay.period_s:    Delay period in seconds.</span><br><span style="color: hsl(120, 100%, 40%);">+# delay.init_time_s: Delay initial time in seconds.</span><br><span style="color: hsl(120, 100%, 40%);">+# delay.maximum_us:  Maximum delay in microseconds</span><br><span style="color: hsl(120, 100%, 40%);">+# delay.minumum_us:  Minimum delay in microseconds</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# -- Radio-Link Failure (RLF) Emulator</span><br><span style="color: hsl(120, 100%, 40%);">+# rlf.enable:        Enable/disable RLF simulator</span><br><span style="color: hsl(120, 100%, 40%);">+# rlf.t_on_ms:       Time for On state of the channel (ms)</span><br><span style="color: hsl(120, 100%, 40%);">+# rlf.t_off_ms:      Time for Off state of the channel (ms)</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# -- High Speed Train Doppler model simulator</span><br><span style="color: hsl(120, 100%, 40%);">+# hst.enable:        Enable/Disable HST simulator</span><br><span style="color: hsl(120, 100%, 40%);">+# hst.period_s:      HST simulation period in seconds</span><br><span style="color: hsl(120, 100%, 40%);">+# hst.fd_hz:         Doppler frequency in Hz</span><br><span style="color: hsl(120, 100%, 40%);">+# hst.init_time_s:   Initial time in seconds</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.dl]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.dl.fading]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+#model         = none</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.dl.delay]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+#period_s      = 3600</span><br><span style="color: hsl(120, 100%, 40%);">+#init_time_s   = 0</span><br><span style="color: hsl(120, 100%, 40%);">+#maximum_us    = 100</span><br><span style="color: hsl(120, 100%, 40%);">+#minimum_us    = 10</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.dl.rlf]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+#t_on_ms       = 10000</span><br><span style="color: hsl(120, 100%, 40%);">+#t_off_ms      = 2000</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.dl.hst]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+#period_s      = 7.2</span><br><span style="color: hsl(120, 100%, 40%);">+#fd_hz         = 750.0</span><br><span style="color: hsl(120, 100%, 40%);">+#init_time_s   = 0.0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.ul]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.ul.fading]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+#model         = none</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.ul.delay]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+#period_s      = 3600</span><br><span style="color: hsl(120, 100%, 40%);">+#init_time_s   = 0</span><br><span style="color: hsl(120, 100%, 40%);">+#maximum_us    = 100</span><br><span style="color: hsl(120, 100%, 40%);">+#minimum_us    = 10</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.ul.rlf]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+#t_on_ms       = 10000</span><br><span style="color: hsl(120, 100%, 40%);">+#t_off_ms      = 2000</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+[channel.ul.hst]</span><br><span style="color: hsl(120, 100%, 40%);">+#enable        = false</span><br><span style="color: hsl(120, 100%, 40%);">+#period_s      = 7.2</span><br><span style="color: hsl(120, 100%, 40%);">+#fd_hz         = -750.0</span><br><span style="color: hsl(120, 100%, 40%);">+#init_time_s   = 0.0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# PHY configuration options</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# rx_gain_offset:       RX Gain offset to add to rx_gain to calibrate RSRP readings</span><br><span style="color: hsl(120, 100%, 40%);">+# prach_gain:           PRACH gain (dB). If defined, forces a gain for the tranmsission of PRACH only.,</span><br><span style="color: hsl(120, 100%, 40%);">+#                       Default is to use tx_gain in [rf] section.</span><br><span style="color: hsl(120, 100%, 40%);">+# cqi_max:              Upper bound on the maximum CQI to be reported. Default 15.</span><br><span style="color: hsl(120, 100%, 40%);">+# cqi_fixed:            Fixes the reported CQI to a constant value. Default disabled.</span><br><span style="color: hsl(120, 100%, 40%);">+# snr_ema_coeff:        Sets the SNR exponential moving average coefficient (Default 0.1)</span><br><span style="color: hsl(120, 100%, 40%);">+# snr_estim_alg:        Sets the noise estimation algorithm. (Default refs)</span><br><span style="color: hsl(120, 100%, 40%);">+#                          Options: pss:   use difference between received and known pss signal,</span><br><span style="color: hsl(120, 100%, 40%);">+#                                   refs:  use difference between noise references and noiseless (after filtering)</span><br><span style="color: hsl(120, 100%, 40%);">+#                                   empty: use empty subcarriers in the boarder of pss/sss signal</span><br><span style="color: hsl(120, 100%, 40%);">+# pdsch_max_its:        Maximum number of turbo decoder iterations (Default 4)</span><br><span style="color: hsl(120, 100%, 40%);">+# nof_phy_threads:      Selects the number of PHY threads (maximum 4, minimum 1, default 2)</span><br><span style="color: hsl(120, 100%, 40%);">+# equalizer_mode:       Selects equalizer mode. Valid modes are: "mmse", "zf" or any</span><br><span style="color: hsl(120, 100%, 40%);">+#                       non-negative real number to indicate a regularized zf coefficient.</span><br><span style="color: hsl(120, 100%, 40%);">+#                       Default is MMSE.</span><br><span style="color: hsl(120, 100%, 40%);">+# sfo_ema:              EMA coefficient to average sample offsets used to compute SFO</span><br><span style="color: hsl(120, 100%, 40%);">+# sfo_correct_period:   Period in ms to correct sample time to adjust for SFO</span><br><span style="color: hsl(120, 100%, 40%);">+# sss_algorithm:        Selects the SSS estimation algorithm. Can choose between</span><br><span style="color: hsl(120, 100%, 40%);">+#                       {full, partial, diff}.</span><br><span style="color: hsl(120, 100%, 40%);">+# estimator_fil_auto:   The channel estimator smooths the channel estimate with an adaptative filter.</span><br><span style="color: hsl(120, 100%, 40%);">+# estimator_fil_stddev: Sets the channel estimator smooth gaussian filter standard deviation.</span><br><span style="color: hsl(120, 100%, 40%);">+# estimator_fil_order:  Sets the channel estimator smooth gaussian filter order (even values perform better).</span><br><span style="color: hsl(120, 100%, 40%);">+#                       The taps are [w, 1-2w, w]</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# snr_to_cqi_offset:    Sets an offset in the SNR to CQI table. This is used to adjust the reported CQI.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# pregenerate_signals:  Pregenerate uplink signals after attach. Improves CPU performance.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# interpolate_subframe_enabled: Interpolates in the time domain the channel estimates within 1 subframe. Default is to average.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# sic_pss_enabled:      Applies Successive Interference Cancellation to PSS signals when searching for neighbour cells.</span><br><span style="color: hsl(120, 100%, 40%);">+#                       Must be disabled if cells have identical channel and timing, for instance if generated from</span><br><span style="color: hsl(120, 100%, 40%);">+#                       the same source.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# pdsch_csi_enabled:     Stores the Channel State Information and uses it for weightening the softbits. It is only</span><br><span style="color: hsl(120, 100%, 40%);">+#                        used in TM1. It is True by default.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# pdsch_8bit_decoder:    Use 8-bit for LLR representation and turbo decoder trellis computation (Experimental)</span><br><span style="color: hsl(120, 100%, 40%);">+# force_ul_amplitude:    Forces the peak amplitude in the PUCCH, PUSCH and SRS (set 0.0 to 1.0, set to 0 or negative for disabling)</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[phy]</span><br><span style="color: hsl(120, 100%, 40%);">+#rx_gain_offset      = 62</span><br><span style="color: hsl(120, 100%, 40%);">+#prach_gain          = 30</span><br><span style="color: hsl(120, 100%, 40%);">+#cqi_max             = 15</span><br><span style="color: hsl(120, 100%, 40%);">+#cqi_fixed           = 10</span><br><span style="color: hsl(120, 100%, 40%);">+#snr_ema_coeff       = 0.1</span><br><span style="color: hsl(120, 100%, 40%);">+#snr_estim_alg       = refs</span><br><span style="color: hsl(120, 100%, 40%);">+#pdsch_max_its       = 8    # These are half iterations</span><br><span style="color: hsl(120, 100%, 40%);">+#nof_phy_threads     = 3</span><br><span style="color: hsl(120, 100%, 40%);">+#equalizer_mode      = mmse</span><br><span style="color: hsl(120, 100%, 40%);">+#sfo_ema             = 0.1</span><br><span style="color: hsl(120, 100%, 40%);">+#sfo_correct_period  = 10</span><br><span style="color: hsl(120, 100%, 40%);">+#sss_algorithm       = full</span><br><span style="color: hsl(120, 100%, 40%);">+#estimator_fil_auto  = false</span><br><span style="color: hsl(120, 100%, 40%);">+#estimator_fil_stddev  = 1.0</span><br><span style="color: hsl(120, 100%, 40%);">+#estimator_fil_order  = 4</span><br><span style="color: hsl(120, 100%, 40%);">+#snr_to_cqi_offset   = 0.0</span><br><span style="color: hsl(120, 100%, 40%);">+#interpolate_subframe_enabled = false</span><br><span style="color: hsl(120, 100%, 40%);">+#sic_pss_enabled     = true</span><br><span style="color: hsl(120, 100%, 40%);">+#pregenerate_signals = false</span><br><span style="color: hsl(120, 100%, 40%);">+#pdsch_csi_enabled  = true</span><br><span style="color: hsl(120, 100%, 40%);">+#pdsch_8bit_decoder = false</span><br><span style="color: hsl(120, 100%, 40%);">+#force_ul_amplitude = 0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+# General configuration options</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# metrics_csv_enable:   Write UE metrics to CSV file.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# metrics_period_secs:  Sets the period at which metrics are requested from the UE.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+# metrics_csv_filename: File path to use for CSV metrics.</span><br><span style="color: hsl(120, 100%, 40%);">+#</span><br><span style="color: hsl(120, 100%, 40%);">+#####################################################################</span><br><span style="color: hsl(120, 100%, 40%);">+[general]</span><br><span style="color: hsl(120, 100%, 40%);">+#metrics_csv_enable  = false</span><br><span style="color: hsl(120, 100%, 40%);">+#metrics_period_secs = 1</span><br><span style="color: hsl(120, 100%, 40%);">+#metrics_csv_filename = /tmp/ue_metrics.csv</span><br><span>diff --git a/suites/4g/iperf3.py b/suites/4g/iperf3.py</span><br><span>new file mode 100755</span><br><span>index 0000000..5ccc922</span><br><span>--- /dev/null</span><br><span>+++ b/suites/4g/iperf3.py</span><br><span>@@ -0,0 +1,44 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#!/usr/bin/env python3</span><br><span style="color: hsl(120, 100%, 40%);">+from osmo_gsm_tester.testenv import *</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def print_results(cli_res, srv_res):</span><br><span style="color: hsl(120, 100%, 40%);">+    cli_sent = cli_res['end']['sum_sent']</span><br><span style="color: hsl(120, 100%, 40%);">+    cli_recv = cli_res['end']['sum_received']</span><br><span style="color: hsl(120, 100%, 40%);">+    print("RESULT client:")</span><br><span style="color: hsl(120, 100%, 40%);">+    print("\tSEND: %d KB, %d kbps, %d seconds (%d retrans)" % (cli_sent['bytes']/1000, cli_sent['bits_per_second']/1000,  cli_sent['seconds'], cli_sent['retransmits']))</span><br><span style="color: hsl(120, 100%, 40%);">+    print("\tRECV: %d KB, %d kbps, %d seconds" % (cli_recv['bytes']/1000, cli_recv['bits_per_second']/1000, cli_recv['seconds']))</span><br><span style="color: hsl(120, 100%, 40%);">+    print("RESULT server:")</span><br><span style="color: hsl(120, 100%, 40%);">+    print("\tSEND: %d KB, %d kbps, %d seconds" % (cli_sent['bytes']/1000, cli_sent['bits_per_second']/1000, cli_sent['seconds']))</span><br><span style="color: hsl(120, 100%, 40%);">+    print("\tRECV: %d KB, %d kbps, %d seconds" % (cli_recv['bytes']/1000, cli_recv['bits_per_second']/1000, cli_recv['seconds']))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+epc = suite.epc()</span><br><span style="color: hsl(120, 100%, 40%);">+enb = suite.enb()</span><br><span style="color: hsl(120, 100%, 40%);">+ue = suite.modem()</span><br><span style="color: hsl(120, 100%, 40%);">+iperf3srv = suite.iperf3srv({'addr': epc.tun_addr()})</span><br><span style="color: hsl(120, 100%, 40%);">+iperf3srv.set_run_node(epc.run_node())</span><br><span style="color: hsl(120, 100%, 40%);">+iperf3cli = iperf3srv.create_client()</span><br><span style="color: hsl(120, 100%, 40%);">+iperf3cli.set_run_node(ue.run_node())</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+epc.subscriber_add(ue)</span><br><span style="color: hsl(120, 100%, 40%);">+epc.start()</span><br><span style="color: hsl(120, 100%, 40%);">+enb.ue_add(ue)</span><br><span style="color: hsl(120, 100%, 40%);">+enb.start(epc)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+print('waiting for ENB to connect to EPC...')</span><br><span style="color: hsl(120, 100%, 40%);">+wait(epc.enb_is_connected, enb)</span><br><span style="color: hsl(120, 100%, 40%);">+print('ENB is connected to EPC')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ue.connect(enb)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+iperf3srv.start()</span><br><span style="color: hsl(120, 100%, 40%);">+proc = iperf3cli.prepare_test_proc(ue.netns())</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+print('waiting for UE to attach...')</span><br><span style="color: hsl(120, 100%, 40%);">+wait(ue.is_connected, None)</span><br><span style="color: hsl(120, 100%, 40%);">+print('UE is attached')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+print("Running iperf3 client to %s through %s" % (str(iperf3cli), ue.netns()))</span><br><span style="color: hsl(120, 100%, 40%);">+proc.launch_sync()</span><br><span style="color: hsl(120, 100%, 40%);">+iperf3srv.stop()</span><br><span style="color: hsl(120, 100%, 40%);">+print_results(iperf3cli.get_results(), iperf3srv.get_results())</span><br><span>diff --git a/suites/4g/mo_mt_sms.py b/suites/4g/mo_mt_sms.py</span><br><span>deleted file mode 100755</span><br><span>index 8aa4357..0000000</span><br><span>--- a/suites/4g/mo_mt_sms.py</span><br><span>+++ /dev/null</span><br><span>@@ -1,22 +0,0 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python3</span><br><span style="color: hsl(0, 100%, 40%);">-from osmo_gsm_tester.testenv import *</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#epc = suite.epc()</span><br><span style="color: hsl(0, 100%, 40%);">-#enb = suite.enb()</span><br><span style="color: hsl(0, 100%, 40%);">-ue = suite.modem()</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#enb.start()</span><br><span style="color: hsl(0, 100%, 40%);">-#epc.enb_add(enb)</span><br><span style="color: hsl(0, 100%, 40%);">-#epc.start()</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#wait(epc.enb_is_connected, enb)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#hss/epc.subscriber_add(ue)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#ue.connect(epc.mcc_mnc())</span><br><span style="color: hsl(0, 100%, 40%);">-ue.connect()</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-print('waiting for modem to attach...')</span><br><span style="color: hsl(0, 100%, 40%);">-#wait(ue.is_connected, msc.mcc_mnc())</span><br><span style="color: hsl(0, 100%, 40%);">-sleep(10)</span><br><span>diff --git a/suites/4g/ping.py b/suites/4g/ping.py</span><br><span>new file mode 100755</span><br><span>index 0000000..b44ff84</span><br><span>--- /dev/null</span><br><span>+++ b/suites/4g/ping.py</span><br><span>@@ -0,0 +1,22 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#!/usr/bin/env python3</span><br><span style="color: hsl(120, 100%, 40%);">+from osmo_gsm_tester.testenv import *</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+epc = suite.epc()</span><br><span style="color: hsl(120, 100%, 40%);">+enb = suite.enb()</span><br><span style="color: hsl(120, 100%, 40%);">+ue = suite.modem()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+epc.subscriber_add(ue)</span><br><span style="color: hsl(120, 100%, 40%);">+epc.start()</span><br><span style="color: hsl(120, 100%, 40%);">+enb.ue_add(ue)</span><br><span style="color: hsl(120, 100%, 40%);">+enb.start(epc)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+print('waiting for ENB to connect to EPC...')</span><br><span style="color: hsl(120, 100%, 40%);">+wait(epc.enb_is_connected, enb)</span><br><span style="color: hsl(120, 100%, 40%);">+print('ENB is connected to EPC')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ue.connect(enb)</span><br><span style="color: hsl(120, 100%, 40%);">+print('waiting for UE to attach...')</span><br><span style="color: hsl(120, 100%, 40%);">+wait(ue.is_connected, None)</span><br><span style="color: hsl(120, 100%, 40%);">+print('UE is attached')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ue.run_netns_wait('ping', ('ping', '-c', '10', epc.tun_addr()))</span><br><span>diff --git a/suites/4g/suite.conf b/suites/4g/suite.conf</span><br><span>index c55b610..352293a 100644</span><br><span>--- a/suites/4g/suite.conf</span><br><span>+++ b/suites/4g/suite.conf</span><br><span>@@ -1,6 +1,9 @@</span><br><span> resources:</span><br><span style="color: hsl(0, 100%, 40%);">-  ip_address:</span><br><span style="color: hsl(120, 100%, 40%);">+  run_node: # for EPC</span><br><span>   - times: 1</span><br><span style="color: hsl(120, 100%, 40%);">+  enb:</span><br><span style="color: hsl(120, 100%, 40%);">+  - times: 1</span><br><span style="color: hsl(120, 100%, 40%);">+    type: srsenb</span><br><span>   modem:</span><br><span>   - times: 1</span><br><span>     type: srsue</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-gsm-tester/+/17139">change 17139</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-gsm-tester/+/17139"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-gsm-tester </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I290c0d79258a9f94f00c7ff2e1c6c5579c0e32f4 </div>
<div style="display:none"> Gerrit-Change-Number: 17139 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>