device: merge branch 'th/device-assume-guess-rh1443878'

https://bugzilla.redhat.com/show_bug.cgi?id=1443878

(cherry picked from commit c828277872)
This commit is contained in:
Thomas Haller
2017-04-20 14:20:27 +02:00
7 changed files with 111 additions and 50 deletions

View File

@@ -12997,7 +12997,7 @@ nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze)
{ {
gs_free NMConfigDeviceStateData *dev_state = NULL; gs_free NMConfigDeviceStateData *dev_state = NULL;
dev_state = nm_config_device_state_load (nm_config_get (), ifindex); dev_state = nm_config_device_state_load (ifindex);
if ( dev_state if ( dev_state
&& dev_state->perm_hw_addr_fake && dev_state->perm_hw_addr_fake
&& nm_utils_hwaddr_aton (dev_state->perm_hw_addr_fake, buf, priv->hw_addr_len) && nm_utils_hwaddr_aton (dev_state->perm_hw_addr_fake, buf, priv->hw_addr_len)

View File

@@ -149,6 +149,9 @@ nm_main_utils_ensure_rundir ()
exit (1); exit (1);
} }
/* NM_CONFIG_DEVICE_STATE_DIR is used to determine whether NM is restarted or not.
* It is important to set NMConfigCmdLineOptions.first_start before creating
* the directory. */
nm_assert (g_str_has_prefix (NM_CONFIG_DEVICE_STATE_DIR, NMRUNDIR"/")); nm_assert (g_str_has_prefix (NM_CONFIG_DEVICE_STATE_DIR, NMRUNDIR"/"));
if (g_mkdir (NM_CONFIG_DEVICE_STATE_DIR, 0755) != 0) { if (g_mkdir (NM_CONFIG_DEVICE_STATE_DIR, 0755) != 0) {
errsv = errno; errsv = errno;

View File

@@ -239,7 +239,11 @@ main (int argc, char *argv[])
main_loop = g_main_loop_new (NULL, FALSE); main_loop = g_main_loop_new (NULL, FALSE);
config_cli = nm_config_cmd_line_options_new (); /* we determine a first-start (contrary to a restart during the same boot)
* based on the existence of NM_CONFIG_DEVICE_STATE_DIR directory. */
config_cli = nm_config_cmd_line_options_new (!g_file_test (NM_CONFIG_DEVICE_STATE_DIR,
G_FILE_TEST_IS_DIR));
do_early_setup (&argc, &argv, config_cli); do_early_setup (&argc, &argv, config_cli);
if (global_opt.g_fatal_warnings) if (global_opt.g_fatal_warnings)
@@ -356,7 +360,8 @@ main (int argc, char *argv[])
NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY), NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY),
nm_config_get_is_debug (config)); nm_config_get_is_debug (config));
nm_log_info (LOGD_CORE, "NetworkManager (version " NM_DIST_VERSION ") is starting..."); nm_log_info (LOGD_CORE, "NetworkManager (version " NM_DIST_VERSION ") is starting... (%s)",
nm_config_get_first_start (config) ? "for the first time" : "after a restart");
nm_log_info (LOGD_CORE, "Read config: %s", nm_config_data_get_config_description (nm_config_get_data (config))); nm_log_info (LOGD_CORE, "Read config: %s", nm_config_data_get_config_description (nm_config_get_data (config)));
nm_config_data_log (nm_config_get_data (config), "CONFIG: ", " ", NULL); nm_config_data_log (nm_config_get_data (config), "CONFIG: ", " ", NULL);

View File

@@ -60,6 +60,15 @@ struct NMConfigCmdLineOptions {
*/ */
int connectivity_interval; int connectivity_interval;
char *connectivity_response; char *connectivity_response;
/* @first_start is not provided by command line. It is a convenient hack
* to pass in an argument to NMConfig. This makes NMConfigCmdLineOptions a
* misnomer.
*
* It is true, if NM is started the first time -- contrary to a restart
* during the same boot up. That is determined by the content of the
* /var/run/NetworManager state directory. */
bool first_start;
}; };
typedef struct { typedef struct {
@@ -291,6 +300,12 @@ nm_config_get_is_debug (NMConfig *config)
return NM_CONFIG_GET_PRIVATE (config)->cli.is_debug; return NM_CONFIG_GET_PRIVATE (config)->cli.is_debug;
} }
gboolean
nm_config_get_first_start (NMConfig *config)
{
return NM_CONFIG_GET_PRIVATE (config)->cli.first_start;
}
/*****************************************************************************/ /*****************************************************************************/
static char ** static char **
@@ -412,6 +427,7 @@ _nm_config_cmd_line_options_clear (NMConfigCmdLineOptions *cli)
g_clear_pointer (&cli->connectivity_uri, g_free); g_clear_pointer (&cli->connectivity_uri, g_free);
g_clear_pointer (&cli->connectivity_response, g_free); g_clear_pointer (&cli->connectivity_response, g_free);
cli->connectivity_interval = -1; cli->connectivity_interval = -1;
cli->first_start = FALSE;
} }
static void static void
@@ -434,14 +450,18 @@ _nm_config_cmd_line_options_copy (const NMConfigCmdLineOptions *cli, NMConfigCmd
dst->connectivity_uri = g_strdup (cli->connectivity_uri); dst->connectivity_uri = g_strdup (cli->connectivity_uri);
dst->connectivity_response = g_strdup (cli->connectivity_response); dst->connectivity_response = g_strdup (cli->connectivity_response);
dst->connectivity_interval = cli->connectivity_interval; dst->connectivity_interval = cli->connectivity_interval;
dst->first_start = cli->first_start;
} }
NMConfigCmdLineOptions * NMConfigCmdLineOptions *
nm_config_cmd_line_options_new () nm_config_cmd_line_options_new (gboolean first_start)
{ {
NMConfigCmdLineOptions *cli = g_new0 (NMConfigCmdLineOptions, 1); NMConfigCmdLineOptions *cli = g_new0 (NMConfigCmdLineOptions, 1);
_nm_config_cmd_line_options_clear (cli); _nm_config_cmd_line_options_clear (cli);
cli->first_start = first_start;
return cli; return cli;
} }
@@ -1926,15 +1946,13 @@ _config_device_state_data_new (int ifindex, GKeyFile *kf)
/** /**
* nm_config_device_state_load: * nm_config_device_state_load:
* @self: the NMConfig instance
* @ifindex: the ifindex for which the state is to load * @ifindex: the ifindex for which the state is to load
* *
* Returns: (transfer full): a run state object. * Returns: (transfer full): a run state object.
* Must be freed with g_free(). * Must be freed with g_free().
*/ */
NMConfigDeviceStateData * NMConfigDeviceStateData *
nm_config_device_state_load (NMConfig *self, nm_config_device_state_load (int ifindex)
int ifindex)
{ {
NMConfigDeviceStateData *device_state; NMConfigDeviceStateData *device_state;
char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR) + 60]; char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR) + 60];
@@ -1972,8 +1990,7 @@ NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_device_state_managed_type_to_str, NMConfigDe
); );
gboolean gboolean
nm_config_device_state_write (NMConfig *self, nm_config_device_state_write (int ifindex,
int ifindex,
NMConfigDeviceStateManagedType managed, NMConfigDeviceStateManagedType managed,
const char *perm_hw_addr_fake, const char *perm_hw_addr_fake,
const char *connection_uuid) const char *connection_uuid)
@@ -1982,7 +1999,6 @@ nm_config_device_state_write (NMConfig *self,
GError *local = NULL; GError *local = NULL;
gs_unref_keyfile GKeyFile *kf = NULL; gs_unref_keyfile GKeyFile *kf = NULL;
g_return_val_if_fail (NM_IS_CONFIG (self), FALSE);
g_return_val_if_fail (ifindex > 0, FALSE); g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (!connection_uuid || *connection_uuid, FALSE); g_return_val_if_fail (!connection_uuid || *connection_uuid, FALSE);
g_return_val_if_fail (managed == NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED || !connection_uuid, FALSE); g_return_val_if_fail (managed == NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED || !connection_uuid, FALSE);
@@ -2027,8 +2043,7 @@ nm_config_device_state_write (NMConfig *self,
} }
void void
nm_config_device_state_prune_unseen (NMConfig *self, nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes)
GHashTable *seen_ifindexes)
{ {
GDir *dir; GDir *dir;
const char *fn; const char *fn;

View File

@@ -125,13 +125,15 @@ const char *nm_config_get_log_domains (NMConfig *config);
gboolean nm_config_get_configure_and_quit (NMConfig *config); gboolean nm_config_get_configure_and_quit (NMConfig *config);
gboolean nm_config_get_is_debug (NMConfig *config); gboolean nm_config_get_is_debug (NMConfig *config);
gboolean nm_config_get_first_start (NMConfig *config);
void nm_config_set_values (NMConfig *self, void nm_config_set_values (NMConfig *self,
GKeyFile *keyfile_intern_new, GKeyFile *keyfile_intern_new,
gboolean allow_write, gboolean allow_write,
gboolean force_rewrite); gboolean force_rewrite);
/* for main.c only */ /* for main.c only */
NMConfigCmdLineOptions *nm_config_cmd_line_options_new (void); NMConfigCmdLineOptions *nm_config_cmd_line_options_new (gboolean first_start);
void nm_config_cmd_line_options_free (NMConfigCmdLineOptions *cli); void nm_config_cmd_line_options_free (NMConfigCmdLineOptions *cli);
void nm_config_cmd_line_options_add_to_entries (NMConfigCmdLineOptions *cli, void nm_config_cmd_line_options_add_to_entries (NMConfigCmdLineOptions *cli,
GOptionContext *opt_ctx); GOptionContext *opt_ctx);
@@ -204,14 +206,12 @@ struct _NMConfigDeviceStateData {
const char *perm_hw_addr_fake; const char *perm_hw_addr_fake;
}; };
NMConfigDeviceStateData *nm_config_device_state_load (NMConfig *self, NMConfigDeviceStateData *nm_config_device_state_load (int ifindex);
int ifindex); gboolean nm_config_device_state_write (int ifindex,
gboolean nm_config_device_state_write (NMConfig *self,
int ifindex,
NMConfigDeviceStateManagedType managed, NMConfigDeviceStateManagedType managed,
const char *perm_hw_addr_fake, const char *perm_hw_addr_fake,
const char *connection_uuid); const char *connection_uuid);
void nm_config_device_state_prune_unseen (NMConfig *self, GHashTable *seen_ifindexes); void nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes);
/*****************************************************************************/ /*****************************************************************************/

View File

@@ -450,6 +450,8 @@ _get_activatable_connections_filter (NMSettings *settings,
NMSettingsConnection *connection, NMSettingsConnection *connection,
gpointer user_data) 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); return !active_connection_find_first (user_data, connection, NULL, NM_ACTIVE_CONNECTION_STATE_DEACTIVATING);
} }
@@ -1677,16 +1679,12 @@ done:
g_clear_error (&error); 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: * get_existing_connection:
* @manager: #NMManager instance * @manager: #NMManager instance
* @device: #NMDevice 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 * @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 * UUID. If no uuid is given or no matching connection is found, we
* only do external activation. * only do external activation.
@@ -1698,6 +1696,7 @@ match_connection_filter (NMConnection *connection, gpointer user_data)
static NMSettingsConnection * static NMSettingsConnection *
get_existing_connection (NMManager *self, get_existing_connection (NMManager *self,
NMDevice *device, NMDevice *device,
gboolean guess_assume,
const char *assume_connection_uuid, const char *assume_connection_uuid,
gboolean *out_generated) gboolean *out_generated)
{ {
@@ -1708,6 +1707,7 @@ get_existing_connection (NMManager *self,
NMDevice *master = NULL; NMDevice *master = NULL;
int ifindex = nm_device_get_ifindex (device); int ifindex = nm_device_get_ifindex (device);
NMSettingsConnection *matched; NMSettingsConnection *matched;
NMSettingsConnection *connection_checked = NULL;
if (out_generated) if (out_generated)
*out_generated = FALSE; *out_generated = FALSE;
@@ -1752,11 +1752,12 @@ get_existing_connection (NMManager *self,
* the generated connection instead. * the generated connection instead.
*/ */
if ( assume_connection_uuid if ( assume_connection_uuid
&& (matched = nm_settings_get_connection_by_uuid (priv->settings, assume_connection_uuid)) && (connection_checked = nm_settings_get_connection_by_uuid (priv->settings, assume_connection_uuid))
&& !active_connection_find_first (self, matched, NULL, && !active_connection_find_first (self, connection_checked, NULL,
NM_ACTIVE_CONNECTION_STATE_DEACTIVATING)) { NM_ACTIVE_CONNECTION_STATE_DEACTIVATING)
&& nm_device_check_connection_compatible (device, NM_CONNECTION (connection_checked))) {
NMConnection *const connections[] = { NMConnection *const connections[] = {
NM_CONNECTION (matched), NM_CONNECTION (connection_checked),
NULL, NULL,
}; };
@@ -1765,17 +1766,50 @@ get_existing_connection (NMManager *self,
nm_device_has_carrier (device), nm_device_has_carrier (device),
nm_device_get_ip4_route_metric (device), nm_device_get_ip4_route_metric (device),
nm_device_get_ip6_route_metric (device), nm_device_get_ip6_route_metric (device),
match_connection_filter, NULL, NULL));
device)); } else
if (matched) { matched = NULL;
_LOGI (LOGD_DEVICE, "(%s): found matching connection '%s'",
nm_device_get_iface (device), if (!matched && guess_assume) {
nm_settings_connection_get_id (matched)); gs_free NMSettingsConnection **connections = NULL;
g_object_unref (connection); guint len, i, j;
return matched;
/* 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'", _LOGD (LOGD_DEVICE, "(%s): generated connection '%s'",
nm_device_get_iface (device), nm_device_get_iface (device),
nm_connection_get_id (connection)); nm_connection_get_id (connection));
@@ -1803,6 +1837,7 @@ get_existing_connection (NMManager *self,
static gboolean static gboolean
recheck_assume_connection (NMManager *self, recheck_assume_connection (NMManager *self,
NMDevice *device, NMDevice *device,
gboolean guess_assume,
const char *assume_connection_uuid) const char *assume_connection_uuid)
{ {
NMSettingsConnection *connection; 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) if (nm_device_sys_iface_state_get (device) != NM_DEVICE_SYS_IFACE_STATE_EXTERNAL)
return FALSE; 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) { if (!connection) {
_LOGD (LOGD_DEVICE, "(%s): can't assume; no connection", _LOGD (LOGD_DEVICE, "(%s): can't assume; no connection",
nm_device_get_iface (device)); nm_device_get_iface (device));
@@ -1906,7 +1941,7 @@ recheck_assume_connection (NMManager *self,
static void static void
recheck_assume_connection_cb (NMDevice *device, gpointer user_data) 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 static void
@@ -2000,6 +2035,7 @@ static void
_device_realize_finish (NMManager *self, _device_realize_finish (NMManager *self,
NMDevice *device, NMDevice *device,
const NMPlatformLink *plink, const NMPlatformLink *plink,
gboolean guess_assume,
const char *connection_uuid_to_assume) const char *connection_uuid_to_assume)
{ {
g_return_if_fail (NM_IS_MANAGER (self)); g_return_if_fail (NM_IS_MANAGER (self));
@@ -2010,7 +2046,7 @@ _device_realize_finish (NMManager *self,
if (!nm_device_get_managed (device, FALSE)) if (!nm_device_get_managed (device, FALSE))
return; return;
if (recheck_assume_connection (self, device, connection_uuid_to_assume)) if (recheck_assume_connection (self, device, guess_assume, connection_uuid_to_assume))
return; return;
/* if we failed to assume a connection for the managed device, but the device /* 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, NULL,
&error)) { &error)) {
add_device (self, device, NULL); add_device (self, device, NULL);
_device_realize_finish (self, device, NULL, NULL); _device_realize_finish (self, device, NULL, FALSE, NULL);
} else { } else {
_LOGW (LOGD_DEVICE, "(%s): failed to realize device: %s", _LOGW (LOGD_DEVICE, "(%s): failed to realize device: %s",
nm_device_get_iface (device), error->message); nm_device_get_iface (device), error->message);
@@ -2214,6 +2250,7 @@ static void
platform_link_added (NMManager *self, platform_link_added (NMManager *self,
int ifindex, int ifindex,
const NMPlatformLink *plink, const NMPlatformLink *plink,
gboolean guess_assume,
const NMConfigDeviceStateData *dev_state) const NMConfigDeviceStateData *dev_state)
{ {
NMDeviceFactory *factory; NMDeviceFactory *factory;
@@ -2245,7 +2282,7 @@ platform_link_added (NMManager *self,
&compatible, &compatible,
&error)) { &error)) {
/* Success */ /* Success */
_device_realize_finish (self, candidate, plink, NULL); _device_realize_finish (self, candidate, plink, FALSE, NULL);
return; return;
} }
@@ -2317,6 +2354,7 @@ platform_link_added (NMManager *self,
&error)) { &error)) {
add_device (self, device, NULL); add_device (self, device, NULL);
_device_realize_finish (self, device, plink, _device_realize_finish (self, device, plink,
guess_assume,
dev_state ? dev_state->connection_uuid : NULL); dev_state ? dev_state->connection_uuid : NULL);
} else { } else {
_LOGW (LOGD_DEVICE, "%s: failed to realize device: %s", _LOGW (LOGD_DEVICE, "%s: failed to realize device: %s",
@@ -2347,7 +2385,7 @@ _platform_link_cb_idle (PlatformLinkCbData *data)
NMPlatformLink pllink; NMPlatformLink pllink;
pllink = *l; /* make a copy of the link instance */ 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 { } else {
NMDevice *device; NMDevice *device;
GError *error = NULL; GError *error = NULL;
@@ -2404,22 +2442,24 @@ platform_link_cb (NMPlatform *platform,
static void static void
platform_query_devices (NMManager *self) platform_query_devices (NMManager *self)
{ {
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
GArray *links_array; GArray *links_array;
NMPlatformLink *links; NMPlatformLink *links;
int i; 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_array = nm_platform_link_get_all (NM_PLATFORM_GET);
links = (NMPlatformLink *) links_array->data; links = (NMPlatformLink *) links_array->data;
for (i = 0; i < links_array->len; i++) { for (i = 0; i < links_array->len; i++) {
gs_free NMConfigDeviceStateData *dev_state = NULL; gs_free NMConfigDeviceStateData *dev_state = NULL;
dev_state = nm_config_device_state_load (priv->config, dev_state = nm_config_device_state_load (links[i].ifindex);
links[i].ifindex);
platform_link_added (self, platform_link_added (self,
links[i].ifindex, links[i].ifindex,
&links[i], &links[i],
guess_assume && (!dev_state || !dev_state->connection_uuid),
dev_state); dev_state);
} }
@@ -4976,16 +5016,14 @@ nm_manager_write_device_state (NMManager *self)
if (perm_hw_addr_fake && !perm_hw_addr_is_fake) if (perm_hw_addr_fake && !perm_hw_addr_is_fake)
perm_hw_addr_fake = NULL; perm_hw_addr_fake = NULL;
if (nm_config_device_state_write (priv->config, if (nm_config_device_state_write (ifindex,
ifindex,
managed_type, managed_type,
perm_hw_addr_fake, perm_hw_addr_fake,
uuid)) uuid))
g_hash_table_add (seen_ifindexes, GINT_TO_POINTER (ifindex)); g_hash_table_add (seen_ifindexes, GINT_TO_POINTER (ifindex));
} }
nm_config_device_state_prune_unseen (priv->config, nm_config_device_state_prune_unseen (seen_ifindexes);
seen_ifindexes);
} }
static gboolean static gboolean

View File

@@ -97,7 +97,7 @@ setup_config (GError **error, const char *config_file, const char *intern_config
argv = (char **)args->pdata; argv = (char **)args->pdata;
argc = args->len; argc = args->len;
cli = nm_config_cmd_line_options_new (); cli = nm_config_cmd_line_options_new (FALSE);
context = g_option_context_new (NULL); context = g_option_context_new (NULL);
nm_config_cmd_line_options_add_to_entries (cli, context); nm_config_cmd_line_options_add_to_entries (cli, context);