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 (#7). 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, 223 insertions(+), 9 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-gsm-tester refs/changes/79/2779/7 diff --git a/src/osmo_gsm_tester/ofono_client.py b/src/osmo_gsm_tester/ofono_client.py index 46300ec..394220f 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 = [] @@ -72,6 +79,55 @@ 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, + *proxymethod_args, + result_handler=None, error_handler=None, + user_data=None, timeout=30, + **proxymethod_kwargs): + +#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(proxymethod_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(proxymethod_args))) + + timeout = timeout * 1000 + user_data = (result_handler, error_handler, user_data) + + ret = instance._bus.con.call( + instance._bus_name, instance._path, + proxymethod._iface_name, proxymethod.__name__, + GLib.Variant(proxymethod._sinargs, proxymethod_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 +311,10 @@ self.path = conf.get('path') self.set_name(self.path) self.set_log_category(log.C_TST) + self.mcc_mnc = 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 +381,71 @@ 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 is_connected(self, mcc_mnc=None): + nr = self.dbus.interface(I_NETREG) + prop = nr.GetProperties() + status = prop.get('Status') + if not (status == NETREG_ST_REGISTERED or status == NETREG_ST_ROAMING): + return False + if mcc_mnc is None: # Any network is fine and we are registered. + return True + mcc = prop.get('MobileCountryCode') + mnc = prop.get('MobileNetworkCode') + if (mcc, mnc) == mcc_mnc: + return True + return False + + def schedule_scan_register(self): + if self.register_attempts > NETREG_MAX_REGISTER_ATTEMPTS: + self.raise_exn('Failed to find Network Operator', mcc_mnc=self.mcc_mnc, attempts=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 register when the scan is + # finished. + dbus_async_call(nr.Scan, nr, timeout=30, result_handler=self.scan_result_cb, + error_handler=self.scan_error_cb, user_data=None) + + def scan_error_cb(self, obj, e, user_data): + self.raise_exn('Scan() failed:', e) + + def scan_result_cb(self, obj, result, user_data): + self.register(result) + + def register(self, scanned_operators): + if self.mcc_mnc is None: + if not self.is_connected(): + self.log('Registering with the default network...') + nr = self.dbus.interface(I_NETREG) + nr.Register() + else: + self.log('Already registered with the network') + return + self.dbg('scanned operators: ', scanned_operators); + myop = None + for op in scanned_operators: + op_path, op_prop = op + mcc = op_prop.get('MobileCountryCode') + mnc = op_prop.get('MobileNetworkCode') + if (mcc, mnc) == self.mcc_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', mcc_mnc=self.mcc_mnc, attempts=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 +455,19 @@ self.set_online() event_loop.wait(self, self.dbus.has_interface, I_NETREG, I_SMS, timeout=10) + def connect(self, mcc_mnc=None): + 'Connect to MCC+MNC from NITB config' + if mcc_mnc is not None and (len(mcc_mnc) != 2 or None in mcc_mnc): + self.raise_exn('mcc_mnc value is invalid. It should be None or contain both valid mcc and mnc values:', mcc_mnc=mcc_mnc) + self.mcc_mnc = mcc_mnc + self.power_cycle() + self.log('connect to', self.mcc_mnc if self.mcc_mnc else 'default network') + self.register_attempts = 0 + if self.is_connected(self.mcc_mnc): + self.log('Already registered with the network') + else: + 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 ca0e246..b2507c8 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 b2ddfb7..b4bf247 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 7cc1b76..cfedd3a 100755 --- a/suites/aoip_debug/interactive.py +++ b/suites/aoip_debug/interactive.py @@ -18,7 +18,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 @@ break elif 'wait-registered'.startswith(cmd): try: + for m in modems: + wait(m.is_connected, msc.mcc_mnc()) wait(msc.subscriber_attached, *modems) except Timeout: print('Timeout while waiting for registration.') diff --git a/suites/aoip_sms/mo_mt_sms.py b/suites/aoip_sms/mo_mt_sms.py index b9383ea..8eba842 100755 --- a/suites/aoip_sms/mo_mt_sms.py +++ b/suites/aoip_sms/mo_mt_sms.py @@ -21,13 +21,15 @@ 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(ms_mo.is_connected, msc.mcc_mnc()) +wait(ms_mt.is_connected, msc.mcc_mnc()) wait(msc.subscriber_attached, ms_mo, ms_mt) sms = ms_mo.sms_send(ms_mt) diff --git a/suites/debug/interactive.py b/suites/debug/interactive.py index 603e395..37076dc 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') @@ -25,6 +25,8 @@ break elif 'wait-registered'.startswith(cmd): try: + for m in modems: + wait(m.is_connected, nitb.mcc_mnc()) wait(nitb.subscriber_attached, *modems) except Timeout: print('Timeout while waiting for registration.') diff --git a/suites/netreg/register.py b/suites/netreg/register.py new file mode 100755 index 0000000..9141986 --- /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.info()) + +wait(ms.is_connected, nitb.mcc_mnc()) +wait(nitb.subscriber_attached, ms) diff --git a/suites/netreg/register_default.py b/suites/netreg/register_default.py new file mode 100755 index 0000000..d15b3f5 --- /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.info()) + +wait(ms.is_connected) +wait(nitb.subscriber_attached, ms) 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..4e0ba08 100755 --- a/suites/sms/mo_mt_sms.py +++ b/suites/sms/mo_mt_sms.py @@ -14,13 +14,15 @@ 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(ms_mo.is_connected, nitb.mcc_mnc()) +wait(ms_mt.is_connected, nitb.mcc_mnc()) wait(nitb.subscriber_attached, ms_mo, ms_mt) sms = ms_mo.sms_send(ms_mt) -- 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: 7 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> Gerrit-Reviewer: Pau Espin Pedrol <pespin at sysmocom.de>