This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Pau Espin Pedrol gerrit-no-reply at lists.osmocom.orgHello Neels Hofmeyr, Jenkins Builder, I'd like you to reexamine a change. Please visit https://gerrit.osmocom.org/2779 to look at the new patch set (#5). ofono_client: Implement network registration during connect() Also add a new simple test to check network registration is working Change-Id: I8d9eb47eac1044550d3885adb55105c304b0c15c --- M src/osmo_gsm_tester/ofono_client.py M src/osmo_gsm_tester/osmo_msc.py M src/osmo_gsm_tester/osmo_nitb.py M suites/aoip_debug/interactive.py M suites/aoip_sms/mo_mt_sms.py M suites/debug/interactive.py A suites/netreg/register.py A suites/netreg/register_default.py A suites/netreg/suite.conf M suites/sms/mo_mt_sms.py 10 files changed, 217 insertions(+), 9 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-gsm-tester refs/changes/79/2779/5 diff --git a/src/osmo_gsm_tester/ofono_client.py b/src/osmo_gsm_tester/ofono_client.py index 7c27f08..9a23c36 100644 --- a/src/osmo_gsm_tester/ofono_client.py +++ b/src/osmo_gsm_tester/ofono_client.py @@ -22,6 +22,7 @@ from pydbus import SystemBus, Variant import time import pprint +import sys from gi.repository import GLib glib_main_loop = GLib.MainLoop() @@ -31,6 +32,12 @@ I_MODEM = 'org.ofono.Modem' I_NETREG = 'org.ofono.NetworkRegistration' I_SMS = 'org.ofono.MessageManager' + +# See https://github.com/intgr/ofono/blob/master/doc/network-api.txt#L78 +NETREG_ST_REGISTERED = 'registered' +NETREG_ST_ROAMING = 'roaming' + +NETREG_MAX_REGISTER_ATTEMPTS = 3 class DeferredHandling: defer_queue = [] @@ -47,6 +54,9 @@ while DeferredHandling.defer_queue: handler, args, kwargs = DeferredHandling.defer_queue.pop(0) handler(*args, **kwargs) + +def defer(handler, *args, **kwargs): + DeferredHandling.defer_queue.append((handler, args, kwargs)) def dbus_connect(dbus_iface, handler): '''This function shall be used instead of directly connecting DBus signals. @@ -72,6 +82,49 @@ def list_modems(): root = systembus_get('/') return sorted(root.GetModems()) + +def __async_result_handler(obj, result, user_data): + '''Generic callback dispatcher called from glib loop when an async method + call has returned. This callback is set up by method dbus_async_call.''' + (result_callback, error_callback, real_user_data) = user_data + try: + ret = obj.call_finish(result) + except Exception: + etype, e = sys.exc_info()[:2] + # return exception as value + if error_callback: + error_callback(obj, e, real_user_data) + else: + result_callback(obj, e, real_user_data) + return + + ret = ret.unpack() + # to be compatible with standard Python behaviour, unbox + # single-element tuples and return None for empty result tuples + if len(ret) == 1: + ret = ret[0] + elif len(ret) == 0: + ret = None + result_callback(obj, ret, real_user_data) + +def dbus_async_call(proxymethod, instance, *args, **kwargs): + '''pydbus doesn't support asynchronous methods. This method adds support for + it until pydbus implements it''' + argdiff = len(args) - len(proxymethod._inargs) + if argdiff < 0: + raise TypeError(proxymethod.__qualname__ + " missing {} required positional argument(s)".format(-argdiff)) + elif argdiff > 0: + raise TypeError(proxymethod.__qualname__ + " takes {} positional argument(s) but {} was/were given".format(len(proxymethod._inargs), len(args))) + + timeout = kwargs.get("timeout", 30) * 1000 + user_data = (kwargs['result_handler'], kwargs.get('error_handler'), kwargs.get('user_data')) + + ret = instance._bus.con.call( + instance._bus_name, instance._path, + proxymethod._iface_name, proxymethod.__name__, + GLib.Variant(proxymethod._sinargs, args), GLib.VariantType.new(proxymethod._soutargs), + 0, timeout, None, + __async_result_handler, user_data) class ModemDbusInteraction(log.Origin): '''Work around inconveniences specific to pydbus and ofono. @@ -255,8 +308,11 @@ self.path = conf.get('path') self.set_name(self.path) self.set_log_category(log.C_TST) + self.mnc = None + self.mcc = None self.sms_received_list = [] self.dbus = ModemDbusInteraction(self.path) + self.register_attempts = 0 self.dbus.required_signals = { I_SMS: ( ('IncomingMessage', self._on_incoming_message), ), I_NETREG: ( ('PropertyChanged', self._on_netreg_property_changed), ), @@ -323,9 +379,70 @@ def _on_netreg_property_changed(self, name, value): self.dbg('%r.PropertyChanged() -> %s=%s' % (I_NETREG, name, value)) - def connect(self, nitb): - 'set the modem up to connect to MCC+MNC from NITB config' - self.log('connect to', nitb) + def get_netreg_status(self): + try: + status = self.properties(I_NETREG).get('Status') + except KeyError: + status = None + return status + + def is_roaming(self): + status = self.get_netreg_status() + return status == NETREG_ST_ROAMING + + def is_connected(self): + status = self.get_netreg_status() + return status == NETREG_ST_REGISTERED or status == NETREG_ST_ROAMING + + def schedule_scan_register(self): + if self.register_attempts > NETREG_MAX_REGISTER_ATTEMPTS: + self.raise_exn('Failed to find Network Operator', mcc=self.mcc, mnc=self.mnc, attempt=self.register_attempts) + self.register_attempts += 1 + nr = self.dbus.interface(I_NETREG) + self.dbg('Scanning for operators...') + # Scan method can take several seconds, and we don't want to block + # waiting for that. Make it async and try to regsiter when the scan is + # finished. + dbus_async_call(nr.Scan, nr, timeout=30, result_handler=self.scan_result_cb, + error_handler=self.raise_exn_cb, user_data=None) + + def raise_exn_cb(self, obj, e, user_data): + self.raise_exn() + + def scan_result_cb(self, obj, result, user_data): + self.register(result) + + def register(self, ops): + nr = self.dbus.interface(I_NETREG) + if self.mcc is None or self.mnc is None: + if not self.is_connected(): + self.log('Registering with the default network...') + nr.Register() + else: + self.log('Already registered with the network') + return + self.dbg('ops: ', ops); + myop = None + for op in ops: + op_path, op_prop = op + if op_prop.get('MobileCountryCode') == self.mcc and op_prop.get('MobileNetworkCode') == self.mnc: + if op_prop.get('Status') == 'current': + self.log('Already registered with the network') + # return and not try to re-connect, otherwise dbus method returns a fail + return + myop = op_path + break + if myop is None: + self.dbg('Failed to find Network Operator', self.mcc, self.mnc, 'attempt', self.register_attempts) + self.schedule_scan_register() + return + dbus_op = systembus_get(myop) + self.log('Registering with operator', myop) + dbus_op.Register() + + def power_cycle(self): + 'Power the modem and put it online' + self.dbg('Powering on') if self.is_powered(): self.dbg('is powered') self.set_online(False) @@ -335,6 +452,16 @@ self.set_online() event_loop.wait(self, self.dbus.has_interface, I_NETREG, I_SMS, timeout=10) + def connect(self, mcc_mnc): + 'Connect to MCC+MNC from NITB config' + self.mcc, self.mnc = mcc_mnc + if (self.mcc is None and self.mnc is not None) or (self.mcc is not None and self.mnc is None): + self.raise_exn('Either none or both of the following values must be set:', mcc=self.mcc, mnc=self.mnc) + self.power_cycle() + self.log('connect to', self.mcc, self.mnc) + self.register_attempts = 0 + self.schedule_scan_register() + 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/osmo_msc.py b/src/osmo_gsm_tester/osmo_msc.py index ea539d6..78418cf 100644 --- a/src/osmo_gsm_tester/osmo_msc.py +++ b/src/osmo_gsm_tester/osmo_msc.py @@ -37,6 +37,7 @@ self.set_name('osmo-msc_%s' % ip_address.get('addr')) self.hlr = hlr self.mgcpgw = mgcpgw + self.config = None def start(self): self.log('Starting osmo-msc') @@ -72,6 +73,7 @@ config.overlay(values, self.suite_run.config()) config.overlay(values, dict(msc=dict(ip_address=self.ip_address))) config.overlay(values, self.mgcpgw.conf_for_msc()) + self.config = values self.dbg('MSC CONFIG:\n' + pprint.pformat(values)) @@ -83,6 +85,15 @@ def addr(self): return self.ip_address.get('addr') + def mcc(self): + return self.config['msc']['net']['mcc'] + + def mnc(self): + return self.config['msc']['net']['mnc'] + + def mcc_mnc(self): + return (self.mcc(), self.mnc()) + def subscriber_attached(self, *modems): return self.imsi_attached(*[m.imsi() for m in modems]) diff --git a/src/osmo_gsm_tester/osmo_nitb.py b/src/osmo_gsm_tester/osmo_nitb.py index 1bb1fcf..f77c83b 100644 --- a/src/osmo_gsm_tester/osmo_nitb.py +++ b/src/osmo_gsm_tester/osmo_nitb.py @@ -76,6 +76,7 @@ for bts in self.bts: bts_list.append(bts.conf_for_bsc()) config.overlay(values, dict(nitb=dict(net=dict(bts_list=bts_list)))) + self.config = values self.dbg('NITB CONFIG:\n' + pprint.pformat(values)) @@ -91,6 +92,15 @@ self.bts.append(bts) bts.set_bsc(self) + def mcc(self): + return self.config['nitb']['net']['mcc'] + + def mnc(self): + return self.config['nitb']['net']['mnc'] + + def mcc_mnc(self): + return (self.mcc(), self.mnc()) + def subscriber_add(self, modem, msisdn=None): if msisdn is None: msisdn = self.suite_run.resources_pool.next_msisdn(modem) diff --git a/suites/aoip_debug/interactive.py b/suites/aoip_debug/interactive.py index 4f56d5c..bac510c 100755 --- a/suites/aoip_debug/interactive.py +++ b/suites/aoip_debug/interactive.py @@ -17,7 +17,7 @@ for m in modems: hlr.subscriber_add(m) - m.connect(bsc) + m.connect(msc.mcc_mnc()) while True: cmd = prompt('Enter command: (q)uit (s)ms (g)et-registered (w)ait-registered') @@ -30,6 +30,8 @@ elif 'wait-registered'.startswith(cmd): try: wait(msc.subscriber_attached, *modems) + for m in modems: + wait(m.is_connected) except Timeout: print('Timeout while waiting for registration.') elif 'get-registered'.startswith(cmd): diff --git a/suites/aoip_sms/mo_mt_sms.py b/suites/aoip_sms/mo_mt_sms.py index b9383ea..309237e 100755 --- a/suites/aoip_sms/mo_mt_sms.py +++ b/suites/aoip_sms/mo_mt_sms.py @@ -21,14 +21,16 @@ hlr.subscriber_add(ms_mo) hlr.subscriber_add(ms_mt) -ms_mo.connect(bsc) -ms_mt.connect(bsc) +ms_mo.connect(msc.mcc_mnc()) +ms_mt.connect(msc.mcc_mnc()) ms_mo.log_info() ms_mt.log_info() print('waiting for modems to attach...') wait(msc.subscriber_attached, ms_mo, ms_mt) +wait(ms_mo.is_connected) +wait(ms_mt.is_connected) sms = ms_mo.sms_send(ms_mt) wait(ms_mt.sms_was_received, sms) diff --git a/suites/debug/interactive.py b/suites/debug/interactive.py index 603e395..815f0c0 100755 --- a/suites/debug/interactive.py +++ b/suites/debug/interactive.py @@ -13,7 +13,7 @@ for m in modems: nitb.subscriber_add(m) - m.connect(nitb) + m.connect(nitb.mcc_mnc()) while True: cmd = prompt('Enter command: (q)uit (s)ms (g)et-registered (w)ait-registered') @@ -26,6 +26,8 @@ elif 'wait-registered'.startswith(cmd): try: wait(nitb.subscriber_attached, *modems) + for m in modems: + wait(m.is_connected) except Timeout: print('Timeout while waiting for registration.') elif 'get-registered'.startswith(cmd): diff --git a/suites/netreg/register.py b/suites/netreg/register.py new file mode 100755 index 0000000..103770a --- /dev/null +++ b/suites/netreg/register.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +from osmo_gsm_tester.test import * + +print('use resources...') +nitb = suite.nitb() +bts = suite.bts() +ms = suite.modem() + +print('start nitb and bts...') +nitb.bts_add(bts) +nitb.start() +bts.start() + +nitb.subscriber_add(ms) + +ms.connect(nitb.mcc_mnc()) + +print(ms.properties()) + +wait(nitb.subscriber_attached, ms) +wait(ms.is_connected) diff --git a/suites/netreg/register_default.py b/suites/netreg/register_default.py new file mode 100755 index 0000000..661bcec --- /dev/null +++ b/suites/netreg/register_default.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 +from osmo_gsm_tester.test import * + +print('use resources...') +nitb = suite.nitb() +bts = suite.bts() +ms = suite.modem() + +print('start nitb and bts...') +nitb.bts_add(bts) +nitb.start() +bts.start() + +nitb.subscriber_add(ms) + +ms.connect() + +print(ms.properties()) + +wait(nitb.subscriber_attached, ms) +wait(ms.is_connected) diff --git a/suites/netreg/suite.conf b/suites/netreg/suite.conf new file mode 100644 index 0000000..1bb1dbb --- /dev/null +++ b/suites/netreg/suite.conf @@ -0,0 +1,10 @@ +resources: + ip_address: + - times: 1 + bts: + - times: 1 + modem: + - times: 1 + +defaults: + timeout: 40s diff --git a/suites/sms/mo_mt_sms.py b/suites/sms/mo_mt_sms.py index 860f5e7..3ccf947 100755 --- a/suites/sms/mo_mt_sms.py +++ b/suites/sms/mo_mt_sms.py @@ -14,14 +14,16 @@ nitb.subscriber_add(ms_mo) nitb.subscriber_add(ms_mt) -ms_mo.connect(nitb) -ms_mt.connect(nitb) +ms_mo.connect(nitb.mcc_mnc()) +ms_mt.connect(nitb.mcc_mnc()) ms_mo.log_info() ms_mt.log_info() print('waiting for modems to attach...') wait(nitb.subscriber_attached, ms_mo, ms_mt) +wait(ms_mo.is_connected) +wait(ms_mt.is_connected) sms = ms_mo.sms_send(ms_mt) wait(ms_mt.sms_was_received, sms) -- To view, visit https://gerrit.osmocom.org/2779 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: newpatchset Gerrit-Change-Id: I8d9eb47eac1044550d3885adb55105c304b0c15c Gerrit-PatchSet: 5 Gerrit-Project: osmo-gsm-tester Gerrit-Branch: master Gerrit-Owner: Pau Espin Pedrol <pespin at sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr at sysmocom.de>