summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2014-02-09 03:49:55 -0600
committerDan Williams <dcbw@redhat.com>2014-02-21 09:45:06 -0600
commit9d50e9dbd9d84f5e8df32895bc245dadf133aa39 (patch)
treea1fe5461a4a184254947dd186cd366aad9101097
parent5c1dee10cde3cc7cf74718650702dd124d46aa75 (diff)
downloadNetworkManager-9d50e9dbd9d84f5e8df32895bc245dadf133aa39.tar.gz
mobile: fix removal of ethernet interfaces owned by modems
If the kernel doesn't tag a modem's ethernet interface with DEVTYPE=wwan then NetworkManager has no idea that's a modem (and cannot be used until connected via the control port). Since DEVTYPE=wwan devices get ignored by NM, so should these interfaces when NM knows they are modems. That got broken at some point for ModemManager1, because the data port isn't read until the modem is connected. NM only looked for and removed the data-port-as-ethernet-device when the modem was added, long before the MM1 data port was found. ModemManager does provide a list of ports owned by the modem though, which we can use at modem addition time to remove an ethernet device that is controled by the modem.
-rw-r--r--src/modem-manager/nm-modem-broadband.c15
-rw-r--r--src/modem-manager/nm-modem.c21
-rw-r--r--src/modem-manager/nm-modem.h4
-rw-r--r--src/nm-manager.c29
4 files changed, 58 insertions, 11 deletions
diff --git a/src/modem-manager/nm-modem-broadband.c b/src/modem-manager/nm-modem-broadband.c
index 611931f6b9..5acce68f79 100644
--- a/src/modem-manager/nm-modem-broadband.c
+++ b/src/modem-manager/nm-modem-broadband.c
@@ -124,6 +124,20 @@ get_capabilities (NMModem *_self,
*current_caps = (NMDeviceModemCapabilities) mm_modem_get_current_capabilities (self->priv->modem_iface);
}
+static gboolean
+owns_port (NMModem *_self, const char *iface)
+{
+ NMModemBroadband *self = NM_MODEM_BROADBAND (_self);
+ const MMModemPortInfo *ports = NULL;
+ guint n_ports = 0, i;
+ gboolean owns = FALSE;
+
+ mm_modem_peek_ports (self->priv->modem_iface, &ports, &n_ports);
+ for (i = 0; i < n_ports && !owns; i++)
+ owns = (g_strcmp0 (iface, ports[i].name) == 0);
+ return owns;
+}
+
/*****************************************************************************/
static void
@@ -916,6 +930,7 @@ nm_modem_broadband_class_init (NMModemBroadbandClass *klass)
modem_class->check_connection_compatible = check_connection_compatible;
modem_class->complete_connection = complete_connection;
modem_class->act_stage1_prepare = act_stage1_prepare;
+ modem_class->owns_port = owns_port;
/* Properties */
g_object_class_install_property
diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c
index f427142e2b..e88ebe1bd7 100644
--- a/src/modem-manager/nm-modem.c
+++ b/src/modem-manager/nm-modem.c
@@ -661,6 +661,27 @@ nm_modem_get_data_port (NMModem *self)
NM_MODEM_GET_PRIVATE (self)->ppp_iface : NM_MODEM_GET_PRIVATE (self)->data_port;
}
+gboolean
+nm_modem_owns_port (NMModem *self, const char *iface)
+{
+ NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self);
+
+ g_return_val_if_fail (iface != NULL, FALSE);
+
+ if (NM_MODEM_GET_CLASS (self)->owns_port)
+ return NM_MODEM_GET_CLASS (self)->owns_port (self, iface);
+
+ /* Fall back to data/control ports */
+ if (priv->ppp_iface && (strcmp (priv->ppp_iface, iface) == 0))
+ return TRUE;
+ if (priv->data_port && (strcmp (priv->data_port, iface) == 0))
+ return TRUE;
+ if (priv->control_port && (strcmp (priv->control_port, iface) == 0))
+ return TRUE;
+
+ return FALSE;
+}
+
/*****************************************************************************/
void
diff --git a/src/modem-manager/nm-modem.h b/src/modem-manager/nm-modem.h
index 531c79388e..db20407006 100644
--- a/src/modem-manager/nm-modem.h
+++ b/src/modem-manager/nm-modem.h
@@ -108,6 +108,8 @@ typedef struct {
void (*deactivate) (NMModem *self, NMDevice *device);
+ gboolean (*owns_port) (NMModem *self, const char *iface);
+
/* Signals */
void (*ppp_stats) (NMModem *self, guint32 in_bytes, guint32 out_bytes);
void (*ppp_failed) (NMModem *self, NMDeviceStateReason reason);
@@ -127,6 +129,8 @@ const char *nm_modem_get_control_port (NMModem *modem);
const char *nm_modem_get_data_port (NMModem *modem);
const char *nm_modem_get_driver (NMModem *modem);
+gboolean nm_modem_owns_port (NMModem *modem, const char *iface);
+
void nm_modem_get_capabilities (NMModem *self,
NMDeviceModemCapabilities *modem_caps,
NMDeviceModemCapabilities *current_caps);
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 3ae48c8538..7cb71a63c7 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -550,19 +550,22 @@ modem_added (NMModemManager *modem_manager,
{
NMManager *self = NM_MANAGER (user_data);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
- NMDevice *replace_device, *device = NULL;
+ NMDevice *device = NULL;
const char *modem_iface;
- GSList *iter;
+ GSList *iter, *remove = NULL;
- /* Don't rely only on the data port; use the control port if available */
- modem_iface = nm_modem_get_data_port (modem);
- if (!modem_iface)
- modem_iface = nm_modem_get_control_port (modem);
- g_return_if_fail (modem_iface);
-
- replace_device = find_device_by_ip_iface (NM_MANAGER (user_data), modem_iface);
- if (replace_device)
- remove_device (NM_MANAGER (user_data), replace_device, FALSE);
+ /* Remove ethernet devices that are actually owned by the modem, since
+ * they cannot be used as normal ethernet.
+ */
+ for (iter = priv->devices; iter; iter = iter->next) {
+ if (nm_device_get_device_type (iter->data) == NM_DEVICE_TYPE_ETHERNET) {
+ if (nm_modem_owns_port (modem, nm_device_get_ip_iface (iter->data)))
+ remove = g_slist_prepend (remove, iter->data);
+ }
+ }
+ for (iter = remove; iter; iter = iter->next)
+ remove_device (self, NM_DEVICE (iter->data), FALSE);
+ g_slist_free (remove);
/* Give Bluetooth DUN devices first chance to claim the modem */
for (iter = priv->devices; iter; iter = g_slist_next (iter)) {
@@ -577,6 +580,10 @@ modem_added (NMModemManager *modem_manager,
* by the Bluetooth code during the connection process.
*/
if (driver && !strcmp (driver, "bluetooth")) {
+ modem_iface = nm_modem_get_data_port (modem);
+ if (!modem_iface)
+ modem_iface = nm_modem_get_control_port (modem);
+
nm_log_info (LOGD_MB, "ignoring modem '%s' (no associated Bluetooth device)", modem_iface);
return;
}