diff mbox series

[4/4] ofono: Provide a secondary opportunity to get CM props and contexts.

Message ID 5f8c2021153277ed01fe100f733f935c5cf6b9db.1739403363.git.gerickson@nuovations.com (mailing list archive)
State Accepted
Commit 0b091dd8fc8fc6fd4f780914587ab3969600dd40
Headers show
Series ofono: Make the oFono Plugin Modem Interface Order Tolerant | expand

Commit Message

Grant Erickson Feb. 12, 2025, 11:39 p.m. UTC
Provides a secondary opportunity to send D-Bus request to get
Connection Manager interface properties and contexts at the successful
closure of 'try_create_device' since the primary opportunity in
'modem_update_interfaces' is missed in the following test case:

    # connmanctl disable cellular
    # /etc/init.d/connman stop
    # /etc/init.d/ofono stop
    # rm -rf /var/lib/ofono/*
    # rm -rf /var/lib/connman/cellular*
    # /etc/init.d/ofono start
    # /etc/init.d/connman start
    # connmanctl enable cellular

At this point, ofonod will create a fully-provisioned and -functional
Cellular service, with both IPv4 and IPv6 Cellular network
contexts. However, connmand has no network and no service associated
with it so, so any Connection Manager client observing the Cellular
service state will observe it failing, on timeout.

In this use case, the ordering of the oFono 'lte' (Long-term
Evolution) and 'cm' (Connection Manager) modem interfaces shared
between ofonod and connmand is different from what they normally are
in the case where a Cellular connection has already been
established. Consequently, when the 'cm' interface state change
notification addition arrives, the connman device has not yet been
created because in 'modem_update_interfaces' executing
'cm_get_properties' and 'cm_get_contexts' is dependent on the presence
of 'modem->device':

	if (api_added(old_ifaces, new_ifaces, OFONO_API_CM)) {
		if (modem->device) {
			cm_get_properties(modem);
			cm_get_contexts(modem);
		}
	}

Unfortunately, that does not and cannot happen until the 'lte' modem
interface is added because 'try_create_device' has these conditionals:

	if ((modem->capabilities & LTE_CAPABLE) &&
			!has_interface(modem->interfaces, OFONO_API_LTE))
		return false;

and the 'lte' interface is added only moments later (rather than
moments earlier as is normal outside this use case), but too late
nonetheless. So, the ofono plugin will never get 'cm' interface
properties or Cellular network contexts.

With this change, each call to 'try_create_device' now has an
opportunity to check if the 'cm' interface has been added and, if it
has, to request 'cm' properties and contexts.
---
 plugins/ofono.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)
diff mbox series

Patch

diff --git a/plugins/ofono.c b/plugins/ofono.c
index 820299765c67..f5248e57488b 100644
--- a/plugins/ofono.c
+++ b/plugins/ofono.c
@@ -167,6 +167,9 @@  struct modem_data {
 	DBusPendingCall *call_get_contexts;
 };
 
+static int cm_get_contexts(struct modem_data *modem);
+static int cm_get_properties(struct modem_data *modem);
+
 static const char *api2string(enum ofono_api api)
 {
 	switch (api) {
@@ -1038,6 +1041,27 @@  static bool try_create_device(struct modem_data *modem)
 	modem->device = device;
 	connman_device_set_powered(modem->device, modem->online);
 
+	/*
+	 * The order in which the LTE and Connection Manager interfaces
+	 * arrive may not always be the same.
+	 *
+	 * If the latter arrived before the former and a modem device was
+	 * successfully created, this represents a secondary opportunity
+	 * to get Connection Manager properties and contexts, both
+	 * essential to successfully creating a Connection Manager
+	 * Cellular network and service.
+	 *
+	 * The primary opportunity would have been with api_added in
+	 * modem_update_interfaces; however, that would have been skipped
+	 * since the LTE interface did not yet exist in such a scenario
+	 * and this call would exit early due to the LTE_CAPABLE and
+	 * OFONO_API_LTE conditional checks above.
+	 */
+	if (has_interface(modem->interfaces, OFONO_API_CM)) {
+		cm_get_properties(modem);
+		cm_get_contexts(modem);
+	}
+
 	return true;
 }