summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-04-19 16:16:12 +0200
committerThomas Haller <thaller@redhat.com>2017-04-20 14:20:04 +0200
commit27b2477cb7dad2410c88c7dfca51f3aad208b881 (patch)
tree1d232333abb75b012f4d007408a4f23a18788729
parent2131954a190244714e8b27b48567594c7b103fb9 (diff)
downloadNetworkManager-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.c90
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);
}