<p>pespin has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-gsm-tester/+/17690">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Introduce support for AmarisoftEPC<br><br>* A new abstract generic base class EPC is created<br>* srsEPC and AmarisoftEPC inherit from that class<br>* options are loaded from defaults.conf in cascade. First generic "epc",<br>  afterwards the specific enb type.<br>* A new scenario is added to select the EPC type to use. srsEPC is the<br>  default unless stated by an scenario.<br>* AmarisoftEPC delegates setup of the tun IP address to an "ifup"<br>  script. As a result, since we run without root permissions (ony with<br>  CAP_NET_ADMIN), the ifup script itself is unablet o set the IP<br>  address. To solve this, we introduce a new osmo-gsm-tester helper<br>  script which must be installed in the slave node which can be called<br>  through sudo to increase privileges to do so.<br><br>With this commit, I can already get srsUE<->amarisoftENB<->amarisoftEPC<br>to pass ping and iperf3 4g tests.<br><br>Change-Id: Ia50ea6a74b63b2d688c8d683aea11416ad40a6d3<br>---<br>M example/defaults.conf<br>A example/scenarios/cfg-epc-type@.conf<br>A src/osmo_gsm_tester/amarisoft_epc.py<br>A src/osmo_gsm_tester/epc.py<br>M src/osmo_gsm_tester/resource.py<br>M src/osmo_gsm_tester/srs_epc.py<br>M src/osmo_gsm_tester/suite.py<br>A src/osmo_gsm_tester/templates/amarisoft_ltemme.cfg.tmpl<br>A utils/bin/osmo-gsm-tester_amarisoft_ltemme_ifup.sh<br>A utils/sudoers.d/osmo-gsm-tester_amarisoft_ltemme_ifup<br>10 files changed, 451 insertions(+), 21 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-gsm-tester refs/changes/90/17690/1</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 bcd1fa2..56a41e5 100644</span><br><span>--- a/example/defaults.conf</span><br><span>+++ b/example/defaults.conf</span><br><span>@@ -93,12 +93,17 @@</span><br><span>   trx_list:</span><br><span>   - nominal_power: 25</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-srsepc:</span><br><span style="color: hsl(120, 100%, 40%);">+epc:</span><br><span style="color: hsl(120, 100%, 40%);">+  type: srsepc</span><br><span>   mcc: 901</span><br><span>   mnc: 70</span><br><span style="color: hsl(120, 100%, 40%);">+srsepc:</span><br><span>   rlc_drb_mode: UM</span><br><span>   enable_pcap: false</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+amarisoftepc:</span><br><span style="color: hsl(120, 100%, 40%);">+  license_server_addr: 10.12.1.139</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> enb:</span><br><span>   mcc: 901</span><br><span>   mnc: 70</span><br><span>diff --git a/example/scenarios/cfg-epc-type@.conf b/example/scenarios/cfg-epc-type@.conf</span><br><span>new file mode 100644</span><br><span>index 0000000..89b7fba</span><br><span>--- /dev/null</span><br><span>+++ b/example/scenarios/cfg-epc-type@.conf</span><br><span>@@ -0,0 +1,3 @@</span><br><span style="color: hsl(120, 100%, 40%);">+config:</span><br><span style="color: hsl(120, 100%, 40%);">+  epc:</span><br><span style="color: hsl(120, 100%, 40%);">+    type: ${param1}</span><br><span>diff --git a/src/osmo_gsm_tester/amarisoft_epc.py b/src/osmo_gsm_tester/amarisoft_epc.py</span><br><span>new file mode 100644</span><br><span>index 0000000..0361f54</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo_gsm_tester/amarisoft_epc.py</span><br><span>@@ -0,0 +1,203 @@</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%);">+from . import epc</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#def rlc_drb_mode2qci(rlc_drb_mode):</span><br><span style="color: hsl(120, 100%, 40%);">+#    if rlc_drb_mode.upper() == "UM":</span><br><span style="color: hsl(120, 100%, 40%);">+#        return 7;</span><br><span style="color: hsl(120, 100%, 40%);">+#    elif rlc_drb_mode.upper() == "AM":</span><br><span style="color: hsl(120, 100%, 40%);">+#        return 9;</span><br><span style="color: hsl(120, 100%, 40%);">+#    raise log.Error('Unexpected rlc_drb_mode', rlc_drb_mode=rlc_drb_mode)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class AmarisoftEPC(epc.EPC):</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    REMOTE_DIR = '/osmo-gsm-tester-amarisoftepc'</span><br><span style="color: hsl(120, 100%, 40%);">+    BINFILE = 'ltemme'</span><br><span style="color: hsl(120, 100%, 40%);">+    CFGFILE = 'amarisoft_ltemme.cfg'</span><br><span style="color: hsl(120, 100%, 40%);">+    LOGFILE = 'ltemme.log'</span><br><span style="color: hsl(120, 100%, 40%);">+    IFUPFILE = 'mme-ifup'</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__(suite_run, run_node, 'amarisoftepc')</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.ifup_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_inst = 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_ifup_file =None</span><br><span style="color: hsl(120, 100%, 40%);">+        self._bin_prefix = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.inst = None</span><br><span style="color: hsl(120, 100%, 40%);">+        self.subscriber_list = []</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def bin_prefix(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        if self._bin_prefix is None:</span><br><span style="color: hsl(120, 100%, 40%);">+            self._bin_prefix = os.getenv('AMARISOFT_PATH_EPC', AmarisoftEPC.REMOTE_DIR)</span><br><span style="color: hsl(120, 100%, 40%);">+        return self._bin_prefix</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def start(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log('Starting amarisoftepc')</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%);">+        remote_binary = self.remote_inst.child('', AmarisoftEPC.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 amarisoftepc')</span><br><span style="color: hsl(120, 100%, 40%);">+        self.rem_host.change_elf_rpath(remote_binary, str(self.remote_inst))</span><br><span style="color: hsl(120, 100%, 40%);">+        # amarisoftepc 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 amarisoftepc')</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.process = self.rem_host.RemoteProcess(AmarisoftEPC.BINFILE, args)</span><br><span style="color: hsl(120, 100%, 40%);">+        #self.process = self.rem_host.RemoteProcessFixIgnoreSIGHUP(AmarisoftEPC.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%);">+        binary = self.inst.child('', BINFILE)</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 amarisoftepc')</span><br><span style="color: hsl(120, 100%, 40%);">+        util.change_elf_rpath(binary, util.prepend_library_path(str(self.inst)), self.run_dir.new_dir('patchelf'))</span><br><span style="color: hsl(120, 100%, 40%);">+        # amarisoftepc 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 amarisoftepc')</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%);">+</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.inst = util.Dir(os.path.abspath(self.bin_prefix()))</span><br><span style="color: hsl(120, 100%, 40%);">+        if not self.inst.isfile('', AmarisoftEPC.BINFILE):</span><br><span style="color: hsl(120, 100%, 40%);">+            raise log.Error('No %s binary in' % AmarisoftEPC.BINFILE, self.inst)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.config_file = self.run_dir.child(AmarisoftEPC.CFGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.log_file = self.run_dir.child(AmarisoftEPC.LOGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.ifup_file = self.run_dir.new_file(AmarisoftEPC.IFUPFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+        os.chmod(self.ifup_file, 0o744) # add execution permission</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%);">+        with open(self.ifup_file, 'w') as f:</span><br><span style="color: hsl(120, 100%, 40%);">+            r = '''#!/bin/sh</span><br><span style="color: hsl(120, 100%, 40%);">+            set -x -e</span><br><span style="color: hsl(120, 100%, 40%);">+            # script + sudoers file available in osmo-gsm-tester.git/utils/{bin,sudoers.d}</span><br><span style="color: hsl(120, 100%, 40%);">+            sudo /usr/local/bin/osmo-gsm-tester_amarisoft_ltemme_ifup.sh "$@"</span><br><span style="color: hsl(120, 100%, 40%);">+            '''</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%);">+        if not self._run_node.is_local():</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(AmarisoftEPC.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(AmarisoftEPC.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(AmarisoftEPC.CFGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+            self.remote_log_file = remote_run_dir.child(AmarisoftEPC.LOGFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+            self.remote_ifup_file = remote_run_dir.child(AmarisoftEPC.IFUPFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        values = super().configure('amarisoftepc')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        logfile = self.log_file if self._run_node.is_local() else self.remote_log_file</span><br><span style="color: hsl(120, 100%, 40%);">+        ifupfile = self.ifup_file if self._run_node.is_local() else self.remote_ifup_file</span><br><span style="color: hsl(120, 100%, 40%);">+        config.overlay(values, dict(epc=dict(log_filename=logfile,</span><br><span style="color: hsl(120, 100%, 40%);">+                                             ifup_filename=ifupfile)))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        # Set qci for each subscriber:</span><br><span style="color: hsl(120, 100%, 40%);">+        #rlc_drb_mode = values['epc'].get('rlc_drb_mode', None)</span><br><span style="color: hsl(120, 100%, 40%);">+        #assert rlc_drb_mode is not None</span><br><span style="color: hsl(120, 100%, 40%);">+        #for i in range(len(self.subscriber_list)):</span><br><span style="color: hsl(120, 100%, 40%);">+        #    self.subscriber_list[i]['qci'] = rlc_drb_mode2qci(rlc_drb_mode)</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%);">+</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(AmarisoftEPC.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%);">+        if not self._run_node.is_local():</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.recreate_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-ifup-to-remote', self.ifup_file, self.remote_ifup_file)</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, 'apn_ipaddr': modem.apn_ipaddr()})</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%);">+        # TODO: improve this a bit, like matching IP addr of enb. CTRL iface?</span><br><span style="color: hsl(120, 100%, 40%);">+        # The string is only available in log file, not in stdout:</span><br><span style="color: hsl(120, 100%, 40%);">+        #return 'S1 setup response' in (self.process.get_stdout() or '')</span><br><span style="color: hsl(120, 100%, 40%);">+        return True</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 tun_addr(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        # TODO: set proper addr</span><br><span style="color: hsl(120, 100%, 40%);">+        return '192.168.4.1'</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/epc.py b/src/osmo_gsm_tester/epc.py</span><br><span>new file mode 100644</span><br><span>index 0000000..da8302c</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo_gsm_tester/epc.py</span><br><span>@@ -0,0 +1,80 @@</span><br><span style="color: hsl(120, 100%, 40%);">+# osmo_gsm_tester: base classes to share code among EPC subclasses.</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%);">+from abc import ABCMeta, abstractmethod</span><br><span style="color: hsl(120, 100%, 40%);">+from . import log, 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%);">+class EPC(log.Origin, metaclass=ABCMeta):</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%);">+# PROTECTED</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, name):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(log.C_RUN, '%s' % name)</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('%s_%s' % (name, self._addr))</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 configure(self, default_specifics):</span><br><span style="color: hsl(120, 100%, 40%);">+        values = dict(epc=config.get_defaults('epc'))</span><br><span style="color: hsl(120, 100%, 40%);">+        config.overlay(values, dict(epc=config.get_defaults(default_specifics)))</span><br><span style="color: hsl(120, 100%, 40%);">+        config.overlay(values, dict(epc=self.suite_run.config().get('epc', {})))</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%);">+        return values</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%);">+# PUBLIC - INTERNAL API</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%);">+        'Nothing to do by default. Subclass can override if required.'</span><br><span style="color: hsl(120, 100%, 40%);">+        pass</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%);">+# PUBLIC (test API included)</span><br><span style="color: hsl(120, 100%, 40%);">+###################</span><br><span style="color: hsl(120, 100%, 40%);">+    @abstractmethod</span><br><span style="color: hsl(120, 100%, 40%);">+    def start(self, epc):</span><br><span style="color: hsl(120, 100%, 40%);">+        'Starts ENB, it will connect to "epc"'</span><br><span style="color: hsl(120, 100%, 40%);">+        pass</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    @abstractmethod</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%);">+        pass</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    @abstractmethod</span><br><span style="color: hsl(120, 100%, 40%);">+    def enb_is_connected(self, enb):</span><br><span style="color: hsl(120, 100%, 40%);">+        pass</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    @abstractmethod</span><br><span style="color: hsl(120, 100%, 40%);">+    def running(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        pass</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    @abstractmethod</span><br><span style="color: hsl(120, 100%, 40%);">+    def tun_addr(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        pass</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%);">+        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/resource.py b/src/osmo_gsm_tester/resource.py</span><br><span>index d14ee96..383f09e 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,7 +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(0, 100%, 40%);">-from . import srs_ue, srs_enb, amarisoft_enb</span><br><span style="color: hsl(120, 100%, 40%);">+from . import srs_ue, srs_enb, amarisoft_enb, srs_epc, amarisoft_epc</span><br><span> </span><br><span> from .util import is_dict, is_list</span><br><span> </span><br><span>@@ -122,6 +122,7 @@</span><br><span>     { 'defaults.timeout': schema.STR,</span><br><span>       'config.bsc.net.codec_list[]': schema.CODEC,</span><br><span>       'config.enb.enable_pcap': schema.BOOL_STR,</span><br><span style="color: hsl(120, 100%, 40%);">+      'config.epc.type': schema.STR,</span><br><span>       'config.epc.rlc_drb_mode': schema.LTE_RLC_DRB_MODE,</span><br><span>       'config.epc.enable_pcap': schema.BOOL_STR,</span><br><span>       'config.modem.enable_pcap': schema.BOOL_STR,</span><br><span>@@ -143,6 +144,11 @@</span><br><span>         'amarisoftenb': amarisoft_enb.AmarisoftENB,</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+KNOWN_EPC_TYPES = {</span><br><span style="color: hsl(120, 100%, 40%);">+        'srsepc': srs_epc.srsEPC,</span><br><span style="color: hsl(120, 100%, 40%);">+        'amarisoftepc': amarisoft_epc.AmarisoftEPC,</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</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>diff --git a/src/osmo_gsm_tester/srs_epc.py b/src/osmo_gsm_tester/srs_epc.py</span><br><span>index 947eb7b..708ca5b 100644</span><br><span>--- a/src/osmo_gsm_tester/srs_epc.py</span><br><span>+++ b/src/osmo_gsm_tester/srs_epc.py</span><br><span>@@ -21,6 +21,7 @@</span><br><span> import pprint</span><br><span> </span><br><span> from . import log, util, config, template, process, remote</span><br><span style="color: hsl(120, 100%, 40%);">+from . import epc</span><br><span> </span><br><span> def rlc_drb_mode2qci(rlc_drb_mode):</span><br><span>     if rlc_drb_mode.upper() == "UM":</span><br><span>@@ -29,7 +30,7 @@</span><br><span>         return 9;</span><br><span>     raise log.Error('Unexpected rlc_drb_mode', rlc_drb_mode=rlc_drb_mode)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-class srsEPC(log.Origin):</span><br><span style="color: hsl(120, 100%, 40%);">+class srsEPC(epc.EPC):</span><br><span> </span><br><span>     REMOTE_DIR = '/osmo-gsm-tester-srsepc'</span><br><span>     BINFILE = 'srsepc'</span><br><span>@@ -39,9 +40,7 @@</span><br><span>     LOGFILE = 'srsepc.log'</span><br><span> </span><br><span>     def __init__(self, suite_run, run_node):</span><br><span style="color: hsl(0, 100%, 40%);">-        super().__init__(log.C_RUN, 'srsepc')</span><br><span style="color: hsl(0, 100%, 40%);">-        self._addr = run_node.run_addr()</span><br><span style="color: hsl(0, 100%, 40%);">-        self.set_name('srsepc_%s' % self._addr)</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(suite_run, run_node, 'srsepc')</span><br><span>         self.run_dir = None</span><br><span>         self.config_file = None</span><br><span>         self.db_file = None</span><br><span>@@ -55,8 +54,6 @@</span><br><span>         self.remote_pcap_file = None</span><br><span>         self.enable_pcap = False</span><br><span>         self.subscriber_list = []</span><br><span style="color: hsl(0, 100%, 40%);">-        self.suite_run = suite_run</span><br><span style="color: hsl(0, 100%, 40%);">-        self._run_node = run_node</span><br><span> </span><br><span>     def cleanup(self):</span><br><span>         if self.process is None:</span><br><span>@@ -161,9 +158,7 @@</span><br><span>         self.pcap_file = self.run_dir.child(srsEPC.PCAPFILE)</span><br><span>         self.dbg(config_file=self.config_file, db_file=self.db_file)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        values = dict(epc=config.get_defaults('srsepc'))</span><br><span style="color: hsl(0, 100%, 40%);">-        config.overlay(values, dict(epc=self.suite_run.config().get('epc', {})))</span><br><span style="color: hsl(0, 100%, 40%);">-        config.overlay(values, dict(epc={'run_addr': self.addr()}))</span><br><span style="color: hsl(120, 100%, 40%);">+        values = super().configure('srsepc')</span><br><span> </span><br><span>         # Convert parsed boolean string to Python boolean:</span><br><span>         self.enable_pcap = util.str2bool(values['epc'].get('enable_pcap', 'false'))</span><br><span>@@ -212,13 +207,7 @@</span><br><span>     def running(self):</span><br><span>         return not self.process.terminated()</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    def addr(self):</span><br><span style="color: hsl(0, 100%, 40%);">-        return self._addr</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>     def tun_addr(self):</span><br><span>         return '172.16.0.1'</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    def run_node(self):</span><br><span style="color: hsl(0, 100%, 40%);">-        return self._run_node</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> # 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 8c79d35..5076671 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,7 +25,6 @@</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(0, 100%, 40%);">-from . import srs_epc</span><br><span> </span><br><span> class Timeout(Exception):</span><br><span>     pass</span><br><span>@@ -374,9 +373,9 @@</span><br><span>     def epc(self, run_node=None):</span><br><span>         if run_node is None:</span><br><span>             run_node = self.run_node()</span><br><span style="color: hsl(0, 100%, 40%);">-        epc_obj = srs_epc.srsEPC(self, run_node)</span><br><span style="color: hsl(0, 100%, 40%);">-        self.register_for_cleanup(epc_obj)</span><br><span style="color: hsl(0, 100%, 40%);">-        return epc_obj</span><br><span style="color: hsl(120, 100%, 40%);">+        epc = epc_obj(self, run_node)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.register_for_cleanup(epc)</span><br><span style="color: hsl(120, 100%, 40%);">+        return epc</span><br><span> </span><br><span>     def osmocon(self, specifics=None):</span><br><span>         conf = self.reserved_resources.get(resource.R_OSMOCON, specifics=specifics)</span><br><span>@@ -505,4 +504,16 @@</span><br><span>         raise RuntimeError('No such ENB type is defined: %r' % enb_type)</span><br><span>     return enb_class(suite_run, conf)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+def epc_obj(suite_run, run_node):</span><br><span style="color: hsl(120, 100%, 40%);">+    values = dict(epc=config.get_defaults('epc'))</span><br><span style="color: hsl(120, 100%, 40%);">+    config.overlay(values, dict(epc=suite_run.config().get('epc', {})))</span><br><span style="color: hsl(120, 100%, 40%);">+    epc_type = values['epc'].get('type', None)</span><br><span style="color: hsl(120, 100%, 40%);">+    if epc_type is None:</span><br><span style="color: hsl(120, 100%, 40%);">+        raise RuntimeError('EPC type is not defined!')</span><br><span style="color: hsl(120, 100%, 40%);">+    log.dbg('create EPC object', type=epc_type)</span><br><span style="color: hsl(120, 100%, 40%);">+    epc_class = resource.KNOWN_EPC_TYPES.get(epc_type)</span><br><span style="color: hsl(120, 100%, 40%);">+    if epc_class is None:</span><br><span style="color: hsl(120, 100%, 40%);">+        raise RuntimeError('No such EPC type is defined: %r' % epc_type)</span><br><span style="color: hsl(120, 100%, 40%);">+    return epc_class(suite_run, run_node)</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/amarisoft_ltemme.cfg.tmpl b/src/osmo_gsm_tester/templates/amarisoft_ltemme.cfg.tmpl</span><br><span>new file mode 100644</span><br><span>index 0000000..a2af69a</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo_gsm_tester/templates/amarisoft_ltemme.cfg.tmpl</span><br><span>@@ -0,0 +1,116 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* ltemme configuration file</span><br><span style="color: hsl(120, 100%, 40%);">+ * version 2018-10-18</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2015-2018 Amarisoft</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%);">+  license_server: {</span><br><span style="color: hsl(120, 100%, 40%);">+    server_addr: "${epc.license_server_addr}",</span><br><span style="color: hsl(120, 100%, 40%);">+    name: "amarisoft",</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 filter: syntax: layer.field=value[,...]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     Possible layers are nas, ip, s1ap, gtpu and all. The 'all' layer</span><br><span style="color: hsl(120, 100%, 40%);">+     is used to address all the layers at the same time.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     field values:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     - 'level': the log level of each layer can be set to 'none',</span><br><span style="color: hsl(120, 100%, 40%);">+     'error', 'info' or 'debug'. Use 'debug' to log all the messages.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     - 'max_size': set the maximum size of the hex dump. 0 means no</span><br><span style="color: hsl(120, 100%, 40%);">+       hex dump. -1 means no limit.</span><br><span style="color: hsl(120, 100%, 40%);">+  */</span><br><span style="color: hsl(120, 100%, 40%);">+  //log_options: "all.level=debug,all.max_size=32",</span><br><span style="color: hsl(120, 100%, 40%);">+  log_options: "all.level=error,all.max_size=0,nas.level=debug,nas.max_size=1,s1ap.level=debug,s1ap.max_size=1",</span><br><span style="color: hsl(120, 100%, 40%);">+  log_filename: "${epc.log_filename}",</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Enable remote API and Web interface */</span><br><span style="color: hsl(120, 100%, 40%);">+  com_addr: "${epc.run_addr}:9000",</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* bind address for GTP-U. Normally = address of the PC, here bound</span><br><span style="color: hsl(120, 100%, 40%);">+    on local interface to be able to run ltemme on the same PC as</span><br><span style="color: hsl(120, 100%, 40%);">+    lteenb. By default, the S1AP SCTP connection is bound on the same</span><br><span style="color: hsl(120, 100%, 40%);">+    address. */</span><br><span style="color: hsl(120, 100%, 40%);">+  gtp_addr: "${epc.run_addr}",</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  s1ap_bind_addr: "${epc.run_addr}",</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  plmn: "${epc.mcc}${epc.mnc}",</span><br><span style="color: hsl(120, 100%, 40%);">+  mme_group_id: 32769,</span><br><span style="color: hsl(120, 100%, 40%);">+  mme_code: 1,</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* network name and network short name sent in the EMM information</span><br><span style="color: hsl(120, 100%, 40%);">+     message to the UE */</span><br><span style="color: hsl(120, 100%, 40%);">+  network_name: "Amarisoft Network",</span><br><span style="color: hsl(120, 100%, 40%);">+  network_short_name: "Amarisoft",</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Control Plane Cellular IoT EPS optimization support */</span><br><span style="color: hsl(120, 100%, 40%);">+  cp_ciot_opt: true,</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Public Data Networks. The first one is the default. */</span><br><span style="color: hsl(120, 100%, 40%);">+  pdn_list: [</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Some UE requires a specific PDN for data access */</span><br><span style="color: hsl(120, 100%, 40%);">+      pdn_type: "ipv4",</span><br><span style="color: hsl(120, 100%, 40%);">+      access_point_name: "internet",</span><br><span style="color: hsl(120, 100%, 40%);">+      first_ip_addr: "192.168.4.2",</span><br><span style="color: hsl(120, 100%, 40%);">+      last_ip_addr: "192.168.4.254",</span><br><span style="color: hsl(120, 100%, 40%);">+      ip_addr_shift: 2,</span><br><span style="color: hsl(120, 100%, 40%);">+      dns_addr: "8.8.8.8", /* Google DNS address */</span><br><span style="color: hsl(120, 100%, 40%);">+      erabs: [</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%);">+          priority_level: 15,</span><br><span style="color: hsl(120, 100%, 40%);">+          pre_emption_capability: "shall_not_trigger_pre_emption",</span><br><span style="color: hsl(120, 100%, 40%);">+          pre_emption_vulnerability: "not_pre_emptable",</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%);">+  /* Setup script for the network interface.</span><br><span style="color: hsl(120, 100%, 40%);">+     If no script is given, no network interface is created.</span><br><span style="color: hsl(120, 100%, 40%);">+     Script is called for each PDN with following parameters:</span><br><span style="color: hsl(120, 100%, 40%);">+        1) Interface name</span><br><span style="color: hsl(120, 100%, 40%);">+        2) PDN index</span><br><span style="color: hsl(120, 100%, 40%);">+        3) Access Point Name</span><br><span style="color: hsl(120, 100%, 40%);">+        4) IP version: 'ipv4' or 'ipv6'</span><br><span style="color: hsl(120, 100%, 40%);">+        5) IP address: first IP address for ipv4 and link local address for IPv6</span><br><span style="color: hsl(120, 100%, 40%);">+        6) First IP address</span><br><span style="color: hsl(120, 100%, 40%);">+        7) Last IP address</span><br><span style="color: hsl(120, 100%, 40%);">+  */</span><br><span style="color: hsl(120, 100%, 40%);">+  tun_setup_script: "${epc.ifup_filename}",</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* If true, inter-UE routing is done inside the MME (hence no IP</span><br><span style="color: hsl(120, 100%, 40%);">+     packet is output to the virtual network interface in case of</span><br><span style="color: hsl(120, 100%, 40%);">+     inter-UE communication). Otherwise, it is done by the Linux IP</span><br><span style="color: hsl(120, 100%, 40%);">+     layer. */</span><br><span style="color: hsl(120, 100%, 40%);">+  ue_to_ue_forwarding: false,</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* NAS ciphering algorithm preference. EEA0 is always the last. */</span><br><span style="color: hsl(120, 100%, 40%);">+  nas_cipher_algo_pref: [ ],</span><br><span style="color: hsl(120, 100%, 40%);">+  /* NAS integrity algorithm preference. EIA0 is always the last. */</span><br><span style="color: hsl(120, 100%, 40%);">+  nas_integ_algo_pref: [ 2, 1 ],</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* user data base */</span><br><span style="color: hsl(120, 100%, 40%);">+  ue_db: [</span><br><span style="color: hsl(120, 100%, 40%);">+%for sub in epc.hss.subscribers:</span><br><span style="color: hsl(120, 100%, 40%);">+    {</span><br><span style="color: hsl(120, 100%, 40%);">+      sim_algo: "${sub.auth_algo}", /* USIM authentication algorithm: xor, milenage or tuak */</span><br><span style="color: hsl(120, 100%, 40%);">+      imsi: "${sub.imsi}", /* Anritsu Test USIM */</span><br><span style="color: hsl(120, 100%, 40%);">+      amf: 0x9001, /* Authentication Management Field */</span><br><span style="color: hsl(120, 100%, 40%);">+      sqn: "000000000000", /* Sequence Number */</span><br><span style="color: hsl(120, 100%, 40%);">+      K: "${sub.ki}", /* Anritsu Test USIM */</span><br><span style="color: hsl(120, 100%, 40%);">+      /* if true, allow several UEs to have the same IMSI (useful</span><br><span style="color: hsl(120, 100%, 40%);">+         with test SIM cards). They are distinguished with their</span><br><span style="color: hsl(120, 100%, 40%);">+         IMEI. default = false. */</span><br><span style="color: hsl(120, 100%, 40%);">+      multi_sim: true,</span><br><span style="color: hsl(120, 100%, 40%);">+    },</span><br><span style="color: hsl(120, 100%, 40%);">+%endfor</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Add new entries for each IMSI/K */</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%);">+  /* persistent user database */</span><br><span style="color: hsl(120, 100%, 40%);">+  //ue_db_filename: "lte_ue.db",</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/utils/bin/osmo-gsm-tester_amarisoft_ltemme_ifup.sh b/utils/bin/osmo-gsm-tester_amarisoft_ltemme_ifup.sh</span><br><span>new file mode 100755</span><br><span>index 0000000..d502123</span><br><span>--- /dev/null</span><br><span>+++ b/utils/bin/osmo-gsm-tester_amarisoft_ltemme_ifup.sh</span><br><span>@@ -0,0 +1,16 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#!/bin/bash -e</span><br><span style="color: hsl(120, 100%, 40%);">+ifname="$1"     # Interface name</span><br><span style="color: hsl(120, 100%, 40%);">+index="$2"      # Network index (PDN index)</span><br><span style="color: hsl(120, 100%, 40%);">+apn="$3"        # Access point name</span><br><span style="color: hsl(120, 100%, 40%);">+type="$4"       # ipv4 or ipv6</span><br><span style="color: hsl(120, 100%, 40%);">+ifaddr="$5" # Interface address</span><br><span style="color: hsl(120, 100%, 40%);">+addr1="$6"  # First IP address</span><br><span style="color: hsl(120, 100%, 40%);">+addr2="$7"  # Last IP address</span><br><span style="color: hsl(120, 100%, 40%);">+mask="$8"   # Mask</span><br><span style="color: hsl(120, 100%, 40%);">+echo "*** Configuring $type APN[$index] '$apn' on ${ifname}, $ifaddr/$mask, ${addr1}..${addr2}"</span><br><span style="color: hsl(120, 100%, 40%);">+if [ "$type" = "ipv4" ] ; then</span><br><span style="color: hsl(120, 100%, 40%);">+        ifconfig ${ifname} ${ifaddr}/${mask} up</span><br><span style="color: hsl(120, 100%, 40%);">+else</span><br><span style="color: hsl(120, 100%, 40%);">+        ifconfig ${ifname} inet6 add ${addr1}/${mask} up</span><br><span style="color: hsl(120, 100%, 40%);">+fi</span><br><span style="color: hsl(120, 100%, 40%);">+echo "*** done configuring interface ${ifname}"</span><br><span>diff --git a/utils/sudoers.d/osmo-gsm-tester_amarisoft_ltemme_ifup b/utils/sudoers.d/osmo-gsm-tester_amarisoft_ltemme_ifup</span><br><span>new file mode 100644</span><br><span>index 0000000..a8cd298</span><br><span>--- /dev/null</span><br><span>+++ b/utils/sudoers.d/osmo-gsm-tester_amarisoft_ltemme_ifup</span><br><span>@@ -0,0 +1 @@</span><br><span style="color: hsl(120, 100%, 40%);">+%osmo-gsm-tester ALL=(root) NOPASSWD: /usr/local/bin/osmo-gsm-tester_amarisoft_ltemme_ifup.sh</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-gsm-tester/+/17690">change 17690</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/+/17690"/><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: Ia50ea6a74b63b2d688c8d683aea11416ad40a6d3 </div>
<div style="display:none"> Gerrit-Change-Number: 17690 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>