diff --git a/example/resources.conf.prod b/example/resources.conf.prod index 22134e73..b12a7bc9 100644 --- a/example/resources.conf.prod +++ b/example/resources.conf.prod @@ -122,14 +122,14 @@ modem: ki: 'EBAB63D06C3F546A16C977CB40E57C68' auth_algo: 'comp128v1' ciphers: [a5_0, a5_1] - features: ['sms', 'voice', 'ussd', 'gprs', 'sim'] + features: ['sms', 'voice', 'ussd', 'sim'] - label: sierra_2nd path: '/sys/devices/pci0000:00/0000:00:12.2/usb1/1-5/1-5.4/1-5.4.1/1-5.4.1.3' ki: 'EBD2B5F6CF3374106D0A66C11F922001' auth_algo: 'comp128v1' ciphers: [a5_0, a5_1] - features: ['sms', 'voice', 'ussd', 'gprs', 'sim'] + features: ['sms', 'voice', 'ussd', 'sim'] - label: ec20 path: '/sys/devices/pci0000:00/0000:00:12.2/usb1/1-5/1-5.4/1-5.4.1/1-5.4.1.6' @@ -143,7 +143,7 @@ modem: ki: '5752B3F43277C35D2D1D957007DF74E2' auth_algo: 'comp128v1' ciphers: [a5_0, a5_1] - features: ['gprs', 'sim'] + features: ['sim'] osmocon_phone: - serial_device: '/dev/serial/by-id/usb-Silicon_Labs_CP2104_USB_to_UART_Bridge_Controller_00897B41-if00-port0' diff --git a/example/resources.conf.rnd b/example/resources.conf.rnd index dbdf3cce..63650e18 100644 --- a/example/resources.conf.rnd +++ b/example/resources.conf.rnd @@ -72,14 +72,14 @@ modem: ki: '80A37E6FDEA931EAC92FFA5F671EFEAD' auth_algo: 'comp128v1' ciphers: [a5_0, a5_1] - features: ['sms', 'voice', 'ussd', 'gprs', 'sim'] + features: ['sms', 'voice', 'ussd', 'sim'] - label: sierra_2nd path: '/sys/devices/pci0000:00/0000:00:12.2/usb1/1-1/1-1.3' ki: '00969E283349D354A8239E877F2E0866' auth_algo: 'comp128v1' ciphers: [a5_0, a5_1] - features: ['sms', 'voice', 'ussd', 'gprs', 'sim'] + features: ['sms', 'voice', 'ussd', 'sim'] - label: ec20 path: '/sys/devices/pci0000:00/0000:00:12.2/usb1/1-1/1-1.6' @@ -93,7 +93,7 @@ modem: ki: '2F70DCA43C45ACB97E947FDD0C7CA30A' auth_algo: 'comp128v1' ciphers: [a5_0, a5_1] - features: ['gprs', 'sim'] + features: ['sim'] osmocon_phone: - serial_device: '/dev/serial/by-id/usb-Silicon_Labs_CP2104_USB_to_UART_Bridge_Controller_0089279D-if00-port0' diff --git a/src/osmo_gsm_tester/modem.py b/src/osmo_gsm_tester/modem.py index 21b208c8..d35933a0 100644 --- a/src/osmo_gsm_tester/modem.py +++ b/src/osmo_gsm_tester/modem.py @@ -17,10 +17,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -from . import log, util, sms +from . import log, util, sms, process from .event_loop import MainLoop from pydbus import SystemBus, Variant +import os # Required for Gio.Cancellable. # See https://lazka.github.io/pgi-docs/Gio-2.0/classes/Cancellable.html#Gio.Cancellable @@ -323,15 +324,17 @@ class Modem(log.Origin): CTX_PROT_IPv6 = 'ipv6' CTX_PROT_IPv46 = 'dual' - def __init__(self, conf): + def __init__(self, suite_run, conf): + self.suite_run = suite_run self.conf = conf self.syspath = conf.get('path') self.dbuspath = get_dbuspath_from_syspath(self.syspath) super().__init__(log.C_TST, self.dbuspath) - self.dbg('creating from syspath %s', self.syspath) + self.dbg('creating from syspath %s' % self.syspath) self.msisdn = None self._ki = None self._imsi = None + self.run_dir = util.Dir(self.suite_run.get_test_run_dir().new_dir(self.name().strip('/'))) self.sms_received_list = [] self.dbus = ModemDbusInteraction(self.dbuspath) self.register_attempts = 0 @@ -358,6 +361,9 @@ class Modem(log.Origin): self.dbus.cleanup() self.dbus = None + def netns(self): + return os.path.basename(self.syspath.rstrip('/')) + def properties(self, *args, **kwargs): '''Return a dict of properties on this modem. For the actual arguments, see ModemDbusInteraction.properties(), which this function calls. The @@ -627,6 +633,23 @@ class Modem(log.Origin): connmgr.RemoveContext(ctx_id) self.log('context deactivated', path=ctx_id) + def run_netns_wait(self, name, popen_args): + proc = process.NetNSProcess(name, self.run_dir.new_dir(name), self.netns(), popen_args, + env={}) + process.run_proc_sync(proc) + + def setup_context_data_plane(self, ctx_id): + self.dbg('setup_context_data', path=ctx_id) + ctx = systembus_get(ctx_id) + ctx_settings = ctx.GetProperties().get('Settings', None) + if not ctx_settings: + raise log.Error('%s no Settings found! No way to get iface!' % ctx_id) + iface = ctx_settings.get('Interface', None) + if not iface: + raise log.Error('%s Settings contains no iface! %r' % (ctx_id, repr(ctx_settings))) + self.run_netns_wait('ifup', ('ip', 'link', 'set', 'dev', iface, 'up')) + self.run_netns_wait('dhcp', ('udhcpc', '-q', '-i', iface)) + def sms_send(self, to_msisdn_or_modem, *tokens): if isinstance(to_msisdn_or_modem, Modem): to_msisdn = to_msisdn_or_modem.msisdn diff --git a/src/osmo_gsm_tester/process.py b/src/osmo_gsm_tester/process.py index fb5c6f6b..a845f7fa 100644 --- a/src/osmo_gsm_tester/process.py +++ b/src/osmo_gsm_tester/process.py @@ -100,6 +100,9 @@ class Process(log.Origin): time.sleep(wait_step) return False + def send_signal(self, sig): + os.kill(self.process_obj.pid, sig) + def terminate(self): if self.process_obj is None: return @@ -109,21 +112,21 @@ class Process(log.Origin): while True: # first try SIGINT to allow stdout+stderr flushing self.log('Terminating (SIGINT)') - os.kill(self.process_obj.pid, signal.SIGINT) + self.send_signal(signal.SIGINT) self.killed = signal.SIGINT if self._poll_termination(): break # SIGTERM maybe? self.log('Terminating (SIGTERM)') - self.process_obj.terminate() + self.send_signal(signal.SIGTERM) self.killed = signal.SIGTERM if self._poll_termination(): break # out of patience self.log('Terminating (SIGKILL)') - self.process_obj.kill() + self.send_signal(signal.SIGKILL) self.killed = signal.SIGKILL break; @@ -236,6 +239,22 @@ class RemoteProcess(Process): ' '.join(self.popen_args))] self.dbg(self.popen_args, dir=self.run_dir, conf=self.popen_kwargs) +class NetNSProcess(Process): + NETNS_EXEC_BIN = 'osmo-gsm-tester_netns_exec.sh' + def __init__(self, name, run_dir, netns, popen_args, **popen_kwargs): + super().__init__(name, run_dir, popen_args, **popen_kwargs) + self.netns = netns + + self.popen_args = ['sudo', self.NETNS_EXEC_BIN, self.netns] + list(popen_args) + self.dbg(self.popen_args, dir=self.run_dir, conf=self.popen_kwargs) + + # HACK: Since we run under sudo, only way to kill root-owned process is to kill as root... + # This function is overwritten from Process. + def send_signal(self, sig): + kill_cmd = ('kill', '-%d' % int(sig), str(self.process_obj.pid)) + run_local_netns_sync(self.run_dir, self.name()+"-kill", self.netns, kill_cmd) + + def run_proc_sync(proc): try: proc.launch() @@ -252,6 +271,11 @@ def run_local_sync(run_dir, name, popen_args): proc = Process(name, run_dir, popen_args) run_proc_sync(proc) +def run_local_netns_sync(run_dir, name, netns, popen_args): + run_dir =run_dir.new_dir(name) + proc = NetNSProcess(name, run_dir, netns, popen_args) + run_proc_sync(proc) + def run_remote_sync(run_dir, remote_user, remote_addr, name, popen_args, remote_cwd=None): run_dir = run_dir.new_dir(name) proc = RemoteProcess(name, run_dir, remote_user, remote_addr, remote_cwd, popen_args) diff --git a/src/osmo_gsm_tester/suite.py b/src/osmo_gsm_tester/suite.py index 22a47a23..67ddefdc 100644 --- a/src/osmo_gsm_tester/suite.py +++ b/src/osmo_gsm_tester/suite.py @@ -328,7 +328,7 @@ class SuiteRun(log.Origin): def modem(self, specifics=None): conf = self.reserved_resources.get(resource.R_MODEM, specifics=specifics) self.dbg('create Modem object', conf=conf) - ms = modem.Modem(conf) + ms = modem.Modem(self, conf) self.register_for_cleanup(ms) return ms diff --git a/suites/gprs/ping.py b/suites/gprs/ping.py index 1647445d..9186fe62 100755 --- a/suites/gprs/ping.py +++ b/suites/gprs/ping.py @@ -48,8 +48,10 @@ wait(ms.is_attached) # We need to use inet46 since ofono qmi only uses ipv4v6 eua (OS#2713) ctx_id_v4 = ms.activate_context(apn='inet46', protocol=ms.CTX_PROT_IPv4) -sleep(5) -# TODO: send ping to server or open TCP conn with a socket in python +print("Setting up data plan for %r" % repr(ctx_id_v4)) +ms.setup_context_data_plane(ctx_id_v4) +print("Running 10 ping requests for %r" % repr(ctx_id_v4)) +ms.run_netns_wait('ping', ('ping', '-c', '10', ggsn.addr())) ms.deactivate_context(ctx_id_v4) # We need to use inet46 since ofono qmi only uses ipv4v6 eua (OS#2713) diff --git a/utils/osmo-gsm-tester_netns_exec.sh b/utils/osmo-gsm-tester_netns_exec.sh new file mode 100755 index 00000000..336b746e --- /dev/null +++ b/utils/osmo-gsm-tester_netns_exec.sh @@ -0,0 +1,5 @@ +#!/bin/bash +netns="$1" +shift +#TODO: Later on I may want to call myself with specific ENV and calling sudo in order to run inside the netns but with dropped privileges +ip netns exec $netns "$@"