osmo-gsm-tester/src/osmo_gsm_tester/obj/android_bitrate_monitor.py

119 lines
5.0 KiB
Python
Raw Normal View History

Introduce Android UEs as new modems To expand the test capacities we would like to introduce Android UEs as new modems. Currently the following tests are supported: - Ping - iPerf3 DL/UL - RRC Mobile MT Ping In the following is a small description. Prerequisites: - Android UE - Rooted (Ping, iPerf, RRC Idle MT Ping) - Qualcomm baseband with working diag_mdlog (RRC Idle MT Ping) - iPerf3 - Dropbear - OGT Slave Unit - Android SDK Platform-Tools (https://developer.android.com/studio/releases/platform-tools#downloads) - Pycrate (https://github.com/P1sec/pycrate) - SCAT clone https://github.com/bedrankara/scat/ & install dependencies checkout branch ogt symlink scat (ln -s ~/scat/scat.py /usr/local/bin/scat) Infrastructure explaination: The Android UEs are connected to the OGT Units via USB. We activate tethering and set up a SSH server (with Dropbear). We chose tethering over WiFi to have a more stable route for the ssh connection. We forward incoming connections to the OGT unit hosting the Android UE(s) on specific ports to the UEs via iptables. This enables OGT to issue commands directly to the UEs. In case of local execution we use ADB to issue commands to the AndroidUE. The set up was tested with 5 Android UEs connected in parallel but it should be scalable to the number of available IPs in the respective subnet. Furthermore, we need to cross compile Dropbear and iPerf3 to use them on the UEs. These tools have to be added to the $PATH variable of the UEs. Examplary set up: In this example we have two separate OGT units (master and slave) and two Android UEs that are connected to the slave unit. An illustration may be found here: https://ibb.co/6BXSP2C On UE 1: ip address add 192.168.42.130/24 dev rndis0 ip route add 192.168.42.0/24 dev rndis0 table local_network dropbearmulti dropbear -F -E -p 130 -R -T /data/local/tmp/authorized_keys -U 0 -G 0 -N root -A On UE 2: ip address add 192.168.42.131/24 dev rndis0 ip route add 192.168.42.0/24 dev rndis0 table local_network dropbearmulti dropbear -F -E -p 131 -R -T /data/local/tmp/authorized_keys -U 0 -G 0 -N root -A On OGT slave unit: sudo ip link add name ogt type bridge sudo ip l set eth0 master ogt sudo ip l set enp0s20f0u1 master ogt sudo ip l set enp0s20f0u2 master ogt sudo ip a a 192.168.42.1/24 dev ogt sudo ip link set ogt up Now we have to manually connect to every UE from OGT Master to set up SSH keys and verify that the setup works. Therefore, use: ssh -p [UE-PORT] root@[OGT SLAVE UNIT's IP] Finally, to finish the setup procedure create the remote_run_dir for Android UEs on the slave unit like following: mkdir /osmo-gsm-tester-androidue chown jenkins /osmo-gsm-tester-androidue Example for modem in resource.conf: - label: mi5g type: androidue imsi: '901700000034757' ki: '85E9E9A947B9ACBB966ED7113C7E1B8A' opc: '3E1C73A29B9C293DC5A763E42C061F15' apn: apn: 'srsapn' mcc: '901' mnc: '70' select: 'True' auth_algo: 'milenage' features: ['4g', 'dl_qam256', 'qc_diag'] run_node: run_type: ssh run_addr: 100.113.1.170 ssh_user: jenkins ssh_addr: 100.113.1.170 ue_ssh_port: 130 adb_serial_id: '8d3c79a7' scat_parser: run_type: local run_addr: 127.0.0.1 adb_serial_id: '8d3c79a7' Example for default-suites.conf: - 4g:ms-label@mi5g+srsenb-rftype@uhd+mod-enb-nprb@25+mod-enb-txmode@1 Change-Id: I79a5d803e869a868d4dac5e0d4c2feb38038dc5c
2020-11-23 13:45:15 +00:00
# osmo_gsm_tester: specifics for monitoring the bit rate of an AndroidUE modem
#
# Copyright (C) 2020 by Software Radio Systems Limited
#
# Author: Nils Fürste <nils.fuerste@softwareradiosystems.com>
# Author: Bedran Karakoc <bedran.karakoc@softwareradiosystems.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from ..core import log
from .android_host import AndroidHost
class BitRateMonitor(AndroidHost):
##############
# PROTECTED
##############
def __init__(self, testenv, run_dir, run_node, rem_host, data_interface):
super().__init__('brate_monitor_%s' % run_node.run_addr())
self.testenv = testenv
self.rem_host = rem_host
self._run_node = run_node
self.run_dir = run_dir
self.data_interface = data_interface
self.rx_monitor_proc = None
self.tx_monitor_proc = None
########################
# PUBLIC - INTERNAL API
########################
def start(self):
# start bit rate monitoring on Android UE
popen_args_rx_mon = ['while true; do cat /sys/class/net/' + self.data_interface + '/statistics/rx_bytes;',
'sleep 1;', 'done']
popen_args_tx_mon = ['while true; do cat /sys/class/net/' + self.data_interface + '/statistics/tx_bytes;',
'sleep 1;', 'done']
self.rx_monitor_proc = self.run_androidue_cmd('start-rx-monitor', popen_args_rx_mon)
self.testenv.remember_to_stop(self.rx_monitor_proc)
self.rx_monitor_proc.launch()
self.tx_monitor_proc = self.run_androidue_cmd('start-tx-monitor', popen_args_tx_mon)
self.testenv.remember_to_stop(self.tx_monitor_proc)
self.tx_monitor_proc.launch()
def stop(self):
self.testenv.stop_process(self.rx_monitor_proc)
self.testenv.stop_process(self.tx_monitor_proc)
def save_metrics(self, metrics_file):
brate_rx_raw = self.rx_monitor_proc.get_stdout().split('\n')
brate_tx_raw = self.tx_monitor_proc.get_stdout().split('\n')
brate_rx_raw.remove('')
brate_tx_raw.remove('')
brate_rx_l = brate_rx_raw[1:]
brate_tx_l = brate_tx_raw[1:]
if len(brate_rx_l) < 2 or len(brate_tx_l) < 2:
raise log.Error('Insufficient data available to write metrics file')
# cut of elements if lists don't have the same length
if len(brate_rx_l) > len(brate_tx_l):
brate_rx_l = brate_rx_l[:len(brate_tx_l) - len(brate_rx_l)]
if len(brate_rx_l) < len(brate_tx_l):
brate_tx_l = brate_tx_l[:len(brate_rx_l) - len(brate_tx_l)]
# get start value
brate_rx_last = int(brate_rx_l[0])
brate_tx_last = int(brate_tx_l[0])
with open(metrics_file, 'w') as ue_metrics_fh:
ue_metrics_fh.write('time;cc;earfcn;pci;rsrp;pl;cfo;pci_neigh;rsrp_neigh;cfo_neigh;'
+ 'dl_mcs;dl_snr;dl_turbo;dl_brate;dl_bler;'
+ 'ul_ta;ul_mcs;ul_buff;ul_brate;ul_bler;rf_o;rf_u;rf_l;'
+ 'is_attached\n')
for i in range(1, len(brate_rx_l)):
time = '0'
cc = '0'
earfcn = '0'
pci = '0'
rsrp = '0'
pl = '0'
cfo = '0'
pci_neigh = '0'
rsrp_neigh = '0'
cfo_neigh = '0'
dl_mcs = '0'
dl_snr = '0'
dl_turbo = '0'
dl_brate = str((int(brate_rx_l[i]) - brate_rx_last) * 8)
brate_rx_last = int(brate_rx_l[i])
dl_bler = '0'
ul_ta = '0'
ul_mcs = '0'
ul_buff = '0'
ul_brate = str((int(brate_tx_l[i]) - brate_tx_last) * 8)
brate_tx_last = int(brate_tx_l[i])
ul_bler = '0'
rf_o = '0'
rf_u = '0'
rf_l = '0'
is_attached = '0'
line = time + ';' + cc + ';' + earfcn + ';' + pci + ';' + rsrp + ';' + pl + ';' + cfo + ';' \
+ pci_neigh + ';' + rsrp_neigh + ';' + cfo_neigh + ';' + dl_mcs + ';' + dl_snr + ';' \
+ dl_turbo + ';' + dl_brate + ';' + dl_bler + ';' + ul_ta + ';' + ul_mcs + ';' + ul_buff + ';' \
+ ul_brate + ';' + ul_bler + ';' + rf_o + ';' + rf_u + ';' + rf_l + ';' + is_attached
ue_metrics_fh.write(line + '\n')