mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-07 02:50:30 +01:00
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.
This commit is contained in:
parent
5c1dee10cd
commit
9d50e9dbd9
4 changed files with 58 additions and 11 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue