diff options
author | Thomas Haller <thaller@redhat.com> | 2017-04-19 16:16:12 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-04-20 14:20:04 +0200 |
commit | 27b2477cb7dad2410c88c7dfca51f3aad208b881 (patch) | |
tree | 1d232333abb75b012f4d007408a4f23a18788729 | |
parent | 2131954a190244714e8b27b48567594c7b103fb9 (diff) | |
download | NetworkManager-27b2477cb7dad2410c88c7dfca51f3aad208b881.tar.gz |
device: assume matching connections during first start
Since commit 2d1b85f (th/assume-vs-unmanaged-bgo746440), we clearly
distinguish between two modes when encountering devices with external
IP configuration:
a) external devices. For those devices we generate a volatile in-memory
connection and pretend it's active. However, the device must not be
touched by NetworkManager in any way.
b) assume, seamless take over. Mostly for restart of NetworkManager,
we activate a connection gracefully without going through an down-up
cycle. After the device reaches activated state, the device is
considered fully managed. For this only an existing, non volatile
connection can be used.
Before 'th/assume-vs-unmanaged-bgo746440', the behaviors were not
clearly separated.
Since then, we only choose to assume a connection (b) when the state
file indicates a matching connection. Now, extend this to also assume
connections when:
- during first-start (not after a restart) when there is no
state file yet.
- and, if we have an existing, non volatile, connection which
matches the device's configuration.
This patch lets NetworkManager assume connection also on first start.
That is for example useful when handing over network configuration from
initrd.
This only applies to existing, permanent, matching(!) connections, so it is a
good guess that the user wants NM to take over this interface. This brings us
closer to the previous behavior before 'th/assume-vs-unmanaged-bgo746440'.
https://bugzilla.redhat.com/show_bug.cgi?id=1439220
-rw-r--r-- | src/nm-manager.c | 90 |
1 files changed, 66 insertions, 24 deletions
diff --git a/src/nm-manager.c b/src/nm-manager.c index 01303ca93d..2490025574 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -450,6 +450,8 @@ _get_activatable_connections_filter (NMSettings *settings, NMSettingsConnection *connection, gpointer user_data) { + if (nm_settings_connection_get_volatile (connection)) + return FALSE; return !active_connection_find_first (user_data, connection, NULL, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING); } @@ -1677,16 +1679,12 @@ done: g_clear_error (&error); } -static gboolean -match_connection_filter (NMConnection *connection, gpointer user_data) -{ - return nm_device_check_connection_compatible (NM_DEVICE (user_data), connection); -} - /** * get_existing_connection: * @manager: #NMManager instance * @device: #NMDevice instance + * @guess_assume: whether to employ a heuristic to search for a matching + * connection to assume. * @assume_connection_uuid: if present, try to assume a connection with this * UUID. If no uuid is given or no matching connection is found, we * only do external activation. @@ -1698,6 +1696,7 @@ match_connection_filter (NMConnection *connection, gpointer user_data) static NMSettingsConnection * get_existing_connection (NMManager *self, NMDevice *device, + gboolean guess_assume, const char *assume_connection_uuid, gboolean *out_generated) { @@ -1708,6 +1707,7 @@ get_existing_connection (NMManager *self, NMDevice *master = NULL; int ifindex = nm_device_get_ifindex (device); NMSettingsConnection *matched; + NMSettingsConnection *connection_checked = NULL; if (out_generated) *out_generated = FALSE; @@ -1752,11 +1752,12 @@ get_existing_connection (NMManager *self, * the generated connection instead. */ if ( assume_connection_uuid - && (matched = nm_settings_get_connection_by_uuid (priv->settings, assume_connection_uuid)) - && !active_connection_find_first (self, matched, NULL, - NM_ACTIVE_CONNECTION_STATE_DEACTIVATING)) { + && (connection_checked = nm_settings_get_connection_by_uuid (priv->settings, assume_connection_uuid)) + && !active_connection_find_first (self, connection_checked, NULL, + NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) + && nm_device_check_connection_compatible (device, NM_CONNECTION (connection_checked))) { NMConnection *const connections[] = { - NM_CONNECTION (matched), + NM_CONNECTION (connection_checked), NULL, }; @@ -1765,17 +1766,50 @@ get_existing_connection (NMManager *self, nm_device_has_carrier (device), nm_device_get_ip4_route_metric (device), nm_device_get_ip6_route_metric (device), - match_connection_filter, - device)); - if (matched) { - _LOGI (LOGD_DEVICE, "(%s): found matching connection '%s'", - nm_device_get_iface (device), - nm_settings_connection_get_id (matched)); - g_object_unref (connection); - return matched; + NULL, NULL)); + } else + matched = NULL; + + if (!matched && guess_assume) { + gs_free NMSettingsConnection **connections = NULL; + guint len, i, j; + + /* the state file doesn't indicate a connection UUID to assume. Search the + * persistent connections for a matching candidate. */ + connections = nm_manager_get_activatable_connections (self, &len, FALSE); + if (len > 0) { + for (i = 0, j = 0; i < len; i++) { + NMConnection *con = NM_CONNECTION (connections[i]); + + if ( con != NM_CONNECTION (connection_checked) + && nm_device_check_connection_compatible (device, con)) + connections[j++] = connections[i]; + } + connections[j] = NULL; + len = j; + g_qsort_with_data (connections, len, sizeof (connections[0]), + nm_settings_connection_cmp_timestamp_p_with_data, NULL); + + matched = NM_SETTINGS_CONNECTION (nm_utils_match_connection ((NMConnection *const*) connections, + connection, + nm_device_has_carrier (device), + nm_device_get_ip4_route_metric (device), + nm_device_get_ip6_route_metric (device), + NULL, NULL)); } } + if (matched) { + _LOGI (LOGD_DEVICE, "(%s): found matching connection '%s' (%s)%s", + nm_device_get_iface (device), + nm_settings_connection_get_id (matched), + nm_settings_connection_get_uuid (matched), + assume_connection_uuid && nm_streq (assume_connection_uuid, nm_settings_connection_get_uuid (matched)) + ? " (indicated)" : " (guessed)"); + g_object_unref (connection); + return matched; + } + _LOGD (LOGD_DEVICE, "(%s): generated connection '%s'", nm_device_get_iface (device), nm_connection_get_id (connection)); @@ -1803,6 +1837,7 @@ get_existing_connection (NMManager *self, static gboolean recheck_assume_connection (NMManager *self, NMDevice *device, + gboolean guess_assume, const char *assume_connection_uuid) { NMSettingsConnection *connection; @@ -1826,7 +1861,7 @@ recheck_assume_connection (NMManager *self, if (nm_device_sys_iface_state_get (device) != NM_DEVICE_SYS_IFACE_STATE_EXTERNAL) return FALSE; - connection = get_existing_connection (self, device, assume_connection_uuid, &generated); + connection = get_existing_connection (self, device, guess_assume, assume_connection_uuid, &generated); if (!connection) { _LOGD (LOGD_DEVICE, "(%s): can't assume; no connection", nm_device_get_iface (device)); @@ -1906,7 +1941,7 @@ recheck_assume_connection (NMManager *self, static void recheck_assume_connection_cb (NMDevice *device, gpointer user_data) { - recheck_assume_connection (user_data, device, NULL); + recheck_assume_connection (user_data, device, FALSE, NULL); } static void @@ -2000,6 +2035,7 @@ static void _device_realize_finish (NMManager *self, NMDevice *device, const NMPlatformLink *plink, + gboolean guess_assume, const char *connection_uuid_to_assume) { g_return_if_fail (NM_IS_MANAGER (self)); @@ -2010,7 +2046,7 @@ _device_realize_finish (NMManager *self, if (!nm_device_get_managed (device, FALSE)) return; - if (recheck_assume_connection (self, device, connection_uuid_to_assume)) + if (recheck_assume_connection (self, device, guess_assume, connection_uuid_to_assume)) return; /* if we failed to assume a connection for the managed device, but the device @@ -2168,7 +2204,7 @@ factory_device_added_cb (NMDeviceFactory *factory, NULL, &error)) { add_device (self, device, NULL); - _device_realize_finish (self, device, NULL, NULL); + _device_realize_finish (self, device, NULL, FALSE, NULL); } else { _LOGW (LOGD_DEVICE, "(%s): failed to realize device: %s", nm_device_get_iface (device), error->message); @@ -2214,6 +2250,7 @@ static void platform_link_added (NMManager *self, int ifindex, const NMPlatformLink *plink, + gboolean guess_assume, const NMConfigDeviceStateData *dev_state) { NMDeviceFactory *factory; @@ -2245,7 +2282,7 @@ platform_link_added (NMManager *self, &compatible, &error)) { /* Success */ - _device_realize_finish (self, candidate, plink, NULL); + _device_realize_finish (self, candidate, plink, FALSE, NULL); return; } @@ -2317,6 +2354,7 @@ platform_link_added (NMManager *self, &error)) { add_device (self, device, NULL); _device_realize_finish (self, device, plink, + guess_assume, dev_state ? dev_state->connection_uuid : NULL); } else { _LOGW (LOGD_DEVICE, "%s: failed to realize device: %s", @@ -2347,7 +2385,7 @@ _platform_link_cb_idle (PlatformLinkCbData *data) NMPlatformLink pllink; pllink = *l; /* make a copy of the link instance */ - platform_link_added (self, data->ifindex, &pllink, NULL); + platform_link_added (self, data->ifindex, &pllink, FALSE, NULL); } else { NMDevice *device; GError *error = NULL; @@ -2407,6 +2445,9 @@ platform_query_devices (NMManager *self) GArray *links_array; NMPlatformLink *links; int i; + gboolean guess_assume; + + guess_assume = nm_config_get_first_start (nm_config_get ()); links_array = nm_platform_link_get_all (NM_PLATFORM_GET); links = (NMPlatformLink *) links_array->data; @@ -2418,6 +2459,7 @@ platform_query_devices (NMManager *self) platform_link_added (self, links[i].ifindex, &links[i], + guess_assume && (!dev_state || !dev_state->connection_uuid), dev_state); } |