Re: NM/ofono FlightMode problem
- From: Tony Espy <espy canonical com>
- To: Dan Williams <dcbw redhat com>
- Cc: networkmanager-list gnome org
- Subject: Re: NM/ofono FlightMode problem
- Date: Sat, 13 Jun 2015 19:42:19 -0400
On 06/12/2015 05:16 PM, Dan Williams wrote:
On Wed, 2015-06-03 at 20:40 -0400, Tony Espy wrote:
Dan --
I'd like to hear your opinion about the following problem I'm trying to
solve, and your take on an idea I have of how to fix it.
This occurs with the current version of NetworkManager we're using for
Ubuntu on phones, 0.9.10.0-4ubuntu15.1.1 ( see [1] for bzr packaging
branch ).
One of the patches ( ignore_rfkill_if_urfkill_is_present.patch ) we're
carrying allows NM to integrate with urfkill, a daemon that we use for
implementing FlightMode, and managing the desired state across reboots
of FlightMode and any other system radio killswitches. There's a long
story about why this daemon needed to be used, but I'll keep that out of
the discussion for now.
Please note, I'm pretty sure the following description is correct,
however it's possible that I missed something...
When the urfkill Killswitch DBus signal is received that indicates that
a radio killswitch for WWAN has been is disabled ( ie. setting the modem
online ), a callback in NM_MANAGER gets invoked. This callback then
invokes nm_manager_update_radio_enabled, which in turn iterates over all
the MANAGER's devices looking for a matching rf_type, and when found
calls nm_device_set_enabled for the device.
This eventually bubbles down to our NM_MODEM_OFONO subclass, which
actually doesn't do anything other than log the set_enabled call ( note,
urfkill is responsible for onlining/offlining the modem via ofono ).
As part of this chain of calls, NM_MODEM sets the modem_state to
ENABLING, which in turn triggers NM_DEVICE_MODEM to set the device_state
to DISCONNECTED, as the device has now become *available* ( thanks to
NM_DEVICE_MODEM->set_enabled setting the rf_enabled flag to TRUE ).
The problem is, this last device state change, triggers NM_DEVICE to
refresh the available connections, however doing so calls back into the
NM_MODEM_OFONO sub-class to check that connections are compatible. When
this happens, there's a chance that the ofono hasn't finished initizing
the modem after being set online by urfkill. If this happens, our modem
connection is effectively stalled, as nothing other than another
FlightMode toggle, or a reboot will re-kick the device to refresh it's
available connections again.
Per our IRC conversation, you're using the "SimManager" interface
appearing, then grabbing the SubscriberIdentity as the indicator of
initialization.
Not exactly...
'SubscriberIdentity' is needed by NMModemOfono's
check_connection_compatible function. It's a long story, but at
startup, our current ofono settings plugin reads all of ofono's gprs
contexts directly from ofono's settings' files ( note, ofono's settings
files are SIM-specific ). NMModemOfono uses the 'SubscriberIdentity' to
filter the connections so that only those for the current SIM are
considered.
When we receive a URfkill Killswitch DBus signal indicating that the
modem has been set online, NMDevice's set_enabled logic ends up
triggering a call to nm_device_recheck_available_connections. If the
modem hasn't fully finished coming back online, it's possible for
NMModemOfono's check_connection_compatible function to get an empty
value back the 'SubscriberIdentity' property, and thus none of the
connections are flagged as compatible...
So let's assume your NMOfonoModem subclass of NMModem starts in the
INITIALIZING state when the modem object is detected from Ofono.Your
NMModem subclass would never advance beyond the INITIALIZING state until
all of these conditions are met:
1) NM has called your set_mm_enabled() hook with true (you'd have to
cache that value internally)
2) The SimManager interface has appeared
3) SimManager.SubscriberIdentity has a valid value
at all 3 points where these things may change you can have a helper
function called maybe "check_modem_initialized()" that basically does
this:
if (rf_enabled && sim_manager && subscriber_identity) {
NMModemState new_state = NM_MODEM_STATE_ENABLED;
if (SimManager.PinRequired)
new_state = NM_MODEM_STATE_LOCKED;
nm_modem_set_state (NM_MODEM (self), new_state, <reason>);
} else if (nm_modem_get_state (NM_MODEM (self)) > INITIALIZING) {
nm_modem_set_state (NM_MODEM (self), INITIALIZING, <reason>);
}
so basically whenever ofono wasn't ready yet (modem in flight mode or
still initializing) the NMModem would sit in INITIALIZING state.
Whenever flight mode was activated the modem would jump back to
INITIALIZING. This should prevent the modem from becoming 'available'
before it can actually be used,
Sure, I see that NMDeviceModem's is_available function checks for
modem_state <= INITIALIZING. So if the modem_state was kept as
INITIALIZING until 'SubscriberIdentity' became available, this would
prevent the NMDevice recheck_available_connections logic from being
triggered till the modem was ready.
That said, I think I slightly misled you in the fact that the presence
of 'SubscriberIdentity' indicates that the ofono modem is initialized.
We monitor a separate property called 'Attached' on ofono's
ConnectionManager interface which indicates whether or not the modem is
attached to the GPRS network. Once this is 'true', the modem is
considered initialized and ready for data calls to be established.
Although the modem starts in INITIALIZING state, once the
ConnectionManager interface appears, the modem_state moves between
SEARCHING ( Attached=false ), REGISTERED ( Attached=true ), CONNECTED (
Attached=true, connection/context activated ), and DISCONNECTING.
The set_enabled logic however seems to be the only case where NMModem
directly sets modem_state. NMDeviceModem's set_enabled function calls
nm_modem_set_mm_enabled, which calls the modem subclass' set_mm_enabled,
then directly sets the modem_state to ENABLING or DISABLING. So this
would override the NMModemOfono goal of keeping the modem in
INITIALIZING state till the modem was ready.
I think my suggestion below, was to introduce the usage of the ENABLED
and DISABLED states, and then change NMDevice's is_available function to
check for <= ENABLED.
NMModemOfono and NMModemBroadband, could both then just signal when the
modem was ready after a set_enabled by setting the modem_state to ENABLED.
and might also fix the issue of
autoconnect retries becoming exhausted when flight mode is turned on
(that we discussed on IRC).
I think this case happens because when flight mode is turned on, ofono
first signals that any active gprs contexts are disconnected before it
indicates that the modem is offline ( by toggling it's top-level Manager
'Online' property ). So, the policy code sees the device DISCONNECTED
and immediately schedules a new activation via g_idle_add. So the
retries happen in a tight-loop, then NM see's 'Online' go to false.
Introducing a slight delay in scheduling these activation requests makes
this problem go away.
Hopefully this seems like it'll work to you, let me know if some things
look dubious though and we can continue to iterate.
I think I have enough to get going. I'll let you know how I make out.
Thanks again for your help!
Regards,
/tony
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]