From 632dd26288601c8564e1363f9bbf2f1f96d2dc53 Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Mon, 26 Sep 2016 16:01:27 +0200 Subject: [PATCH] manager: allow slave connection to auto-connect its slaves Since connection.autoconnect-slaves was introduced, we only allowed it to autoactivate slaves for connections that were not slave themselves. It seems useful to remove such limitation, but we must prevent an infinite loop if there is a circular dependency between connections. https://bugzilla.redhat.com/show_bug.cgi?id=1360386 --- src/nm-manager.c | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index 93fd29b5a7..ed63b58605 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -233,6 +233,9 @@ NM_DEFINE_SINGLETON_INSTANCE (NMManager); /*****************************************************************************/ +GQuark autoconnect_root_quark (void); +G_DEFINE_QUARK (autoconnect-root, autoconnect_root); + static void active_connection_state_changed (NMActiveConnection *active, GParamSpec *pspec, NMManager *self); @@ -315,6 +318,7 @@ active_connection_state_changed (NMActiveConnection *active, { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); NMActiveConnectionState state; + NMSettingsConnection *con; state = nm_active_connection_get_state (active); if (state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) { @@ -325,6 +329,10 @@ active_connection_state_changed (NMActiveConnection *active, */ if (!priv->ac_cleanup_id) priv->ac_cleanup_id = g_idle_add (_active_connection_cleanup, self); + + con = nm_active_connection_get_settings_connection (active); + if (con) + g_object_set_qdata (G_OBJECT (con), autoconnect_root_quark (), NULL); } nm_manager_update_state (self); @@ -2719,14 +2727,9 @@ find_slaves (NMManager *manager, GSList *all_connections, *iter; GSList *slaves = NULL; NMSettingConnection *s_con; - const char *master; s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection)); g_assert (s_con); - master = nm_setting_connection_get_master (s_con); - - if (master != NULL) - return NULL; /* connection is not master */ /* Search through all connections, not only inactive ones, because * even if a slave was already active, it might be deactivated during @@ -2795,8 +2798,34 @@ autoconnect_slaves (NMManager *self, while (iter) { NMSettingsConnection *slave_connection = iter->data; + const char *uuid; iter = iter->next; + + /* To avoid loops when autoconnecting slaves, we propagate + * the UUID of the initial connection down to slaves until + * the same connection is found. + */ + uuid = g_object_get_qdata (G_OBJECT (master_connection), + autoconnect_root_quark ()); + if (nm_streq0 (nm_settings_connection_get_uuid (slave_connection), uuid)) { + _LOGI (LOGD_CORE, + "will NOT activate slave connection '%s' (%s) as a dependency for master '%s' (%s): " + "circular dependency detected", + nm_settings_connection_get_id (slave_connection), + nm_settings_connection_get_uuid (slave_connection), + nm_settings_connection_get_id (master_connection), + nm_settings_connection_get_uuid (master_connection)); + continue; + } + + if (!uuid) + uuid = nm_settings_connection_get_uuid (master_connection); + g_object_set_qdata_full (G_OBJECT (slave_connection), + autoconnect_root_quark (), + g_strdup (uuid), + g_free); + _LOGD (LOGD_CORE, "will activate slave connection '%s' (%s) as a dependency for master '%s' (%s)", nm_settings_connection_get_id (slave_connection), nm_settings_connection_get_uuid (slave_connection),