From edbf766e96332656fca5e3fe7ee86fb4597a6d55 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Sun, 7 Jun 2015 23:22:04 +0200 Subject: [PATCH 1/4] manager: log the address, not the path of the master active connection The connection might not be exported on D-Bus at that point yet and thus shows up as (null) in logs, which is not too helpful. --- src/nm-manager.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index f5f4ba80d6..76ffc72aed 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -2696,9 +2696,9 @@ _internal_activate_device (NMManager *self, NMActiveConnection *active, GError * } nm_active_connection_set_master (active, master_ac); - nm_log_dbg (LOGD_CORE, "Activation of '%s' depends on active connection %s", + nm_log_dbg (LOGD_CORE, "Activation of '%s' depends on active connection %p", nm_connection_get_id (connection), - nm_active_connection_get_path (master_ac)); + master_ac); } /* Check slaves for master connection and possibly activate them */ From f23a46d4b79088344f9d0ad4528afb81f492f54c Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 23 Jun 2015 21:08:29 +0200 Subject: [PATCH 2/4] ifcfg-rh,vlan: fall back to VLAN_ID if vlan id can't be determined from DEVICE If the device begins with "vlan", but a VLAN ID does not follow, the reader would fail and ignore the actual VLAN_ID. --- src/settings/plugins/ifcfg-rh/reader.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index 9dcf5f3b59..29c7854dd1 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -4493,13 +4493,10 @@ make_vlan_setting (shvarFile *ifcfg, /* Grab VLAN ID from interface name; this takes precedence over the * separate VLAN_ID property for backwards compat. */ - vlan_id = (gint) g_ascii_strtoll (p, &end, 10); - if (vlan_id < 0 || vlan_id > 4095 || end == p || *end) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Failed to determine VLAN ID from DEVICE '%s'", - iface_name); - goto error; - } + + gint device_vlan_id = (gint) g_ascii_strtoll (p, &end, 10); + if (device_vlan_id >= 0 && device_vlan_id <= 4095 && end != p && !*end) + vlan_id = device_vlan_id; } } From 40788349997764ee2b0493c131b9640f9f065234 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 23 Jun 2015 21:13:58 +0200 Subject: [PATCH 3/4] active-connection: fail the activation if the master AC disconnect The master may not have successfully activated even though we know the device already. --- src/nm-active-connection.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c index 2b7296196d..b0bdd77a81 100644 --- a/src/nm-active-connection.c +++ b/src/nm-active-connection.c @@ -530,6 +530,7 @@ master_state_cb (NMActiveConnection *master, gpointer user_data) { NMActiveConnection *self = NM_ACTIVE_CONNECTION (user_data); + NMActiveConnectionPrivate *priv = NM_ACTIVE_CONNECTION_GET_PRIVATE (self); NMActiveConnectionState master_state = nm_active_connection_get_state (master); check_master_ready (self); @@ -537,8 +538,8 @@ master_state_cb (NMActiveConnection *master, nm_log_dbg (LOGD_DEVICE, "(%p): master ActiveConnection [%p] state now '%s' (%d)", self, master, state_to_string (master_state), master_state); - if (master_state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATING && - nm_active_connection_get_device (master) == NULL) { + if ( master_state >= NM_ACTIVE_CONNECTION_STATE_DEACTIVATING + && !priv->master_ready) { /* Master failed without ever creating its device */ if (NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed) NM_ACTIVE_CONNECTION_GET_CLASS (self)->master_failed (self); From 7a066a35ad8c48aac669dce286be499663eb9cd8 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 23 Jun 2015 20:52:04 +0200 Subject: [PATCH 4/4] manager: reuse an active connection, if the same activation is pending When a master & slaves get activated at the same time, they all submit separate active connections which race for the device after activation. --- src/nm-manager.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index 76ffc72aed..13decd6d4f 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -154,6 +154,7 @@ typedef struct { char *state_file; GSList *active_connections; + GSList *authorizing_connections; guint ac_cleanup_id; NMActiveConnection *primary_connection; NMActiveConnection *activating_connection; @@ -2857,8 +2858,11 @@ _internal_activation_auth_done (NMActiveConnection *active, gpointer user_data2) { NMManager *self = user_data1; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); GError *error = NULL; + priv->authorizing_connections = g_slist_remove (priv->authorizing_connections, active); + if (success) { if (_internal_activate_generic (self, active, &error)) { g_object_unref (active); @@ -2898,8 +2902,10 @@ nm_manager_activate_connection (NMManager *self, NMAuthSubject *subject, GError **error) { + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMActiveConnection *active; char *error_desc = NULL; + GSList *iter; g_return_val_if_fail (self != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL); @@ -2918,14 +2924,32 @@ nm_manager_activate_connection (NMManager *self, return NULL; } + /* Look for a active connection that's equivalent and is already pending authorization + * and eventual activation. This is used to de-duplicate concurrent activations which would + * otherwise race and cause the device to disconnect and reconnect repeatedly. + * In particular, this allows the master and multiple slaves to concurrently auto-activate + * while all the slaves would use the same active-connection. */ + for (iter = priv->authorizing_connections; iter; iter = g_slist_next (iter)) { + active = iter->data; + + if ( connection == nm_active_connection_get_connection (active) + && g_strcmp0 (nm_active_connection_get_specific_object (active), specific_object) == 0 + && nm_active_connection_get_device (active) == device + && nm_auth_subject_is_internal (nm_active_connection_get_subject (active)) + && nm_auth_subject_is_internal (subject)) + return active; + } + active = _new_active_connection (self, connection, specific_object, device, subject, error); - if (active) + if (active) { + priv->authorizing_connections = g_slist_prepend (priv->authorizing_connections, active); nm_active_connection_authorize (active, _internal_activation_auth_done, self, NULL); + } return active; }