manager: retry virtual connections when a device is added or changes

When a new device gets added or when an existing one changes name,
virtual connections that refer to it as parent device may become
ready, so let's try to activate them.

Previously we tried to activate virtual connections only on startup
and, after commit d8e1590c50 ("manager: retry device creation for
connection that would use a newly created device"), also when a
connection was added/changed, but this doesn't cover the case in which
a parent device appears or changes name at runtime.

https://bugzilla.redhat.com/show_bug.cgi?id=1275875
This commit is contained in:
Beniamino Galvani 2016-01-07 17:54:38 +01:00
parent ad2584c375
commit 5996565ca9

View file

@ -81,6 +81,9 @@ static gboolean find_master (NMManager *self,
static void nm_manager_update_state (NMManager *manager);
static void connection_changed (NMSettings *settings, NMConnection *connection,
NMManager *manager);
#define TAG_ACTIVE_CONNETION_ADD_AND_ACTIVATE "act-con-add-and-activate"
typedef struct {
@ -1097,12 +1100,30 @@ system_create_virtual_device (NMManager *self, NMConnection *connection)
return device;
}
static void
retry_connections_for_parent_device (NMManager *self, NMDevice *device)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GSList *connections, *iter;
g_return_if_fail (device);
connections = nm_settings_get_connections (priv->settings);
for (iter = connections; iter; iter = g_slist_next (iter)) {
NMConnection *candidate = iter->data;
NMDevice *parent;
parent = find_parent_device_for_connection (self, candidate);
if (parent == device)
connection_changed (priv->settings, candidate, self);
}
}
static void
connection_changed (NMSettings *settings,
NMConnection *connection,
NMManager *manager)
{
GSList *connections, *iter;
NMDevice *device;
if (!nm_connection_is_virtual (connection))
@ -1115,16 +1136,7 @@ connection_changed (NMSettings *settings,
/* Maybe the device that was created was needed by some other
* connection's device (parent of a VLAN). Let the connections
* can use the newly created device as a parent know. */
connections = nm_settings_get_connections (settings);
for (iter = connections; iter; iter = g_slist_next (iter)) {
NMConnection *candidate = iter->data;
NMDevice *parent;
parent = find_parent_device_for_connection (manager, candidate);
if (parent == device)
connection_changed (settings, candidate, manager);
}
retry_connections_for_parent_device (manager, device);
}
static void
@ -1738,6 +1750,18 @@ device_ip_iface_changed (NMDevice *device,
}
}
static void
device_iface_changed (NMDevice *device,
GParamSpec *pspec,
NMManager *self)
{
/* Virtual connections may refer to the new device name as
* parent device, retry to activate them.
*/
retry_connections_for_parent_device (self, device);
}
static void
device_realized (NMDevice *device,
GParamSpec *pspec,
@ -1832,6 +1856,11 @@ add_device (NMManager *self, NMDevice *device, GError **error)
g_signal_connect (device, "notify::" NM_DEVICE_IP_IFACE,
G_CALLBACK (device_ip_iface_changed),
self);
g_signal_connect (device, "notify::" NM_DEVICE_IFACE,
G_CALLBACK (device_iface_changed),
self);
g_signal_connect (device, "notify::" NM_DEVICE_REAL,
G_CALLBACK (device_realized),
self);
@ -1883,6 +1912,11 @@ add_device (NMManager *self, NMDevice *device, GError **error)
nm_device_notify_new_device_added (d, device);
}
/* Virtual connections may refer to the new device as
* parent device, retry to activate them.
*/
retry_connections_for_parent_device (self, device);
return TRUE;
}