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;
dev_state = nm_config_device_state_load (nm_config_get (), ifindex);
dev_state = nm_config_device_state_load (ifindex);
if ( dev_state
&& dev_state->perm_hw_addr_fake
&& 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);
}
/* 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"/"));
if (g_mkdir (NM_CONFIG_DEVICE_STATE_DIR, 0755) != 0) {
errsv = errno;

View File

@@ -239,7 +239,11 @@ main (int argc, char *argv[])
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);
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_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_config_data_log (nm_config_get_data (config), "CONFIG: ", " ", NULL);

View File

@@ -60,6 +60,15 @@ struct NMConfigCmdLineOptions {
*/
int connectivity_interval;
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 {
@@ -291,6 +300,12 @@ nm_config_get_is_debug (NMConfig *config)
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 **
@@ -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_response, g_free);
cli->connectivity_interval = -1;
cli->first_start = FALSE;
}
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_response = g_strdup (cli->connectivity_response);
dst->connectivity_interval = cli->connectivity_interval;
dst->first_start = cli->first_start;
}
NMConfigCmdLineOptions *
nm_config_cmd_line_options_new ()
nm_config_cmd_line_options_new (gboolean first_start)
{
NMConfigCmdLineOptions *cli = g_new0 (NMConfigCmdLineOptions, 1);
_nm_config_cmd_line_options_clear (cli);
cli->first_start = first_start;
return cli;
}
@@ -1926,15 +1946,13 @@ _config_device_state_data_new (int ifindex, GKeyFile *kf)
/**
* nm_config_device_state_load:
* @self: the NMConfig instance
* @ifindex: the ifindex for which the state is to load
*
* Returns: (transfer full): a run state object.
* Must be freed with g_free().
*/
NMConfigDeviceStateData *
nm_config_device_state_load (NMConfig *self,
int ifindex)
nm_config_device_state_load (int ifindex)
{
NMConfigDeviceStateData *device_state;
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
nm_config_device_state_write (NMConfig *self,
int ifindex,
nm_config_device_state_write (int ifindex,
NMConfigDeviceStateManagedType managed,
const char *perm_hw_addr_fake,
const char *connection_uuid)
@@ -1982,7 +1999,6 @@ nm_config_device_state_write (NMConfig *self,
GError *local = 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 (!connection_uuid || *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
nm_config_device_state_prune_unseen (NMConfig *self,
GHashTable *seen_ifindexes)
nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes)
{
GDir *dir;
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_is_debug (NMConfig *config);
gboolean nm_config_get_first_start (NMConfig *config);
void nm_config_set_values (NMConfig *self,
GKeyFile *keyfile_intern_new,
gboolean allow_write,
gboolean force_rewrite);
/* 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_add_to_entries (NMConfigCmdLineOptions *cli,
GOptionContext *opt_ctx);
@@ -204,14 +206,12 @@ struct _NMConfigDeviceStateData {
const char *perm_hw_addr_fake;
};
NMConfigDeviceStateData *nm_config_device_state_load (NMConfig *self,
int ifindex);
gboolean nm_config_device_state_write (NMConfig *self,
int ifindex,
NMConfigDeviceStateData *nm_config_device_state_load (int ifindex);
gboolean nm_config_device_state_write (int ifindex,
NMConfigDeviceStateManagedType managed,
const char *perm_hw_addr_fake,
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,
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,16 +1766,49 @@ 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));
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'",
_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_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),
@@ -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;
@@ -2404,22 +2442,24 @@ platform_link_cb (NMPlatform *platform,
static void
platform_query_devices (NMManager *self)
{
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (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;
for (i = 0; i < links_array->len; i++) {
gs_free NMConfigDeviceStateData *dev_state = NULL;
dev_state = nm_config_device_state_load (priv->config,
links[i].ifindex);
dev_state = nm_config_device_state_load (links[i].ifindex);
platform_link_added (self,
links[i].ifindex,
&links[i],
guess_assume && (!dev_state || !dev_state->connection_uuid),
dev_state);
}
@@ -4976,16 +5016,14 @@ nm_manager_write_device_state (NMManager *self)
if (perm_hw_addr_fake && !perm_hw_addr_is_fake)
perm_hw_addr_fake = NULL;
if (nm_config_device_state_write (priv->config,
ifindex,
if (nm_config_device_state_write (ifindex,
managed_type,
perm_hw_addr_fake,
uuid))
g_hash_table_add (seen_ifindexes, GINT_TO_POINTER (ifindex));
}
nm_config_device_state_prune_unseen (priv->config,
seen_ifindexes);
nm_config_device_state_prune_unseen (seen_ifindexes);
}
static gboolean

View File

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