<p>srs_andre would like Nils to <strong>review</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-gsm-tester/+/21217">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Modems: Introduce Android UEs<br><br>To expand the test capacities we would like to introduce<br>Android UEs as a new modem. Currently the following tests<br>are supported:<br>- Ping<br>- iPerf3 DL/UL<br>- RRC Mobile MT Ping<br><br>Change-Id: Iab37a0de59d6643d21bced34ddca06ff40fa62df<br>---<br>M src/osmo_gsm_tester/core/process.py<br>M src/osmo_gsm_tester/core/remote.py<br>M src/osmo_gsm_tester/core/schema.py<br>M src/osmo_gsm_tester/obj/enb_srs.py<br>M src/osmo_gsm_tester/obj/iperf3.py<br>M src/osmo_gsm_tester/obj/ms.py<br>A src/osmo_gsm_tester/obj/ms_android.py<br>M src/osmo_gsm_tester/obj/run_node.py<br>M sysmocom/default-suites.conf<br>A sysmocom/scenarios/androidue@.conf<br>M sysmocom/suites/4g/iperf3_dl.py<br>M sysmocom/suites/4g/iperf3_ul.py<br>A utils/bin/osmo-gsm-tester_androidue_conn_chk.sh<br>A utils/bin/osmo-gsm-tester_androidue_diag_parser.sh<br>14 files changed, 607 insertions(+), 12 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/17/21217/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/osmo_gsm_tester/core/process.py b/src/osmo_gsm_tester/core/process.py</span><br><span>index eaf8de7..5840881 100644</span><br><span>--- a/src/osmo_gsm_tester/core/process.py</span><br><span>+++ b/src/osmo_gsm_tester/core/process.py</span><br><span>@@ -381,12 +381,24 @@</span><br><span> </span><br><span> class RemoteProcess(Process):</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self, name, run_dir, remote_user, remote_host, remote_cwd, popen_args, remote_env={}, **popen_kwargs):</span><br><span style="color: hsl(120, 100%, 40%);">+ def __init__(self, name, run_dir, remote_user, remote_host, remote_cwd, popen_args,</span><br><span style="color: hsl(120, 100%, 40%);">+ remote_env={}, remote_port=None, **popen_kwargs):</span><br><span> super().__init__(name, run_dir, popen_args, **popen_kwargs)</span><br><span> self.remote_user = remote_user</span><br><span> self.remote_host = remote_host</span><br><span> self.remote_cwd = remote_cwd</span><br><span> self.remote_env = remote_env</span><br><span style="color: hsl(120, 100%, 40%);">+ self.remote_port = remote_port</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # check if the command should be executed on an Android UE</span><br><span style="color: hsl(120, 100%, 40%);">+ is_ue_cmd = False</span><br><span style="color: hsl(120, 100%, 40%);">+ android_cmds = ['iperf3-cli', 'ping', 'set-airplane-mode', 'set-apn', 'get-ip',</span><br><span style="color: hsl(120, 100%, 40%);">+ 'rx-monitor', 'tx-monitor', 'diag-monitor', 'kill-diag-monitor', 'clear-diag_logs']</span><br><span style="color: hsl(120, 100%, 40%);">+ if self.remote_port:</span><br><span style="color: hsl(120, 100%, 40%);">+ for cmd in android_cmds:</span><br><span style="color: hsl(120, 100%, 40%);">+ if cmd in name:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.remote_user = 'root'</span><br><span style="color: hsl(120, 100%, 40%);">+ is_ue_cmd = True</span><br><span> </span><br><span> # hacky: instead of just prepending ssh, i.e. piping stdout and stderr</span><br><span> # over the ssh link, we should probably run on the remote side,</span><br><span>@@ -402,6 +414,12 @@</span><br><span> '%s %s %s' % (cd,</span><br><span> ' '.join(['%s=%r'%(k,v) for k,v in self.remote_env.items()]),</span><br><span> ' '.join(self.popen_args))]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # add arguments to directly connect to the Android UE</span><br><span style="color: hsl(120, 100%, 40%);">+ if is_ue_cmd:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.popen_args.insert(1, '-p') # add ssh parameters</span><br><span style="color: hsl(120, 100%, 40%);">+ self.popen_args.insert(2, str(self.remote_port))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> self.dbg(self.popen_args, dir=self.run_dir, conf=self.popen_kwargs, remote_env=self.remote_env)</span><br><span> </span><br><span> def RunError(self, msg_prefix):</span><br><span>@@ -443,14 +461,21 @@</span><br><span> super().__init__(name, run_dir, remote_user, remote_host, remote_cwd, args, **popen_kwargs)</span><br><span> </span><br><span> def run_local_sync(run_dir, name, popen_args):</span><br><span style="color: hsl(0, 100%, 40%);">- run_dir =run_dir.new_dir(name)</span><br><span style="color: hsl(120, 100%, 40%);">+ run_dir = run_dir.new_dir(name)</span><br><span> proc = Process(name, run_dir, popen_args)</span><br><span> proc.launch_sync()</span><br><span> return proc</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+def run_local(run_dir, name, popen_args):</span><br><span style="color: hsl(120, 100%, 40%);">+ run_dir = run_dir.new_dir(name)</span><br><span style="color: hsl(120, 100%, 40%);">+ proc = Process(name, run_dir, popen_args)</span><br><span style="color: hsl(120, 100%, 40%);">+ proc.launch()</span><br><span style="color: hsl(120, 100%, 40%);">+ return proc</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> def run_local_netns_sync(run_dir, name, netns, popen_args):</span><br><span style="color: hsl(0, 100%, 40%);">- run_dir =run_dir.new_dir(name)</span><br><span style="color: hsl(120, 100%, 40%);">+ run_dir = run_dir.new_dir(name)</span><br><span> proc = NetNSProcess(name, run_dir, netns, popen_args)</span><br><span> proc.launch_sync()</span><br><span> return proc</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/core/remote.py b/src/osmo_gsm_tester/core/remote.py</span><br><span>index 8deb25d..ef77c2cd 100644</span><br><span>--- a/src/osmo_gsm_tester/core/remote.py</span><br><span>+++ b/src/osmo_gsm_tester/core/remote.py</span><br><span>@@ -28,13 +28,14 @@</span><br><span> </span><br><span> WRAPPER_SCRIPT = 'ssh_sigkiller.sh'</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self, run_dir, remote_user = 'root', remote_host = 'localhost', remote_cwd=None):</span><br><span style="color: hsl(120, 100%, 40%);">+ def __init__(self, run_dir, remote_user = 'root', remote_host = 'localhost', remote_cwd=None, remote_port=None):</span><br><span> super().__init__(log.C_RUN, 'host-' + remote_user + '@' + remote_host)</span><br><span> self.run_dir = util.Dir(run_dir.new_dir(self.name()))</span><br><span> self.remote_user = remote_user</span><br><span> self.remote_host = remote_host</span><br><span> self.remote_cwd = remote_cwd</span><br><span> self.remote_env = {}</span><br><span style="color: hsl(120, 100%, 40%);">+ self.remote_port = remote_port</span><br><span> </span><br><span> def user(self):</span><br><span> return self.remote_user</span><br><span>@@ -51,9 +52,13 @@</span><br><span> def get_remote_env(self):</span><br><span> return self.remote_env</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ def ssh_port(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.remote_port</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> def RemoteProcess(self, name, popen_args, remote_env={}, **popen_kwargs):</span><br><span> run_dir = self.run_dir.new_dir(name)</span><br><span style="color: hsl(0, 100%, 40%);">- return process.RemoteProcess(name, run_dir, self.user(), self.host(), self.cwd(), popen_args, remote_env=remote_env, **popen_kwargs)</span><br><span style="color: hsl(120, 100%, 40%);">+ return process.RemoteProcess(name, run_dir, self.user(), self.host(), self.cwd(), popen_args,</span><br><span style="color: hsl(120, 100%, 40%);">+ remote_env=remote_env, remote_port=self.ssh_port(), **popen_kwargs)</span><br><span> </span><br><span> def generate_wrapper_script(self, wait_time_sec):</span><br><span> wrapper_script = self.run_dir.new_file(RemoteHost.WRAPPER_SCRIPT)</span><br><span>diff --git a/src/osmo_gsm_tester/core/schema.py b/src/osmo_gsm_tester/core/schema.py</span><br><span>index d56d6ec..6496e57 100644</span><br><span>--- a/src/osmo_gsm_tester/core/schema.py</span><br><span>+++ b/src/osmo_gsm_tester/core/schema.py</span><br><span>@@ -111,7 +111,7 @@</span><br><span> raise ValueError('Unknown Cipher value: %r' % val)</span><br><span> </span><br><span> def modem_feature(val):</span><br><span style="color: hsl(0, 100%, 40%);">- if val in ('sms', 'gprs', 'voice', 'ussd', 'sim', '2g', '3g', '4g', 'dl_qam256', 'ul_qam64'):</span><br><span style="color: hsl(120, 100%, 40%);">+ if val in ('sms', 'gprs', 'voice', 'ussd', 'sim', '2g', '3g', '4g', 'dl_qam256', 'ul_qam64', 'qc_diag'):</span><br><span> return True</span><br><span> raise ValueError('Unknown Modem Feature: %r' % val)</span><br><span> </span><br><span>diff --git a/src/osmo_gsm_tester/obj/enb_srs.py b/src/osmo_gsm_tester/obj/enb_srs.py</span><br><span>index 53beda8..307368f 100644</span><br><span>--- a/src/osmo_gsm_tester/obj/enb_srs.py</span><br><span>+++ b/src/osmo_gsm_tester/obj/enb_srs.py</span><br><span>@@ -114,6 +114,7 @@</span><br><span> self.start_remotely()</span><br><span> </span><br><span> # send t+Enter to enable console trace</span><br><span style="color: hsl(120, 100%, 40%);">+ MainLoop.sleep(3)</span><br><span> self.dbg('Enabling console trace')</span><br><span> self.process.stdin_write('t\n')</span><br><span> </span><br><span>diff --git a/src/osmo_gsm_tester/obj/iperf3.py b/src/osmo_gsm_tester/obj/iperf3.py</span><br><span>index 4785f78..f0309d2 100644</span><br><span>--- a/src/osmo_gsm_tester/obj/iperf3.py</span><br><span>+++ b/src/osmo_gsm_tester/obj/iperf3.py</span><br><span>@@ -232,7 +232,7 @@</span><br><span> locally = not self._run_node or self._run_node.is_local()</span><br><span> return locally</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def prepare_test_proc(self, dir=None, netns=None, time_sec=None, proto=None, bitrate=0, tos=None):</span><br><span style="color: hsl(120, 100%, 40%);">+ def prepare_test_proc(self, dir=None, netns=None, time_sec=None, proto=None, bitrate=0, tos=None, ue=None):</span><br><span> values = config.get_defaults('iperf3cli')</span><br><span> config.overlay(values, self.testenv.suite().config().get('iperf3cli', {}))</span><br><span> </span><br><span>@@ -264,6 +264,12 @@</span><br><span> popen_args = ('iperf3', '-c', self.server.addr(),</span><br><span> '-p', str(self.server.port()), '-J',</span><br><span> '-t', str(time_sec))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # In case the modem is an Android UE we have to extend the iPerf3 command for local execution</span><br><span style="color: hsl(120, 100%, 40%);">+ if self._run_node.is_local() and ue.ue_serial:</span><br><span style="color: hsl(120, 100%, 40%);">+ adb_cmd_pref = ['adb', '-s', ue.ue_serial, 'exec-out', 'su', '-c']</span><br><span style="color: hsl(120, 100%, 40%);">+ popen_args = adb_cmd_pref + list(popen_args)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> if dir == IPerf3Client.DIR_DL:</span><br><span> popen_args += ('-R',)</span><br><span> elif dir == IPerf3Client.DIR_BI:</span><br><span>@@ -281,7 +287,8 @@</span><br><span> return proc</span><br><span> </span><br><span> def prepare_test_proc_remotely(self, netns, popen_args):</span><br><span style="color: hsl(0, 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%);">+ 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%);">+ None, self._run_node.ssh_port())</span><br><span> </span><br><span> remote_prefix_dir = util.Dir(IPerf3Client.REMOTE_DIR)</span><br><span> remote_run_dir = util.Dir(remote_prefix_dir.child('cli-' + str(self)))</span><br><span>diff --git a/src/osmo_gsm_tester/obj/ms.py b/src/osmo_gsm_tester/obj/ms.py</span><br><span>index 70ce558..bfd3f3b 100644</span><br><span>--- a/src/osmo_gsm_tester/obj/ms.py</span><br><span>+++ b/src/osmo_gsm_tester/obj/ms.py</span><br><span>@@ -72,6 +72,9 @@</span><br><span> elif ms_type == 'srsue':</span><br><span> from .ms_srs import srsUE</span><br><span> ms_class = srsUE</span><br><span style="color: hsl(120, 100%, 40%);">+ elif ms_type == 'androidue':</span><br><span style="color: hsl(120, 100%, 40%);">+ from .ms_android import AndroidUE</span><br><span style="color: hsl(120, 100%, 40%);">+ ms_class = AndroidUE</span><br><span> elif ms_type == 'amarisoftue':</span><br><span> from .ms_amarisoft import AmarisoftUE</span><br><span> ms_class = AmarisoftUE</span><br><span>diff --git a/src/osmo_gsm_tester/obj/ms_android.py b/src/osmo_gsm_tester/obj/ms_android.py</span><br><span>new file mode 100644</span><br><span>index 0000000..0d9ed16</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo_gsm_tester/obj/ms_android.py</span><br><span>@@ -0,0 +1,526 @@</span><br><span style="color: hsl(120, 100%, 40%);">+# Author: Nils Fürste <nils.fuerste@softwareradiosystems.com></span><br><span style="color: hsl(120, 100%, 40%);">+# Author: Bedran Karakoc <bedran.karakoc@softwareradiosystems.com></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+import pprint</span><br><span style="color: hsl(120, 100%, 40%);">+import time</span><br><span style="color: hsl(120, 100%, 40%);">+import re</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from ..core import log, util, config, remote, process</span><br><span style="color: hsl(120, 100%, 40%);">+from ..core import schema</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%);">+from .srslte_common import srslte_common</span><br><span style="color: hsl(120, 100%, 40%);">+from .ms_srs import srsUEMetrics</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%);">+def on_register_schemas():</span><br><span style="color: hsl(120, 100%, 40%);">+ resource_schema = {</span><br><span style="color: hsl(120, 100%, 40%);">+ 'additional_args[]': schema.STR,</span><br><span style="color: hsl(120, 100%, 40%);">+ 'apn': schema.STR,</span><br><span style="color: hsl(120, 100%, 40%);">+ 'apn_name': schema.STR,</span><br><span style="color: hsl(120, 100%, 40%);">+ 'apn_mcc': schema.STR,</span><br><span style="color: hsl(120, 100%, 40%);">+ 'apn_mnc': schema.STR,</span><br><span style="color: hsl(120, 100%, 40%);">+ 'sel_apn': schema.STR,</span><br><span style="color: hsl(120, 100%, 40%);">+ 'ue_serial': schema.STR,</span><br><span style="color: hsl(120, 100%, 40%);">+ 'enable_pcap': schema.BOOL_STR,</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, val in RunNode.schema().items():</span><br><span style="color: hsl(120, 100%, 40%);">+ resource_schema['run_node.%s' % key] = val</span><br><span style="color: hsl(120, 100%, 40%);">+ schema.register_resource_schema('modem', resource_schema)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ config_schema = {</span><br><span style="color: hsl(120, 100%, 40%);">+ 'enable_pcap': schema.BOOL_STR,</span><br><span style="color: hsl(120, 100%, 40%);">+ 'log_all_level': schema.STR,</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ schema.register_config_schema('modem', config_schema)</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 AndroidUE(MS, srslte_common):</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ REMOTEDIR = '/osmo-gsm-tester-androidue'</span><br><span style="color: hsl(120, 100%, 40%);">+ METRICSFILE = 'android_ue_metrics.csv'</span><br><span style="color: hsl(120, 100%, 40%);">+ PCAPFILE = 'android_ue.pcap'</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def __init__(self, testenv, conf):</span><br><span style="color: hsl(120, 100%, 40%);">+ self._run_node = RunNode.from_conf(conf.get('run_node', {}))</span><br><span style="color: hsl(120, 100%, 40%);">+ super().__init__('androidue_%s' % self.addr(), testenv, conf)</span><br><span style="color: hsl(120, 100%, 40%);">+ srslte_common.__init__(self)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.run_dir = None</span><br><span style="color: hsl(120, 100%, 40%);">+ self.rem_host = None</span><br><span style="color: hsl(120, 100%, 40%);">+ self.testenv = testenv</span><br><span style="color: hsl(120, 100%, 40%);">+ self.emm_connected = False</span><br><span style="color: hsl(120, 100%, 40%);">+ self.rrc_connected = False</span><br><span style="color: hsl(120, 100%, 40%);">+ self.connect_timeout = 300 # sec</span><br><span style="color: hsl(120, 100%, 40%);">+ self.ue_serial = None # stores the UE serial if available</span><br><span style="color: hsl(120, 100%, 40%);">+ self.remote_port = None</span><br><span style="color: hsl(120, 100%, 40%);">+ self.conn_reset_intvl = 20</span><br><span style="color: hsl(120, 100%, 40%);">+ self.remote_pcap_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.ue_data_intf = None</span><br><span style="color: hsl(120, 100%, 40%);">+ self.remote_metrics_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+ self.metrics_file = None</span><br><span style="color: hsl(120, 100%, 40%);">+ self.remote_run_dir = None</span><br><span style="color: hsl(120, 100%, 40%);">+ self.have_metrics_file = False</span><br><span style="color: hsl(120, 100%, 40%);">+ self.rx_monitor_proc = None</span><br><span style="color: hsl(120, 100%, 40%);">+ self.tx_monitor_proc = None</span><br><span style="color: hsl(120, 100%, 40%);">+ self.diag_monitor_proc = None</span><br><span style="color: hsl(120, 100%, 40%);">+ self.diag_parser_proc = None</span><br><span style="color: hsl(120, 100%, 40%);">+ self.enable_pcap = 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._run_node.is_local():</span><br><span style="color: hsl(120, 100%, 40%);">+ return</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # stop monitoring</span><br><span style="color: hsl(120, 100%, 40%);">+ self.stop()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def scp_back_pcap(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ if self.enable_pcap:</span><br><span style="color: hsl(120, 100%, 40%);">+ DIAG_PARSER = 'osmo-gsm-tester_androidue_diag_parser.sh'</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%);">+ popen_args_diag_parser = [DIAG_PARSER, str(self.ue_serial), str(self.remote_run_dir), str(self.remote_pcap_file)]</span><br><span style="color: hsl(120, 100%, 40%);">+ diag_parser_proc = self.rem_host.RemoteProcess("diag-parser", popen_args_diag_parser, env={})</span><br><span style="color: hsl(120, 100%, 40%);">+ diag_parser_proc.launch()</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ popen_args_diag_parser = [DIAG_PARSER, str(self.ue_serial), str(self.run_dir), str(self.pcap_file)]</span><br><span style="color: hsl(120, 100%, 40%);">+ diag_parser_proc = process.run_local(self.run_dir, "diag-parser", popen_args_diag_parser)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ timeout_ = 300 # timeout in s</span><br><span style="color: hsl(120, 100%, 40%);">+ while timeout_ > 0:</span><br><span style="color: hsl(120, 100%, 40%);">+ diag_parser_stdout = diag_parser_proc.get_stdout()</span><br><span style="color: hsl(120, 100%, 40%);">+ if diag_parser_stdout.count('Pulling new .qmdl file...') > 1:</span><br><span style="color: hsl(120, 100%, 40%);">+ # If the parsers pulls the .qmdl file for the second time we know that</span><br><span style="color: hsl(120, 100%, 40%);">+ # the parsing of the first one is done</span><br><span style="color: hsl(120, 100%, 40%);">+ break</span><br><span style="color: hsl(120, 100%, 40%);">+ time.sleep(2)</span><br><span style="color: hsl(120, 100%, 40%);">+ timeout_ -= 2</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if timeout_ <= 0:</span><br><span style="color: hsl(120, 100%, 40%);">+ raise log.Error("Writing PCAP failed")</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%);">+ 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%);">+ else:</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 stop(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ # terminate bitrate monitors and save metrics</span><br><span style="color: hsl(120, 100%, 40%);">+ brate_rx_raw = self.rx_monitor_proc.get_stdout().split('\n')</span><br><span style="color: hsl(120, 100%, 40%);">+ brate_tx_raw = self.tx_monitor_proc.get_stdout().split('\n')</span><br><span style="color: hsl(120, 100%, 40%);">+ brate_rx_raw.remove('')</span><br><span style="color: hsl(120, 100%, 40%);">+ self.rx_monitor_proc.terminate()</span><br><span style="color: hsl(120, 100%, 40%);">+ brate_tx_raw.remove('')</span><br><span style="color: hsl(120, 100%, 40%);">+ self.tx_monitor_proc.terminate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.save_metrics(brate_rx_raw[1:], brate_tx_raw[1:])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # kill diag monitor if started</span><br><span style="color: hsl(120, 100%, 40%);">+ if self.diag_monitor_proc:</span><br><span style="color: hsl(120, 100%, 40%);">+ kill_diag_proc = self.rem_host.RemoteProcess("kill-diag-monitor", ['/vendor/bin/diag_mdlog', '-k'], env={})</span><br><span style="color: hsl(120, 100%, 40%);">+ kill_diag_proc.launch_sync()</span><br><span style="color: hsl(120, 100%, 40%);">+ time.sleep(3)</span><br><span style="color: hsl(120, 100%, 40%);">+ if self.diag_monitor_proc.is_running():</span><br><span style="color: hsl(120, 100%, 40%);">+ self.diag_monitor_proc.terminate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.diag_parser_proc.terminate()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # enable airplane mode</span><br><span style="color: hsl(120, 100%, 40%);">+ self.set_airplane_mode(True)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # scp back pcap file</span><br><span style="color: hsl(120, 100%, 40%);">+ self.scp_back_pcap()</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%);">+ # check if device is available over ADB</span><br><span style="color: hsl(120, 100%, 40%);">+ if not self.check_device_availability():</span><br><span style="color: hsl(120, 100%, 40%);">+ self.log("Can't find requested device. Restarting ADB and check again")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.restart_adb_inst(True)</span><br><span style="color: hsl(120, 100%, 40%);">+ if not self.check_device_availability():</span><br><span style="color: hsl(120, 100%, 40%);">+ raise log.Error("Device with serial %s is not available" % self.ue_serial)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # enable airplane mode</span><br><span style="color: hsl(120, 100%, 40%);">+ self.set_airplane_mode(True)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # clear working directories</span><br><span style="color: hsl(120, 100%, 40%);">+ self.clear_work_dirs()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def clear_work_dirs(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ # clear remote_run_dir</span><br><span style="color: hsl(120, 100%, 40%);">+ popen_args_clear_run_dir = ['sudo', 'rm', '-rf', '-v', str(self.remote_run_dir) + '/*', '||', 'true']</span><br><span style="color: hsl(120, 100%, 40%);">+ clear_run_dir_proc = self.run_netns_wait('clear-run_dir', popen_args_clear_run_dir)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.dbg("Deleted the following files: %s" % clear_run_dir_proc.get_stdout())</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # clear diag_logs</span><br><span style="color: hsl(120, 100%, 40%);">+ popen_args_clear_diag_logs = ['rm', '-r', '/data/local/tmp/diag_logs/*', '||', 'true']</span><br><span style="color: hsl(120, 100%, 40%);">+ clear_diag_logs_proc = self.run_netns_wait('clear-diag_logs', popen_args_clear_diag_logs)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.dbg("Deleted the following files: %s" % clear_diag_logs_proc.get_stdout())</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def check_device_availability(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ serials_cmd = ['adb', 'devices']</span><br><span style="color: hsl(120, 100%, 40%);">+ proc = self.run_netns_wait("devices", serials_cmd)</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.ue_serial in proc.get_stdout()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def restart_adb_inst(self, as_root=False):</span><br><span style="color: hsl(120, 100%, 40%);">+ self.run_netns_wait("kill-adb", ['sudo', 'adb', 'kill-server'])</span><br><span style="color: hsl(120, 100%, 40%);">+ if as_root:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.run_netns_wait("start-adb", ['adb', 'start-server'])</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.run_netns_wait("start-adb", ['sudo', 'adb', 'start-server'])</span><br><span style="color: hsl(120, 100%, 40%);">+ return</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 AndroidUE')</span><br><span style="color: hsl(120, 100%, 40%);">+ self.configure()</span><br><span style="color: hsl(120, 100%, 40%);">+ CONN_CHK = 'osmo-gsm-tester_androidue_conn_chk.sh'</span><br><span style="color: hsl(120, 100%, 40%);">+ popen_args_emm_conn_chk = [CONN_CHK, self.ue_serial]</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%);">+ emm_conn_chk_proc = self.rem_host.RemoteProcess('emm-conn-chk', popen_args_emm_conn_chk, env={})</span><br><span style="color: hsl(120, 100%, 40%);">+ emm_conn_chk_proc.launch()</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ emm_conn_chk_proc = process.run_local(self.run_dir, 'emm-conn-chk', popen_args_emm_conn_chk)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # check connection status</span><br><span style="color: hsl(120, 100%, 40%);">+ timer = self.connect_timeout</span><br><span style="color: hsl(120, 100%, 40%);">+ while timer > 0:</span><br><span style="color: hsl(120, 100%, 40%);">+ if 'LTE' in emm_conn_chk_proc.get_stdout():</span><br><span style="color: hsl(120, 100%, 40%);">+ if self.get_assigned_addr():</span><br><span style="color: hsl(120, 100%, 40%);">+ self.emm_connected = True</span><br><span style="color: hsl(120, 100%, 40%);">+ self.rrc_connected = True</span><br><span style="color: hsl(120, 100%, 40%);">+ emm_conn_chk_proc.terminate()</span><br><span style="color: hsl(120, 100%, 40%);">+ break</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # reset connection</span><br><span style="color: hsl(120, 100%, 40%);">+ if timer % self.conn_reset_intvl == 0:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.set_airplane_mode(True)</span><br><span style="color: hsl(120, 100%, 40%);">+ time.sleep(2)</span><br><span style="color: hsl(120, 100%, 40%);">+ timer -= 2</span><br><span style="color: hsl(120, 100%, 40%);">+ self.set_airplane_mode(False)</span><br><span style="color: hsl(120, 100%, 40%);">+ time.sleep(1)</span><br><span style="color: hsl(120, 100%, 40%);">+ timer -= 1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if timer == 0:</span><br><span style="color: hsl(120, 100%, 40%);">+ raise log.Error("Android UE %s connection timer expired" % self.ue_serial)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # start bit rate monitoring on Android UE</span><br><span style="color: hsl(120, 100%, 40%);">+ popen_args_rx = ['while', 'true;', 'do',</span><br><span style="color: hsl(120, 100%, 40%);">+ 'echo', '`cat', '/sys/class/net/' + self.ue_data_intf + '/statistics/rx_bytes`;',</span><br><span style="color: hsl(120, 100%, 40%);">+ 'sleep', '1;', 'done']</span><br><span style="color: hsl(120, 100%, 40%);">+ popen_args_tx = ['while', 'true;', 'do',</span><br><span style="color: hsl(120, 100%, 40%);">+ 'echo', '`cat', '/sys/class/net/' + self.ue_data_intf + '/statistics/tx_bytes`;',</span><br><span style="color: hsl(120, 100%, 40%);">+ 'sleep', '1;', 'done']</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.rx_monitor_proc = self.rem_host.RemoteProcess("rx-monitor", popen_args_rx, env={})</span><br><span style="color: hsl(120, 100%, 40%);">+ self.rx_monitor_proc.launch()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.tx_monitor_proc = self.rem_host.RemoteProcess("tx-monitor", popen_args_tx, env={})</span><br><span style="color: hsl(120, 100%, 40%);">+ self.tx_monitor_proc.launch()</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.rx_monitor_proc = process.run_local(self.run_dir, "rx-monitor", popen_args_rx)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.tx_monitor_proc = process.run_local(self.run_dir, "tx-monitor", popen_args_tx)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # start diag_mdlog and parsing</span><br><span style="color: hsl(120, 100%, 40%);">+ if 'qc_diag' in self.features():</span><br><span style="color: hsl(120, 100%, 40%);">+ DIAG_PARSER = 'osmo-gsm-tester_androidue_diag_parser.sh'</span><br><span style="color: hsl(120, 100%, 40%);">+ self.pcap_file = self.run_dir.child(AndroidUE.PCAPFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.remote_pcap_file = self.remote_run_dir.child(AndroidUE.PCAPFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ popen_args_diag = ['/vendor/bin/diag_mdlog', '-s', '90000', '-f', '/data/local/tmp/ogt_diag.cfg',</span><br><span style="color: hsl(120, 100%, 40%);">+ '-o', '/data/local/tmp/diag_logs']</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.diag_monitor_proc = self.rem_host.RemoteProcess("diag-monitor", popen_args_diag, env={})</span><br><span style="color: hsl(120, 100%, 40%);">+ self.diag_monitor_proc.launch()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ popen_args_diag_parser = [DIAG_PARSER, str(self.ue_serial), str(self.remote_run_dir), str(self.remote_pcap_file)]</span><br><span style="color: hsl(120, 100%, 40%);">+ self.diag_parser_proc = self.rem_host.RemoteProcess("diag-parser", popen_args_diag_parser, env={})</span><br><span style="color: hsl(120, 100%, 40%);">+ self.diag_parser_proc.launch()</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.diag_monitor_proc = process.run_local(self.run_dir, "diag-monitor", popen_args_diag)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.diag_monitor_proc.launch()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ popen_args_diag_parser = [DIAG_PARSER, str(self.ue_serial), str(self.run_dir), str(self.pcap_file)]</span><br><span style="color: hsl(120, 100%, 40%);">+ self.diag_parser_proc = process.run_local(self.run_dir, "diag-parser", popen_args_diag_parser)</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%);">+ values = dict(ue=config.get_defaults('androidue'))</span><br><span style="color: hsl(120, 100%, 40%);">+ config.overlay(values, dict(ue=self.testenv.suite().config().get('modem', {})))</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%);">+ self.dbg('AndroidUE CONFIG:\n' + pprint.pformat(values))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ self.remote_port = values['ue']['run_node']['remote_port']</span><br><span style="color: hsl(120, 100%, 40%);">+ self.ue_serial = values['ue']['ue_serial']</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if 'qc_diag' in self.features():</span><br><span style="color: hsl(120, 100%, 40%);">+ self.enable_pcap = util.str2bool(values['ue'].get('enable_pcap', 'false'))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ self.run_dir = util.Dir(self.testenv.test().get_run_dir().new_dir(self.name()))</span><br><span style="color: hsl(120, 100%, 40%);">+ self.metrics_file = self.run_dir.child(AndroidUE.METRICSFILE)</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(),</span><br><span style="color: hsl(120, 100%, 40%);">+ self._run_node.ssh_addr(), None, remote_port=self.remote_port)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.remote_run_dir = util.Dir(AndroidUE.REMOTEDIR)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.remote_metrics_file = self.remote_run_dir.child(AndroidUE.METRICSFILE)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # set APN</span><br><span style="color: hsl(120, 100%, 40%);">+ apn_params = {</span><br><span style="color: hsl(120, 100%, 40%);">+ "carrier": str(values['ue']['apn_name'] or 'default'),</span><br><span style="color: hsl(120, 100%, 40%);">+ "apn": str(values['ue']['apn']), # mandatory</span><br><span style="color: hsl(120, 100%, 40%);">+ "proxy": str(''),</span><br><span style="color: hsl(120, 100%, 40%);">+ "port": str(''),</span><br><span style="color: hsl(120, 100%, 40%);">+ "user": str(''),</span><br><span style="color: hsl(120, 100%, 40%);">+ "password": str(''),</span><br><span style="color: hsl(120, 100%, 40%);">+ "server": str(''),</span><br><span style="color: hsl(120, 100%, 40%);">+ "mmsc": str(''),</span><br><span style="color: hsl(120, 100%, 40%);">+ "mmsport": str(''),</span><br><span style="color: hsl(120, 100%, 40%);">+ "mmsproxy": str(''),</span><br><span style="color: hsl(120, 100%, 40%);">+ "mcc": str(values['ue']['apn_mcc']), # mandatory</span><br><span style="color: hsl(120, 100%, 40%);">+ "mnc": str(values['ue']['apn_mnc']), # mandatory</span><br><span style="color: hsl(120, 100%, 40%);">+ "auth": str('-1'),</span><br><span style="color: hsl(120, 100%, 40%);">+ "type": str(''),</span><br><span style="color: hsl(120, 100%, 40%);">+ "protocol": str(''),</span><br><span style="color: hsl(120, 100%, 40%);">+ "mvnotype": str(''),</span><br><span style="color: hsl(120, 100%, 40%);">+ "mvnoval": str(''),</span><br><span style="color: hsl(120, 100%, 40%);">+ "groupid": str('-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%);">+ # make sure UE is not in airplane mode</span><br><span style="color: hsl(120, 100%, 40%);">+ self.set_airplane_mode(False)</span><br><span style="color: hsl(120, 100%, 40%);">+ time.sleep(1)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ self.dbg("Set APN parameters: " + str(apn_params))</span><br><span style="color: hsl(120, 100%, 40%);">+ # self.set_apn(apn_params, True)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # move back in airplane mode</span><br><span style="color: hsl(120, 100%, 40%);">+ time.sleep(1)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.set_airplane_mode(False)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # clear working directories</span><br><span style="color: hsl(120, 100%, 40%);">+ self.clear_work_dirs()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def is_rrc_connected(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ if not ('qc_diag' in self.features()):</span><br><span style="color: hsl(120, 100%, 40%);">+ raise log.Error("Checking RRC state not supported (missing qc_diag feature?)")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if not self.diag_monitor_proc:</span><br><span style="color: hsl(120, 100%, 40%);">+ raise log.Error("Diag monitor crashed or not started")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ diag_mon_stdout_l = self.diag_monitor_proc.get_stdout().split("\n")</span><br><span style="color: hsl(120, 100%, 40%);">+ rrc_connected = self.rrc_connected</span><br><span style="color: hsl(120, 100%, 40%);">+ for line in diag_mon_stdout_l:</span><br><span style="color: hsl(120, 100%, 40%);">+ if "rrc_state=RRC_IDLE_CAMPED" in line:</span><br><span style="color: hsl(120, 100%, 40%);">+ rrc_connected = False</span><br><span style="color: hsl(120, 100%, 40%);">+ # elif "LTE_RRC_STATE_CHANGE: RRC_IDLE_NOT_CAMPED" in line: # UE lost connection, throw exception</span><br><span style="color: hsl(120, 100%, 40%);">+ # raise log.Error("Android UE lost connection to the eNB")</span><br><span style="color: hsl(120, 100%, 40%);">+ elif "rrc_state=" in line:</span><br><span style="color: hsl(120, 100%, 40%);">+ rrc_connected = True</span><br><span style="color: hsl(120, 100%, 40%);">+ return rrc_connected</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def is_registered(self, mcc_mnc=None):</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.emm_connected</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def get_counter(self, counter_name):</span><br><span style="color: hsl(120, 100%, 40%);">+ self.stop()</span><br><span style="color: hsl(120, 100%, 40%);">+ if counter_name == 'prach_sent':</span><br><span style="color: hsl(120, 100%, 40%);">+ # not implemented so far, return 2 to pass tests</span><br><span style="color: hsl(120, 100%, 40%);">+ return 2</span><br><span style="color: hsl(120, 100%, 40%);">+ elif counter_name == 'paging_received':</span><br><span style="color: hsl(120, 100%, 40%);">+ diag_parser_stdout_l = self.diag_parser_proc.get_stdout().split("\n")</span><br><span style="color: hsl(120, 100%, 40%);">+ return diag_parser_stdout_l.count('Paging received')</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ raise log.Error("Counter %s not implemented" % counter_name)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def get_assigned_addr(self, ipv6=False):</span><br><span style="color: hsl(120, 100%, 40%);">+ ip_prefix = "172.16.0"</span><br><span style="color: hsl(120, 100%, 40%);">+ proc = self.run_netns_wait("get-ip", ['ip', 'addr', 'show'])</span><br><span style="color: hsl(120, 100%, 40%);">+ out_l = proc.get_stdout().split('\n')</span><br><span style="color: hsl(120, 100%, 40%);">+ ip = None</span><br><span style="color: hsl(120, 100%, 40%);">+ for line in out_l:</span><br><span style="color: hsl(120, 100%, 40%);">+ if ip_prefix in line:</span><br><span style="color: hsl(120, 100%, 40%);">+ ip = line.split(' ')[5][:-3] # UE's IP</span><br><span style="color: hsl(120, 100%, 40%);">+ self.ue_data_intf = line.split(' ')[-1] # UE's data interface</span><br><span style="color: hsl(120, 100%, 40%);">+ return ip</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%);">+ # check if device is available over ADB</span><br><span style="color: hsl(120, 100%, 40%);">+ if not (self.ue_serial is None):</span><br><span style="color: hsl(120, 100%, 40%);">+ serials_cmd = ['adb', 'devices']</span><br><span style="color: hsl(120, 100%, 40%);">+ proc = self.run_netns_wait("devices", serials_cmd)</span><br><span style="color: hsl(120, 100%, 40%);">+ if self.ue_serial in proc.get_stdout():</span><br><span style="color: hsl(120, 100%, 40%);">+ return True</span><br><span style="color: hsl(120, 100%, 40%);">+ self.dbg("Device with serial %s is currently not available" % self.ue_serial)</span><br><span style="color: hsl(120, 100%, 40%);">+ return False</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._run_node.run_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%);">+ def features(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ return self._conf.get('features', [])</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._run_node.is_local():</span><br><span style="color: hsl(120, 100%, 40%);">+ # use adb locally instead of ssh</span><br><span style="color: hsl(120, 100%, 40%);">+ adb_cmd_pref = ['adb', '-s', self.ue_serial, 'exec-out', 'su', '-c']</span><br><span style="color: hsl(120, 100%, 40%);">+ popen_args = adb_cmd_pref + list(popen_args)</span><br><span style="color: hsl(120, 100%, 40%);">+ proc = process.run_local_sync(self.run_dir, name, popen_args)</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ proc = self.rem_host.RemoteProcess(name, popen_args, env={})</span><br><span style="color: hsl(120, 100%, 40%);">+ proc.launch_sync()</span><br><span style="color: hsl(120, 100%, 40%);">+ return proc</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def verify_metric(self, value, operation='avg', metric='dl_brate', criterion='gt', window=1):</span><br><span style="color: hsl(120, 100%, 40%);">+ self.stop()</span><br><span style="color: hsl(120, 100%, 40%);">+ if self.have_metrics_file:</span><br><span style="color: hsl(120, 100%, 40%);">+ metrics = srsUEMetrics(self.metrics_file)</span><br><span style="color: hsl(120, 100%, 40%);">+ return metrics.verify(value, operation, metric, criterion, window)</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ raise log.Error("Metrics file not available")</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 None # no netns needed</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def set_airplane_mode(self, apm_state):</span><br><span style="color: hsl(120, 100%, 40%);">+ self.log("Setting airplane mode: " + str(apm_state))</span><br><span style="color: hsl(120, 100%, 40%);">+ popen_args = ['settings', 'put', 'global', 'airplane_mode_on', str(int(apm_state)),</span><br><span style="color: hsl(120, 100%, 40%);">+ '&&', 'su', '-c', '\"', 'am', 'broadcast', '-a', 'android.intent.action.AIRPLANE_MODE', '\"']</span><br><span style="color: hsl(120, 100%, 40%);">+ self.run_netns_wait("set-airplane-mode", popen_args)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def get_carrier_id(self, carrier_name):</span><br><span style="color: hsl(120, 100%, 40%);">+ qry_carrier_cmd = "content query --uri \"content://telephony/carriers\" "</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ proc = self.run_netns_wait("set-apn", [qry_carrier_cmd])</span><br><span style="color: hsl(120, 100%, 40%);">+ available_carriers = proc.get_stdout().split("\n")</span><br><span style="color: hsl(120, 100%, 40%);">+ carr_id = -1</span><br><span style="color: hsl(120, 100%, 40%);">+ for carr in available_carriers:</span><br><span style="color: hsl(120, 100%, 40%);">+ if 'name=' + carrier_name in carr: # found carrier</span><br><span style="color: hsl(120, 100%, 40%);">+ carr_id = re.findall(r'_id=(\S+),', carr)[0]</span><br><span style="color: hsl(120, 100%, 40%);">+ break</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return carr_id</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def set_new_carrier(self, apn_parameter, carr_id):</span><br><span style="color: hsl(120, 100%, 40%);">+ # check if carrier was found, delete it if exists</span><br><span style="color: hsl(120, 100%, 40%);">+ if carr_id != -1:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.delete_apn(apn_parameter["carrier"])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # build command to add/update carrier</span><br><span style="color: hsl(120, 100%, 40%);">+ set_carrier_cmd = "content insert --uri content://telephony/carriers" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + " --bind name:s:\"" + apn_parameter["carrier"] + "\"" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + " --bind numeric:s:\"" + apn_parameter["mcc"] + apn_parameter["mnc"] + "\"" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + " --bind mcc:s:\"" + apn_parameter["mcc"] + "\"" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + " --bind mnc:s:\"" + apn_parameter["mnc"] + "\""\</span><br><span style="color: hsl(120, 100%, 40%);">+ + " --bind apn:s:\"" + apn_parameter["apn"] + "\"" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + " --bind user:s:\"" + apn_parameter["user"] + "\"" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + " --bind password:s:\"" + apn_parameter["password"] + "\"" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + " --bind mmsc:s:\"" + apn_parameter["mmsc"] + "\"" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + " --bind mmsport:s:\"" + apn_parameter["mmsport"] + "\"" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + " --bind mmsproxy:s:\"" + apn_parameter["mmsproxy"] + "\"" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + " --bind authtype:s:\"" + apn_parameter["auth"] + "\"" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + " --bind type:s:\"" + apn_parameter["type"] + "\"" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + " --bind protocol:s:\"" + apn_parameter["protocol"] + "\"" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + " --bind mvno_type:s:\"" + apn_parameter["mvnotype"] + "\"" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + " --bind mvno_match_data:s:\"" + apn_parameter["mvnoval"] + "\"" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + " --bind sub_id:s:\"" + apn_parameter["groupid"] + "\""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ self.run_netns_wait("set-apn", [set_carrier_cmd])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # return carrier ID</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.get_carrier_id(apn_parameter["carrier"])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def set_preferred_apn(self, carr_id):</span><br><span style="color: hsl(120, 100%, 40%);">+ if carr_id != -1:</span><br><span style="color: hsl(120, 100%, 40%);">+ set_apn_cmd = "content insert --uri content://telephony/carriers/preferapn --bind apn_id:s:\"" + str(carr_id) + "\""</span><br><span style="color: hsl(120, 100%, 40%);">+ self.run_netns_wait("set-apn", [set_apn_cmd])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def set_apn(self, apn_param, sel_apn):</span><br><span style="color: hsl(120, 100%, 40%);">+ # search for carrier in APN database</span><br><span style="color: hsl(120, 100%, 40%);">+ carrier_id = self.get_carrier_id(apn_param["carrier"])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # add/update carrier</span><br><span style="color: hsl(120, 100%, 40%);">+ carrier_id = self.set_new_carrier(apn_param, carrier_id)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # select as preferred APN</span><br><span style="color: hsl(120, 100%, 40%);">+ if sel_apn:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.set_preferred_apn(carrier_id)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def select_apn(self, carr_name):</span><br><span style="color: hsl(120, 100%, 40%);">+ # search for carrier_id</span><br><span style="color: hsl(120, 100%, 40%);">+ carr_id = self.get_carrier_id(carr_name)</span><br><span style="color: hsl(120, 100%, 40%);">+ if carr_id == 0:</span><br><span style="color: hsl(120, 100%, 40%);">+ return False</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # select carrier by id</span><br><span style="color: hsl(120, 100%, 40%);">+ sel_apn_cmd = "content update --uri content://telephony/carriers/preferapn --bind apn_id:s:\"" + str(carr_id) + "\""</span><br><span style="color: hsl(120, 100%, 40%);">+ self.run_netns_wait("set-apn", [sel_apn_cmd])</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 delete_apn(self, carr_name):</span><br><span style="color: hsl(120, 100%, 40%);">+ set_apn_cmd = "content delete --uri content://telephony/carriers --where \'name=\"" + str(carr_name) + "\" \'"</span><br><span style="color: hsl(120, 100%, 40%);">+ self.run_netns_wait("set-apn", [set_apn_cmd])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def is_emm_connected(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ time.sleep(2)</span><br><span style="color: hsl(120, 100%, 40%);">+ proc = self.run_netns_wait("emm-conn-chk", ['getprop', '\"gsm.network.type\"'])</span><br><span style="color: hsl(120, 100%, 40%);">+ return 'LTE' in proc.get_stdout()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def save_metrics(self, brate_rx_l, brate_tx_l):</span><br><span style="color: hsl(120, 100%, 40%);">+ if len(brate_rx_l) < 2 or len(brate_tx_l) < 2:</span><br><span style="color: hsl(120, 100%, 40%);">+ raise log.Error("Insufficient data available to write metrics file")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # cut of elements if lists don't have the same length</span><br><span style="color: hsl(120, 100%, 40%);">+ if len(brate_rx_l) > len(brate_tx_l):</span><br><span style="color: hsl(120, 100%, 40%);">+ brate_rx_l = brate_rx_l[:len(brate_tx_l) - len(brate_rx_l)]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if len(brate_rx_l) < len(brate_tx_l):</span><br><span style="color: hsl(120, 100%, 40%);">+ brate_tx_l = brate_tx_l[:len(brate_rx_l) - len(brate_tx_l)]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # get start value</span><br><span style="color: hsl(120, 100%, 40%);">+ brate_rx_last = int(brate_rx_l[0])</span><br><span style="color: hsl(120, 100%, 40%);">+ brate_tx_last = int(brate_tx_l[0])</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ with open(self.metrics_file, "w") as ue_metrics_fh:</span><br><span style="color: hsl(120, 100%, 40%);">+ ue_metrics_fh.write("time;cc;earfcn;pci;rsrp;pl;cfo;pci_neigh;rsrp_neigh;cfo_neigh;"</span><br><span style="color: hsl(120, 100%, 40%);">+ + "dl_mcs;dl_snr;dl_turbo;dl_brate;dl_bler;"</span><br><span style="color: hsl(120, 100%, 40%);">+ + "ul_ta;ul_mcs;ul_buff;ul_brate;ul_bler;rf_o;rf_u;rf_l;"</span><br><span style="color: hsl(120, 100%, 40%);">+ + "is_attached\n")</span><br><span style="color: hsl(120, 100%, 40%);">+ for i in range(1, len(brate_rx_l)):</span><br><span style="color: hsl(120, 100%, 40%);">+ time = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ cc = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ earfcn = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ pci = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ rsrp = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ pl = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ cfo = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ pci_neigh = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ rsrp_neigh = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ cfo_neigh = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_mcs = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_snr = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_turbo = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_brate = str((int(brate_rx_l[i]) - brate_rx_last) * 8)</span><br><span style="color: hsl(120, 100%, 40%);">+ brate_rx_last = int(brate_rx_l[i])</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_bler = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ ul_ta = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ ul_mcs = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ ul_buff = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ ul_brate = str((int(brate_tx_l[i]) - brate_tx_last) * 8)</span><br><span style="color: hsl(120, 100%, 40%);">+ brate_tx_last = int(brate_tx_l[i])</span><br><span style="color: hsl(120, 100%, 40%);">+ ul_bler = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ rf_o = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ rf_u = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ rf_l = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+ is_attached = "0"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ line = time + ";" + cc + ";" + earfcn + ";" + pci + ";" + rsrp + ";" + pl + ";" + cfo + ";" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + pci_neigh + ";" + rsrp_neigh + ";" + cfo_neigh + ";" + dl_mcs + ";" + dl_snr + ";" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + dl_turbo + ";" + dl_brate + ";" + dl_bler + ";" + ul_ta + ";" + ul_mcs + ";" + ul_buff + ";" \</span><br><span style="color: hsl(120, 100%, 40%);">+ + ul_brate + ";" + ul_bler + ";" + rf_o + ";" + rf_u + ";" + rf_l + ";" + is_attached</span><br><span style="color: hsl(120, 100%, 40%);">+ ue_metrics_fh.write(line + "\n")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ self.have_metrics_file = True</span><br><span>diff --git a/src/osmo_gsm_tester/obj/run_node.py b/src/osmo_gsm_tester/obj/run_node.py</span><br><span>index 6a030ac..c907944 100644</span><br><span>--- a/src/osmo_gsm_tester/obj/run_node.py</span><br><span>+++ b/src/osmo_gsm_tester/obj/run_node.py</span><br><span>@@ -30,13 +30,14 @@</span><br><span> T_LOCAL = 'local'</span><br><span> T_REM_SSH = 'ssh'</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self, type=None, run_addr=None, ssh_user=None, ssh_addr=None, run_label=None):</span><br><span style="color: hsl(120, 100%, 40%);">+ def __init__(self, type=None, run_addr=None, ssh_user=None, ssh_addr=None, run_label=None, remote_port=None):</span><br><span> super().__init__(log.C_RUN, 'runnode')</span><br><span> self._type = type</span><br><span> self._run_addr = run_addr</span><br><span> self._ssh_user = ssh_user</span><br><span> self._ssh_addr = ssh_addr</span><br><span> self._run_label = run_label</span><br><span style="color: hsl(120, 100%, 40%);">+ self._remote_port = remote_port</span><br><span> if not self._type:</span><br><span> raise log.Error('run_type not set')</span><br><span> if not self._run_addr:</span><br><span>@@ -55,7 +56,7 @@</span><br><span> def from_conf(cls, conf):</span><br><span> return cls(conf.get('run_type', None), conf.get('run_addr', None),</span><br><span> conf.get('ssh_user', None), conf.get('ssh_addr', None),</span><br><span style="color: hsl(0, 100%, 40%);">- conf.get('run_label', None))</span><br><span style="color: hsl(120, 100%, 40%);">+ conf.get('run_label', None), conf.get('remote_port', None))</span><br><span> </span><br><span> @classmethod</span><br><span> def schema(cls):</span><br><span>@@ -65,6 +66,7 @@</span><br><span> 'ssh_user': schema.STR,</span><br><span> 'ssh_addr': schema.IPV4,</span><br><span> 'run_label': schema.STR,</span><br><span style="color: hsl(120, 100%, 40%);">+ 'remote_port': schema.STR,</span><br><span> }</span><br><span> return resource_schema</span><br><span> </span><br><span>@@ -89,4 +91,7 @@</span><br><span> def run_label(self):</span><br><span> return self._run_label</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ def ssh_port(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ return self._remote_port</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> # vim: expandtab tabstop=4 shiftwidth=4</span><br><span>diff --git a/sysmocom/default-suites.conf b/sysmocom/default-suites.conf</span><br><span>index b32d7b1..4c196b4 100644</span><br><span>--- a/sysmocom/default-suites.conf</span><br><span>+++ b/sysmocom/default-suites.conf</span><br><span>@@ -172,3 +172,4 @@</span><br><span> - encryption</span><br><span> </span><br><span> - 4g:srsenb-rftype@zmq+srsue-rftype@zmq</span><br><span style="color: hsl(120, 100%, 40%);">+- 4g:androidue@mi5g+srsenb-rftype@uhd+mod-enb-nprb@25+mod-enb-txmode@1</span><br><span>diff --git a/sysmocom/scenarios/androidue@.conf b/sysmocom/scenarios/androidue@.conf</span><br><span>new file mode 100644</span><br><span>index 0000000..a129c0e</span><br><span>--- /dev/null</span><br><span>+++ b/sysmocom/scenarios/androidue@.conf</span><br><span>@@ -0,0 +1,3 @@</span><br><span style="color: hsl(120, 100%, 40%);">+resources:</span><br><span style="color: hsl(120, 100%, 40%);">+ modem:</span><br><span style="color: hsl(120, 100%, 40%);">+ - label: ${param1}</span><br><span>diff --git a/sysmocom/suites/4g/iperf3_dl.py b/sysmocom/suites/4g/iperf3_dl.py</span><br><span>index bf5b1f0..ed137bd 100755</span><br><span>--- a/sysmocom/suites/4g/iperf3_dl.py</span><br><span>+++ b/sysmocom/suites/4g/iperf3_dl.py</span><br><span>@@ -23,7 +23,7 @@</span><br><span> max_rate = enb.ue_max_rate(downlink=True, num_carriers=ue.num_carriers)</span><br><span> </span><br><span> iperf3srv.start()</span><br><span style="color: hsl(0, 100%, 40%);">-proc = iperf3cli.prepare_test_proc(iperf3cli.DIR_DL, ue.netns(), bitrate=max_rate)</span><br><span style="color: hsl(120, 100%, 40%);">+proc = iperf3cli.prepare_test_proc(iperf3cli.DIR_DL, ue.netns(), bitrate=max_rate, ue=ue)</span><br><span> </span><br><span> print('waiting for UE to attach...')</span><br><span> wait(ue.is_registered)</span><br><span>diff --git a/sysmocom/suites/4g/iperf3_ul.py b/sysmocom/suites/4g/iperf3_ul.py</span><br><span>index 6c0d25d..6cc9f21 100755</span><br><span>--- a/sysmocom/suites/4g/iperf3_ul.py</span><br><span>+++ b/sysmocom/suites/4g/iperf3_ul.py</span><br><span>@@ -23,7 +23,7 @@</span><br><span> max_rate = enb.ue_max_rate(downlink=False, num_carriers=ue.num_carriers)</span><br><span> </span><br><span> iperf3srv.start()</span><br><span style="color: hsl(0, 100%, 40%);">-proc = iperf3cli.prepare_test_proc(iperf3cli.DIR_UL, ue.netns(), bitrate=max_rate)</span><br><span style="color: hsl(120, 100%, 40%);">+proc = iperf3cli.prepare_test_proc(iperf3cli.DIR_UL, ue.netns(), bitrate=max_rate, ue=ue)</span><br><span> </span><br><span> print('waiting for UE to attach...')</span><br><span> wait(ue.is_registered)</span><br><span>diff --git a/utils/bin/osmo-gsm-tester_androidue_conn_chk.sh b/utils/bin/osmo-gsm-tester_androidue_conn_chk.sh</span><br><span>new file mode 100644</span><br><span>index 0000000..8e126cd</span><br><span>--- /dev/null</span><br><span>+++ b/utils/bin/osmo-gsm-tester_androidue_conn_chk.sh</span><br><span>@@ -0,0 +1,9 @@</span><br><span style="color: hsl(120, 100%, 40%);">+# osmo-gsm-tester_androidue_conn_chk.sh $serial</span><br><span style="color: hsl(120, 100%, 40%);">+while true; do</span><br><span style="color: hsl(120, 100%, 40%);">+ sudo adb -s "$1" shell getprop "gsm.network.type";</span><br><span style="color: hsl(120, 100%, 40%);">+ sleep 1;</span><br><span style="color: hsl(120, 100%, 40%);">+done</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/utils/bin/osmo-gsm-tester_androidue_diag_parser.sh b/utils/bin/osmo-gsm-tester_androidue_diag_parser.sh</span><br><span>new file mode 100644</span><br><span>index 0000000..00a2f81</span><br><span>--- /dev/null</span><br><span>+++ b/utils/bin/osmo-gsm-tester_androidue_diag_parser.sh</span><br><span>@@ -0,0 +1,10 @@</span><br><span style="color: hsl(120, 100%, 40%);">+# format ./osmo-gsm-tester_androidue_diag_parser.sh $serial $run_dir $pcap_path</span><br><span style="color: hsl(120, 100%, 40%);">+while true; do</span><br><span style="color: hsl(120, 100%, 40%);">+ echo "Pulling new qmdl file...";</span><br><span style="color: hsl(120, 100%, 40%);">+ sudo adb -s "$1" pull /data/local/tmp/diag_logs "$2" > /dev/null;</span><br><span style="color: hsl(120, 100%, 40%);">+ wait $!;</span><br><span style="color: hsl(120, 100%, 40%);">+ QMDL_FN=$(find "$2" -maxdepth 2 -type f -name "*.qmdl");</span><br><span style="color: hsl(120, 100%, 40%);">+ wait $!;</span><br><span style="color: hsl(120, 100%, 40%);">+ sudo scat -t qc --event -d "$QMDL_FN" -F "$3";</span><br><span style="color: hsl(120, 100%, 40%);">+ wait $!;</span><br><span style="color: hsl(120, 100%, 40%);">+done</span><br><span>\ No newline at end of file</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-gsm-tester/+/21217">change 21217</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/+/21217"/><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: Iab37a0de59d6643d21bced34ddca06ff40fa62df </div>
<div style="display:none"> Gerrit-Change-Number: 21217 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: srs_andre <andre@softwareradiosystems.com> </div>
<div style="display:none"> Gerrit-Reviewer: Nils <nils.fuerste@softwareradiosystems.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>