mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-07 13:40:20 +01:00
merge branch 'th/bgo580018_autoconnect_priority'
Add configuration option NMSettingConnection:autoconnect-priority. This new option is only relevant for connections that are set to autoconnect. When having more then one candicate for autoconnect, this new setting allows to always prefer one connection over the other. If both connections have the same priority setting, the previous automatism is used to choose the best candidate. That is, NM will choose the least recently connected candidate. See also the still unresolved but related bug bgo#737356 that asks for providing a different automatism. https://bugzilla.gnome.org/show_bug.cgi?id=580018 Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
commit
a7c8e5c6e9
21 changed files with 360 additions and 93 deletions
|
|
@ -61,15 +61,16 @@ static NmcOutputField nmc_fields_con_show[] = {
|
|||
{"TIMESTAMP", N_("TIMESTAMP"), 12}, /* 3 */
|
||||
{"TIMESTAMP-REAL", N_("TIMESTAMP-REAL"), 34}, /* 4 */
|
||||
{"AUTOCONNECT", N_("AUTOCONNECT"), 13}, /* 5 */
|
||||
{"READONLY", N_("READONLY"), 10}, /* 6 */
|
||||
{"DBUS-PATH", N_("DBUS-PATH"), 42}, /* 7 */
|
||||
{"ACTIVE", N_("ACTIVE"), 10}, /* 8 */
|
||||
{"DEVICE", N_("DEVICE"), 10}, /* 9 */
|
||||
{"STATE", N_("STATE"), 12}, /* 10 */
|
||||
{"ACTIVE-PATH", N_("ACTIVE-PATH"), 51}, /* 11 */
|
||||
{"AUTOCONNECT-PRIORITY", N_("AUTOCONNECT-PRIORITY"), 10}, /* 6 */
|
||||
{"READONLY", N_("READONLY"), 10}, /* 7 */
|
||||
{"DBUS-PATH", N_("DBUS-PATH"), 42}, /* 8 */
|
||||
{"ACTIVE", N_("ACTIVE"), 10}, /* 9 */
|
||||
{"DEVICE", N_("DEVICE"), 10}, /* 10 */
|
||||
{"STATE", N_("STATE"), 12}, /* 11 */
|
||||
{"ACTIVE-PATH", N_("ACTIVE-PATH"), 51}, /* 12 */
|
||||
{NULL, NULL, 0}
|
||||
};
|
||||
#define NMC_FIELDS_CON_SHOW_ALL "NAME,UUID,TYPE,TIMESTAMP,TIMESTAMP-REAL,AUTOCONNECT,READONLY,DBUS-PATH,"\
|
||||
#define NMC_FIELDS_CON_SHOW_ALL "NAME,UUID,TYPE,TIMESTAMP,TIMESTAMP-REAL,AUTOCONNECT,AUTOCONNECT-PRIORITY,READONLY,DBUS-PATH,"\
|
||||
"ACTIVE,DEVICE,STATE,ACTIVE-PATH"
|
||||
#define NMC_FIELDS_CON_SHOW_COMMON "NAME,UUID,TYPE,DEVICE"
|
||||
|
||||
|
|
@ -745,6 +746,7 @@ fill_output_connection (gpointer data, gpointer user_data, gboolean active_only)
|
|||
time_t timestamp_real;
|
||||
char *timestamp_str;
|
||||
char *timestamp_real_str = "";
|
||||
char *prio_str;
|
||||
NmcOutputField *arr;
|
||||
NMActiveConnection *ac = NULL;
|
||||
const char *ac_path = NULL;
|
||||
|
|
@ -772,6 +774,7 @@ fill_output_connection (gpointer data, gpointer user_data, gboolean active_only)
|
|||
timestamp_real_str = g_malloc0 (64);
|
||||
strftime (timestamp_real_str, 64, "%c", localtime (×tamp_real));
|
||||
}
|
||||
prio_str = g_strdup_printf ("%u", nm_setting_connection_get_autoconnect_priority (s_con));
|
||||
|
||||
arr = nmc_dup_fields_array (nmc_fields_con_show,
|
||||
sizeof (nmc_fields_con_show),
|
||||
|
|
@ -782,12 +785,13 @@ fill_output_connection (gpointer data, gpointer user_data, gboolean active_only)
|
|||
set_val_str (arr, 3, timestamp_str);
|
||||
set_val_str (arr, 4, timestamp ? timestamp_real_str : g_strdup (_("never")));
|
||||
set_val_strc (arr, 5, nm_setting_connection_get_autoconnect (s_con) ? _("yes") : _("no"));
|
||||
set_val_strc (arr, 6, nm_setting_connection_get_read_only (s_con) ? _("yes") : _("no"));
|
||||
set_val_strc (arr, 7, nm_connection_get_path (connection));
|
||||
set_val_strc (arr, 8, ac ? _("yes") : _("no"));
|
||||
set_val_str (arr, 9, ac_dev);
|
||||
set_val_strc (arr, 10, ac_state);
|
||||
set_val_strc (arr, 11, ac_path);
|
||||
set_val_str (arr, 6, prio_str);
|
||||
set_val_strc (arr, 7, nm_setting_connection_get_read_only (s_con) ? _("yes") : _("no"));
|
||||
set_val_strc (arr, 8, nm_connection_get_path (connection));
|
||||
set_val_strc (arr, 9, ac ? _("yes") : _("no"));
|
||||
set_val_str (arr, 10, ac_dev);
|
||||
set_val_strc (arr, 11, ac_state);
|
||||
set_val_strc (arr, 12, ac_path);
|
||||
|
||||
g_ptr_array_add (nmc->output_data, arr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,14 +43,15 @@ NmcOutputField nmc_fields_setting_connection[] = {
|
|||
SETTING_FIELD (NM_SETTING_CONNECTION_INTERFACE_NAME, 20), /* 3 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_TYPE, 17), /* 4 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_AUTOCONNECT, 13), /* 5 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_TIMESTAMP, 10), /* 6 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_READ_ONLY, 10), /* 7 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_PERMISSIONS, 30), /* 8 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_ZONE, 10), /* 9 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_MASTER, 20), /* 10 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_SLAVE_TYPE, 20), /* 11 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_SECONDARIES, 40), /* 12 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, 30), /* 13 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, 10), /* 6 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_TIMESTAMP, 10), /* 7 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_READ_ONLY, 10), /* 8 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_PERMISSIONS, 30), /* 9 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_ZONE, 10), /* 10 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_MASTER, 20), /* 11 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_SLAVE_TYPE, 20), /* 12 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_SECONDARIES, 40), /* 13 */
|
||||
SETTING_FIELD (NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, 30), /* 14 */
|
||||
{NULL, NULL, 0, NULL, FALSE, FALSE, 0}
|
||||
};
|
||||
#define NMC_FIELDS_SETTING_CONNECTION_ALL "name"","\
|
||||
|
|
@ -59,6 +60,7 @@ NmcOutputField nmc_fields_setting_connection[] = {
|
|||
NM_SETTING_CONNECTION_INTERFACE_NAME","\
|
||||
NM_SETTING_CONNECTION_TYPE","\
|
||||
NM_SETTING_CONNECTION_AUTOCONNECT","\
|
||||
NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY","\
|
||||
NM_SETTING_CONNECTION_TIMESTAMP","\
|
||||
NM_SETTING_CONNECTION_READ_ONLY","\
|
||||
NM_SETTING_CONNECTION_PERMISSIONS","\
|
||||
|
|
@ -1004,6 +1006,7 @@ DEFINE_GETTER (nmc_property_connection_get_uuid, NM_SETTING_CONNECTION_UUID)
|
|||
DEFINE_GETTER (nmc_property_connection_get_interface_name, NM_SETTING_CONNECTION_INTERFACE_NAME)
|
||||
DEFINE_GETTER (nmc_property_connection_get_type, NM_SETTING_CONNECTION_TYPE)
|
||||
DEFINE_GETTER (nmc_property_connection_get_autoconnect, NM_SETTING_CONNECTION_AUTOCONNECT)
|
||||
DEFINE_GETTER (nmc_property_connection_get_autoconnect_priority, NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY)
|
||||
DEFINE_GETTER (nmc_property_connection_get_timestamp, NM_SETTING_CONNECTION_TIMESTAMP)
|
||||
DEFINE_GETTER (nmc_property_connection_get_read_only, NM_SETTING_CONNECTION_READ_ONLY)
|
||||
|
||||
|
|
@ -2155,7 +2158,27 @@ nmc_property_set_uint (NMSetting *setting, const char *prop, const char *val, GE
|
|||
if (!validate_uint (setting, prop, (guint) val_int, error))
|
||||
return FALSE;
|
||||
|
||||
g_object_set (setting, prop, val_int, NULL);
|
||||
g_object_set (setting, prop, (guint) val_int, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
nmc_property_set_int (NMSetting *setting, const char *prop, const char *val, GError **error)
|
||||
{
|
||||
long int val_int;
|
||||
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
if (!nmc_string_to_int (val, TRUE, G_MININT, G_MAXINT, &val_int)) {
|
||||
g_set_error (error, 1, 0, _("'%s' is not a valid number (or out of range)"), val);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Validate the number according to the property spec */
|
||||
if (!validate_int (setting, prop, (gint) val_int, error))
|
||||
return FALSE;
|
||||
|
||||
g_object_set (setting, prop, (gint) val_int, NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -5115,6 +5138,13 @@ nmc_properties_init (void)
|
|||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
nmc_add_prop_funcs (GLUE (CONNECTION, AUTOCONNECT_PRIORITY),
|
||||
nmc_property_connection_get_autoconnect_priority,
|
||||
nmc_property_set_int,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
nmc_add_prop_funcs (GLUE (CONNECTION, TIMESTAMP),
|
||||
nmc_property_connection_get_timestamp,
|
||||
NULL, /* read-only */
|
||||
|
|
@ -6482,14 +6512,15 @@ setting_connection_details (NMSetting *setting, NmCli *nmc, const char *one_prop
|
|||
set_val_str (arr, 3, nmc_property_connection_get_interface_name (setting));
|
||||
set_val_str (arr, 4, nmc_property_connection_get_type (setting));
|
||||
set_val_str (arr, 5, nmc_property_connection_get_autoconnect (setting));
|
||||
set_val_str (arr, 6, nmc_property_connection_get_timestamp (setting));
|
||||
set_val_str (arr, 7, nmc_property_connection_get_read_only (setting));
|
||||
set_val_str (arr, 8, nmc_property_connection_get_permissions (setting));
|
||||
set_val_str (arr, 9, nmc_property_connection_get_zone (setting));
|
||||
set_val_str (arr, 10, nmc_property_connection_get_master (setting));
|
||||
set_val_str (arr, 11, nmc_property_connection_get_slave_type (setting));
|
||||
set_val_str (arr, 12, nmc_property_connection_get_secondaries (setting));
|
||||
set_val_str (arr, 13, nmc_property_connection_get_gateway_ping_timeout (setting));
|
||||
set_val_str (arr, 6, nmc_property_connection_get_autoconnect_priority (setting));
|
||||
set_val_str (arr, 7, nmc_property_connection_get_timestamp (setting));
|
||||
set_val_str (arr, 8, nmc_property_connection_get_read_only (setting));
|
||||
set_val_str (arr, 9, nmc_property_connection_get_permissions (setting));
|
||||
set_val_str (arr, 10, nmc_property_connection_get_zone (setting));
|
||||
set_val_str (arr, 11, nmc_property_connection_get_master (setting));
|
||||
set_val_str (arr, 12, nmc_property_connection_get_slave_type (setting));
|
||||
set_val_str (arr, 13, nmc_property_connection_get_secondaries (setting));
|
||||
set_val_str (arr, 14, nmc_property_connection_get_gateway_ping_timeout (setting));
|
||||
g_ptr_array_add (nmc->output_data, arr);
|
||||
|
||||
print_data (nmc); /* Print all data */
|
||||
|
|
|
|||
|
|
@ -871,9 +871,8 @@ nmtst_assert_connection_verifies_without_normalization (NMConnection *con)
|
|||
success = nm_connection_normalize (con, NULL, &was_modified, &error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (success);
|
||||
g_assert (!was_modified);
|
||||
|
||||
nmtst_assert_connection_equals (con, FALSE, clone, FALSE);
|
||||
g_assert (!was_modified);
|
||||
}
|
||||
|
||||
inline static void
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ typedef struct {
|
|||
char *slave_type;
|
||||
GSList *permissions; /* list of Permission structs */
|
||||
gboolean autoconnect;
|
||||
gint autoconnect_priority;
|
||||
guint64 timestamp;
|
||||
gboolean read_only;
|
||||
char *zone;
|
||||
|
|
@ -95,6 +96,7 @@ enum {
|
|||
PROP_TYPE,
|
||||
PROP_PERMISSIONS,
|
||||
PROP_AUTOCONNECT,
|
||||
PROP_AUTOCONNECT_PRIORITY,
|
||||
PROP_TIMESTAMP,
|
||||
PROP_READ_ONLY,
|
||||
PROP_ZONE,
|
||||
|
|
@ -497,6 +499,23 @@ nm_setting_connection_get_autoconnect (NMSettingConnection *setting)
|
|||
return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->autoconnect;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_connection_get_autoconnect_priority:
|
||||
* @setting: the #NMSettingConnection
|
||||
*
|
||||
* Returns the #NMSettingConnection:autoconnect-priority property of the connection.
|
||||
* The higher number, the higher priority.
|
||||
*
|
||||
* Returns: the connection's autoconnect priority
|
||||
**/
|
||||
gint
|
||||
nm_setting_connection_get_autoconnect_priority (NMSettingConnection *setting)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), 0);
|
||||
|
||||
return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->autoconnect_priority;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_setting_connection_get_timestamp:
|
||||
* @setting: the #NMSettingConnection
|
||||
|
|
@ -1094,6 +1113,9 @@ set_property (GObject *object, guint prop_id,
|
|||
case PROP_AUTOCONNECT:
|
||||
priv->autoconnect = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_AUTOCONNECT_PRIORITY:
|
||||
priv->autoconnect_priority = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_TIMESTAMP:
|
||||
priv->timestamp = g_value_get_uint64 (value);
|
||||
break;
|
||||
|
|
@ -1165,6 +1187,9 @@ get_property (GObject *object, guint prop_id,
|
|||
case PROP_AUTOCONNECT:
|
||||
g_value_set_boolean (value, nm_setting_connection_get_autoconnect (setting));
|
||||
break;
|
||||
case PROP_AUTOCONNECT_PRIORITY:
|
||||
g_value_set_int (value, nm_setting_connection_get_autoconnect_priority (setting));
|
||||
break;
|
||||
case PROP_TIMESTAMP:
|
||||
g_value_set_uint64 (value, nm_setting_connection_get_timestamp (setting));
|
||||
break;
|
||||
|
|
@ -1331,6 +1356,24 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
|
|||
NM_SETTING_PARAM_FUZZY_IGNORE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* NMSettingConnection:autoconnect-priority:
|
||||
*
|
||||
* The autoconnect priority. If the connection is set to autoconnect,
|
||||
* connections with higher priority will be preferred. Defaults to 0.
|
||||
* The higher number means higher priority.
|
||||
**/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_AUTOCONNECT_PRIORITY,
|
||||
g_param_spec_int (NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, "", "",
|
||||
NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MIN,
|
||||
NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MAX,
|
||||
NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT |
|
||||
NM_SETTING_PARAM_FUZZY_IGNORE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* NMSettingConnection:timestamp:
|
||||
*
|
||||
|
|
|
|||
|
|
@ -72,11 +72,16 @@ typedef enum
|
|||
#define NM_SETTING_CONNECTION_ERROR nm_setting_connection_error_quark ()
|
||||
GQuark nm_setting_connection_error_quark (void);
|
||||
|
||||
#define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MIN -999
|
||||
#define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MAX 999
|
||||
#define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT 0
|
||||
|
||||
#define NM_SETTING_CONNECTION_ID "id"
|
||||
#define NM_SETTING_CONNECTION_UUID "uuid"
|
||||
#define NM_SETTING_CONNECTION_INTERFACE_NAME "interface-name"
|
||||
#define NM_SETTING_CONNECTION_TYPE "type"
|
||||
#define NM_SETTING_CONNECTION_AUTOCONNECT "autoconnect"
|
||||
#define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY "autoconnect-priority"
|
||||
#define NM_SETTING_CONNECTION_TIMESTAMP "timestamp"
|
||||
#define NM_SETTING_CONNECTION_READ_ONLY "read-only"
|
||||
#define NM_SETTING_CONNECTION_PERMISSIONS "permissions"
|
||||
|
|
@ -111,6 +116,7 @@ const char *nm_setting_connection_get_uuid (NMSettingConnection *set
|
|||
const char *nm_setting_connection_get_interface_name (NMSettingConnection *setting);
|
||||
const char *nm_setting_connection_get_connection_type (NMSettingConnection *setting);
|
||||
gboolean nm_setting_connection_get_autoconnect (NMSettingConnection *setting);
|
||||
gint nm_setting_connection_get_autoconnect_priority (NMSettingConnection *setting);
|
||||
guint64 nm_setting_connection_get_timestamp (NMSettingConnection *setting);
|
||||
gboolean nm_setting_connection_get_read_only (NMSettingConnection *setting);
|
||||
|
||||
|
|
|
|||
|
|
@ -552,7 +552,7 @@ _nm_utils_copy_slist_to_array (const GSList *list,
|
|||
|
||||
array = g_ptr_array_new_with_free_func (unref_func);
|
||||
for (iter = list; iter; iter = iter->next)
|
||||
g_ptr_array_add (array, copy_func (iter->data));
|
||||
g_ptr_array_add (array, copy_func ? copy_func (iter->data) : iter->data);
|
||||
return array;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1599,6 +1599,7 @@ test_connection_diff_a_only (void)
|
|||
{ NM_SETTING_CONNECTION_TYPE, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
{ NM_SETTING_CONNECTION_TIMESTAMP, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
{ NM_SETTING_CONNECTION_AUTOCONNECT, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
{ NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
{ NM_SETTING_CONNECTION_READ_ONLY, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
{ NM_SETTING_CONNECTION_PERMISSIONS, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
{ NM_SETTING_CONNECTION_ZONE, NM_SETTING_DIFF_RESULT_IN_A },
|
||||
|
|
|
|||
|
|
@ -530,6 +530,7 @@ global:
|
|||
nm_setting_connection_error_get_type;
|
||||
nm_setting_connection_error_quark;
|
||||
nm_setting_connection_get_autoconnect;
|
||||
nm_setting_connection_get_autoconnect_priority;
|
||||
nm_setting_connection_get_connection_type;
|
||||
nm_setting_connection_get_gateway_ping_timeout;
|
||||
nm_setting_connection_get_id;
|
||||
|
|
|
|||
|
|
@ -1634,6 +1634,31 @@ nm_utils_match_connection (GSList *connections,
|
|||
return best_match;
|
||||
}
|
||||
|
||||
int
|
||||
nm_utils_cmp_connection_by_autoconnect_priority (NMConnection **a, NMConnection **b)
|
||||
{
|
||||
NMSettingConnection *a_s_con, *b_s_con;
|
||||
gboolean a_ac, b_ac;
|
||||
gint a_ap, b_ap;
|
||||
|
||||
a_s_con = nm_connection_get_setting_connection (*a);
|
||||
b_s_con = nm_connection_get_setting_connection (*b);
|
||||
|
||||
a_ac = !!nm_setting_connection_get_autoconnect (a_s_con);
|
||||
b_ac = !!nm_setting_connection_get_autoconnect (b_s_con);
|
||||
if (a_ac != b_ac)
|
||||
return ((int) b_ac) - ((int) a_ac);
|
||||
if (!a_ac)
|
||||
return 0;
|
||||
|
||||
a_ap = nm_setting_connection_get_autoconnect_priority (a_s_con);
|
||||
b_ap = nm_setting_connection_get_autoconnect_priority (b_s_con);
|
||||
if (a_ap != b_ap)
|
||||
return (a_ap > b_ap) ? -1 : 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* nm_utils_ascii_str_to_int64:
|
||||
*
|
||||
* A wrapper for g_ascii_strtoll, that checks whether the whole string
|
||||
|
|
|
|||
|
|
@ -138,6 +138,8 @@ NMConnection *nm_utils_match_connection (GSList *connections,
|
|||
NMUtilsMatchFilterFunc match_filter_func,
|
||||
gpointer match_filter_data);
|
||||
|
||||
int nm_utils_cmp_connection_by_autoconnect_priority (NMConnection **a, NMConnection **b);
|
||||
|
||||
gint64 nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback);
|
||||
|
||||
#define NM_UTILS_NS_PER_SECOND ((gint64) 1000000000)
|
||||
|
|
|
|||
|
|
@ -1640,6 +1640,34 @@ can_auto_connect (NMDevice *self,
|
|||
return nm_device_connection_is_available (self, connection, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_can_auto_connect:
|
||||
* @self: an #NMDevice
|
||||
* @connection: a #NMConnection
|
||||
* @specific_object: (out) (transfer full): on output, the path of an
|
||||
* object associated with the returned connection, to be passed to
|
||||
* nm_manager_activate_connection(), or %NULL.
|
||||
*
|
||||
* Checks if @connection can be auto-activated on @self right now.
|
||||
* This requires, at a minimum, that the connection be compatible with
|
||||
* @self, and that it have the #NMSettingConnection:autoconnect property
|
||||
* set. Some devices impose additional requirements. (Eg, a Wi-Fi connection
|
||||
* can only be activated if its SSID was seen in the last scan.)
|
||||
*
|
||||
* Returns: %TRUE, if the @connection can be auto-activated.
|
||||
**/
|
||||
gboolean
|
||||
nm_device_can_auto_connect (NMDevice *self,
|
||||
NMConnection *connection,
|
||||
char **specific_object)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
|
||||
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
|
||||
g_return_val_if_fail (specific_object && !*specific_object, FALSE);
|
||||
|
||||
return NM_DEVICE_GET_CLASS (self)->can_auto_connect (self, connection, specific_object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
device_has_config (NMDevice *self)
|
||||
{
|
||||
|
|
@ -1796,46 +1824,6 @@ nm_device_generate_connection (NMDevice *self, NMDevice *master)
|
|||
return connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_get_best_auto_connection:
|
||||
* @self: an #NMDevice
|
||||
* @connections: (element-type #NMConnection): a list of connections
|
||||
* @specific_object: (out) (transfer full): on output, the path of an
|
||||
* object associated with the returned connection, to be passed to
|
||||
* nm_manager_activate_connection(), or %NULL.
|
||||
*
|
||||
* Looks through @connections to see if there is a connection that can
|
||||
* be auto-activated on @self right now. This requires, at a minimum,
|
||||
* that the connection be compatible with @self, and that it have the
|
||||
* #NMSettingConnection:autoconnect property set. Some devices impose
|
||||
* additional requirements. (Eg, a Wi-Fi connection can only be
|
||||
* activated if its SSID was seen in the last scan.)
|
||||
*
|
||||
* Returns: an auto-activatable #NMConnection, or %NULL if none are
|
||||
* available.
|
||||
*/
|
||||
|
||||
NMConnection *
|
||||
nm_device_get_best_auto_connection (NMDevice *self,
|
||||
GSList *connections,
|
||||
char **specific_object)
|
||||
{
|
||||
GSList *iter;
|
||||
|
||||
g_return_val_if_fail (NM_IS_DEVICE (self), NULL);
|
||||
g_return_val_if_fail (specific_object != NULL, NULL);
|
||||
g_return_val_if_fail (*specific_object == NULL, NULL);
|
||||
|
||||
for (iter = connections; iter; iter = iter->next) {
|
||||
NMConnection *connection = NM_CONNECTION (iter->data);
|
||||
|
||||
if (NM_DEVICE_GET_CLASS (self)->can_auto_connect (self, connection, specific_object))
|
||||
return connection;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_device_complete_connection (NMDevice *self,
|
||||
NMConnection *connection,
|
||||
|
|
|
|||
|
|
@ -269,9 +269,9 @@ gboolean nm_device_master_update_slave_connection (NMDevice *master,
|
|||
NMConnection *connection,
|
||||
GError **error);
|
||||
|
||||
NMConnection * nm_device_get_best_auto_connection (NMDevice *dev,
|
||||
GSList *connections,
|
||||
char **specific_object);
|
||||
gboolean nm_device_can_auto_connect (NMDevice *self,
|
||||
NMConnection *connection,
|
||||
char **specific_object);
|
||||
|
||||
gboolean nm_device_complete_connection (NMDevice *device,
|
||||
NMConnection *connection,
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "nm-firewall-manager.h"
|
||||
#include "nm-dispatcher.h"
|
||||
#include "nm-utils.h"
|
||||
#include "nm-core-internal.h"
|
||||
#include "nm-glib-compat.h"
|
||||
#include "nm-manager.h"
|
||||
#include "nm-settings.h"
|
||||
|
|
@ -990,7 +991,9 @@ auto_activate_device (gpointer user_data)
|
|||
NMPolicyPrivate *priv;
|
||||
NMConnection *best_connection;
|
||||
char *specific_object = NULL;
|
||||
GSList *connections, *iter;
|
||||
GPtrArray *connections;
|
||||
GSList *connection_list;
|
||||
guint i;
|
||||
|
||||
g_assert (data);
|
||||
policy = data->policy;
|
||||
|
|
@ -1005,20 +1008,31 @@ auto_activate_device (gpointer user_data)
|
|||
if (nm_device_get_act_request (data->device))
|
||||
goto out;
|
||||
|
||||
iter = connections = nm_manager_get_activatable_connections (priv->manager);
|
||||
connection_list = nm_manager_get_activatable_connections (priv->manager);
|
||||
if (!connection_list)
|
||||
goto out;
|
||||
|
||||
/* Remove connections that shouldn't be auto-activated */
|
||||
while (iter) {
|
||||
NMSettingsConnection *candidate = NM_SETTINGS_CONNECTION (iter->data);
|
||||
connections = _nm_utils_copy_slist_to_array (connection_list, NULL, NULL);
|
||||
g_slist_free (connection_list);
|
||||
|
||||
/* Grab next item before we possibly delete the current item */
|
||||
iter = g_slist_next (iter);
|
||||
/* sort is stable (which is important at this point) so that connections
|
||||
* with same priority are still sorted by last-connected-timestamp. */
|
||||
g_ptr_array_sort (connections, (GCompareFunc) nm_utils_cmp_connection_by_autoconnect_priority);
|
||||
|
||||
/* Find the first connection that should be auto-activated */
|
||||
best_connection = NULL;
|
||||
for (i = 0; i < connections->len; i++) {
|
||||
NMSettingsConnection *candidate = NM_SETTINGS_CONNECTION (connections->pdata[i]);
|
||||
|
||||
if (!nm_settings_connection_can_autoconnect (candidate))
|
||||
connections = g_slist_remove (connections, candidate);
|
||||
continue;
|
||||
if (nm_device_can_auto_connect (data->device, (NMConnection *) candidate, &specific_object)) {
|
||||
best_connection = (NMConnection *) candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_ptr_array_free (connections, TRUE);
|
||||
|
||||
best_connection = nm_device_get_best_auto_connection (data->device, connections, &specific_object);
|
||||
if (best_connection) {
|
||||
GError *error = NULL;
|
||||
NMAuthSubject *subject;
|
||||
|
|
@ -1041,8 +1055,6 @@ auto_activate_device (gpointer user_data)
|
|||
g_object_unref (subject);
|
||||
}
|
||||
|
||||
g_slist_free (connections);
|
||||
|
||||
out:
|
||||
activate_data_free (data);
|
||||
return G_SOURCE_REMOVE;
|
||||
|
|
|
|||
|
|
@ -326,17 +326,17 @@ connection_sort (gconstpointer pa, gconstpointer pb)
|
|||
NMConnection *b = NM_CONNECTION (pb);
|
||||
NMSettingConnection *con_b;
|
||||
guint64 ts_a = 0, ts_b = 0;
|
||||
gboolean can_ac_a, can_ac_b;
|
||||
|
||||
con_a = nm_connection_get_setting_connection (a);
|
||||
g_assert (con_a);
|
||||
con_b = nm_connection_get_setting_connection (b);
|
||||
g_assert (con_b);
|
||||
|
||||
if (nm_setting_connection_get_autoconnect (con_a) != nm_setting_connection_get_autoconnect (con_b)) {
|
||||
if (nm_setting_connection_get_autoconnect (con_a))
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
can_ac_a = !!nm_setting_connection_get_autoconnect (con_a);
|
||||
can_ac_b = !!nm_setting_connection_get_autoconnect (con_b);
|
||||
if (can_ac_a != can_ac_b)
|
||||
return can_ac_a ? -1 : 1;
|
||||
|
||||
nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (pa), &ts_a);
|
||||
nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (pb), &ts_b);
|
||||
|
|
|
|||
|
|
@ -169,8 +169,14 @@ make_connection_setting (const char *file,
|
|||
}
|
||||
|
||||
/* Missing ONBOOT is treated as "ONBOOT=true" by the old network service */
|
||||
g_object_set (s_con, NM_SETTING_CONNECTION_AUTOCONNECT,
|
||||
g_object_set (s_con,
|
||||
NM_SETTING_CONNECTION_AUTOCONNECT,
|
||||
svTrueValue (ifcfg, "ONBOOT", TRUE),
|
||||
NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY,
|
||||
(gint) svGetValueInt64 (ifcfg, "AUTOCONNECT_PRIORITY", 10,
|
||||
NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MIN,
|
||||
NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MAX,
|
||||
NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT),
|
||||
NULL);
|
||||
|
||||
value = svGetValue (ifcfg, "USERS", FALSE);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,11 @@
|
|||
|
||||
#include "shvar.h"
|
||||
|
||||
#include "NetworkManagerUtils.h"
|
||||
#include "nm-logging.h"
|
||||
|
||||
#define PARSE_WARNING(msg...) nm_log_warn (LOGD_SETTINGS, " " msg)
|
||||
|
||||
/* Open the file <name>, returning a shvarFile on success and NULL on failure.
|
||||
* Add a wrinkle to let the caller specify whether or not to create the file
|
||||
* (actually, return a structure anyway) if it doesn't exist.
|
||||
|
|
@ -306,6 +311,38 @@ svTrueValue (shvarFile *s, const char *key, gboolean def)
|
|||
return returnValue;
|
||||
}
|
||||
|
||||
/* svGetValueInt64:
|
||||
* @s: fhe file
|
||||
* @key: the name of the key to read
|
||||
* @base: the numeric base (usually 10). Setting to 0 means "auto". Usually you want 10.
|
||||
* @min: the minimum for range-check
|
||||
* @max: the maximum for range-check
|
||||
* @fallback: the fallback value in any error case
|
||||
*
|
||||
* Reads a value @key and converts it to an integer using nm_utils_ascii_str_to_int64().
|
||||
* In case of error, @errno will be set and @fallback returned. */
|
||||
gint64
|
||||
svGetValueInt64 (shvarFile *s, const char *key, guint base, gint64 min, gint64 max, gint64 fallback)
|
||||
{
|
||||
char *tmp;
|
||||
gint64 result;
|
||||
int errsv;
|
||||
|
||||
tmp = svGetValue (s, key, FALSE);
|
||||
if (!tmp) {
|
||||
errno = 0;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
result = nm_utils_ascii_str_to_int64 (tmp, base, min, max, fallback);
|
||||
errsv = errno;
|
||||
if (errsv != 0)
|
||||
PARSE_WARNING ("Error reading '%s' value '%s' as integer (%d)", key, tmp, errsv);
|
||||
|
||||
g_free (tmp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Set the variable <key> equal to the value <value>.
|
||||
* If <key> does not exist, and the <current> pointer is set, append
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ char *svGetValue (shvarFile *s, const char *key, gboolean verbatim);
|
|||
*/
|
||||
gboolean svTrueValue (shvarFile *s, const char *key, gboolean def);
|
||||
|
||||
gint64 svGetValueInt64 (shvarFile *s, const char *key, guint base, gint64 min, gint64 max, gint64 fallback);
|
||||
|
||||
/* Set the variable <key> equal to the value <value>.
|
||||
* If <key> does not exist, and the <current> pointer is set, append
|
||||
* the key=value pair after that line. Otherwise, prepend the pair
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ DEVICE=eth2
|
|||
HWADDR=00:16:41:11:22:33
|
||||
NM_CONTROLLED=yes
|
||||
BOOTPROTO=dhcp
|
||||
AUTOCONNECT_PRIORITY=-1
|
||||
ESSID=blahblah
|
||||
CHANNEL=1
|
||||
MODE=Managed
|
||||
|
|
|
|||
|
|
@ -2910,6 +2910,8 @@ test_read_wifi_open (void)
|
|||
NM_SETTING_CONNECTION_SETTING_NAME,
|
||||
NM_SETTING_CONNECTION_AUTOCONNECT);
|
||||
|
||||
g_assert_cmpint (nm_setting_connection_get_autoconnect_priority (s_con), ==, -1);
|
||||
|
||||
/* ===== WIRELESS SETTING ===== */
|
||||
|
||||
s_wireless = nm_connection_get_setting_wireless (connection);
|
||||
|
|
|
|||
|
|
@ -1664,6 +1664,7 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg)
|
|||
GString *str;
|
||||
const char *master;
|
||||
char *tmp;
|
||||
gint i_int;
|
||||
|
||||
svSetValue (ifcfg, "NAME", nm_setting_connection_get_id (s_con), FALSE);
|
||||
svSetValue (ifcfg, "UUID", nm_setting_connection_get_uuid (s_con), FALSE);
|
||||
|
|
@ -1672,6 +1673,12 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg)
|
|||
nm_setting_connection_get_autoconnect (s_con) ? "yes" : "no",
|
||||
FALSE);
|
||||
|
||||
i_int = nm_setting_connection_get_autoconnect_priority (s_con);
|
||||
tmp = i_int != NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT
|
||||
? g_strdup_printf ("%d", i_int) : NULL;
|
||||
svSetValue (ifcfg, "AUTOCONNECT_PRIORITY", tmp, FALSE);
|
||||
g_free (tmp);
|
||||
|
||||
/* Permissions */
|
||||
svSetValue (ifcfg, "USERS", NULL, FALSE);
|
||||
n = nm_setting_connection_get_num_permissions (s_con);
|
||||
|
|
|
|||
|
|
@ -581,6 +581,104 @@ test_connection_no_match_ip4_addr (void)
|
|||
g_object_unref (copy);
|
||||
}
|
||||
|
||||
static NMConnection *
|
||||
_create_connection_autoconnect (const char *id, gboolean autoconnect, int autoconnect_priority)
|
||||
{
|
||||
NMConnection *c;
|
||||
NMSettingConnection *s_con;
|
||||
|
||||
c = nmtst_create_minimal_connection (id, NULL, NM_SETTING_WIRED_SETTING_NAME, &s_con);
|
||||
g_object_set (s_con,
|
||||
NM_SETTING_CONNECTION_AUTOCONNECT, autoconnect,
|
||||
NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, autoconnect_priority,
|
||||
NULL);
|
||||
nmtst_connection_normalize (c);
|
||||
return c;
|
||||
}
|
||||
|
||||
static void
|
||||
_test_connection_sort_autoconnect_priority_one (NMConnection **list, gboolean shuffle)
|
||||
{
|
||||
int i, j;
|
||||
int count = 0;
|
||||
gs_unref_ptrarray GPtrArray *connections = g_ptr_array_new ();
|
||||
|
||||
while (list[count])
|
||||
count++;
|
||||
g_assert (count > 1);
|
||||
|
||||
/* copy the list of connections over to @connections and shuffle. */
|
||||
for (i = 0; i < count; i++)
|
||||
g_ptr_array_add (connections, list[i]);
|
||||
if (shuffle) {
|
||||
for (i = count - 1; i > 0; i--) {
|
||||
j = g_rand_int (nmtst_get_rand ()) % (i + 1);
|
||||
NMTST_SWAP (connections->pdata[i], connections->pdata[j]);
|
||||
}
|
||||
}
|
||||
|
||||
/* sort it... */
|
||||
g_ptr_array_sort (connections, (GCompareFunc) nm_utils_cmp_connection_by_autoconnect_priority);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (list[i] == connections->pdata[i])
|
||||
continue;
|
||||
if (shuffle && nm_utils_cmp_connection_by_autoconnect_priority (&list[i], (NMConnection **) &connections->pdata[i]) == 0)
|
||||
continue;
|
||||
g_message ("After sorting, the order of connections is not as expected!! Offending index: %d", i);
|
||||
for (j = 0; j < count; j++)
|
||||
g_message (" %3d: %p/%-20s - %p/%-20s", j, list[j], nm_connection_get_id (list[j]), connections->pdata[j], nm_connection_get_id (connections->pdata[j]));
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_test_connection_sort_autoconnect_priority_free (NMConnection **list)
|
||||
{
|
||||
while (*list) {
|
||||
g_object_unref (*list);
|
||||
*list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
test_connection_sort_autoconnect_priority (void)
|
||||
{
|
||||
NMConnection *c1[] = {
|
||||
_create_connection_autoconnect ("AC/100", TRUE, 100),
|
||||
_create_connection_autoconnect ("AC/100", TRUE, 100),
|
||||
_create_connection_autoconnect ("AC/99", TRUE, 99),
|
||||
_create_connection_autoconnect ("AC/0", TRUE, 0),
|
||||
_create_connection_autoconnect ("AC/0", TRUE, 0),
|
||||
_create_connection_autoconnect ("AC/-1", TRUE, -1),
|
||||
_create_connection_autoconnect ("AC/-3", TRUE, -3),
|
||||
_create_connection_autoconnect ("ac/0", FALSE, 0),
|
||||
_create_connection_autoconnect ("ac/0", FALSE, 0),
|
||||
_create_connection_autoconnect ("ac/1", FALSE, 1),
|
||||
_create_connection_autoconnect ("ac/-1", FALSE, -1),
|
||||
_create_connection_autoconnect ("ac/1", FALSE, 1),
|
||||
_create_connection_autoconnect ("ac/0", FALSE, 0),
|
||||
NULL,
|
||||
};
|
||||
NMConnection *c2[] = {
|
||||
_create_connection_autoconnect ("AC/100", TRUE, 100),
|
||||
_create_connection_autoconnect ("AC/99", TRUE, 99),
|
||||
_create_connection_autoconnect ("AC/0", TRUE, 0),
|
||||
_create_connection_autoconnect ("AC/-1", TRUE, -1),
|
||||
_create_connection_autoconnect ("AC/-3", TRUE, -3),
|
||||
_create_connection_autoconnect ("ac/0", FALSE, 0),
|
||||
NULL,
|
||||
};
|
||||
|
||||
_test_connection_sort_autoconnect_priority_one (c1, FALSE);
|
||||
_test_connection_sort_autoconnect_priority_one (c2, FALSE);
|
||||
_test_connection_sort_autoconnect_priority_one (c1, TRUE);
|
||||
_test_connection_sort_autoconnect_priority_one (c2, TRUE);
|
||||
|
||||
_test_connection_sort_autoconnect_priority_free (c1);
|
||||
_test_connection_sort_autoconnect_priority_free (c2);
|
||||
}
|
||||
|
||||
/*******************************************/
|
||||
|
||||
NMTST_DEFINE ();
|
||||
|
|
@ -602,6 +700,8 @@ main (int argc, char **argv)
|
|||
g_test_add_func ("/general/connection-match/wired", test_connection_match_wired);
|
||||
g_test_add_func ("/general/connection-match/no-match-ip4-addr", test_connection_no_match_ip4_addr);
|
||||
|
||||
g_test_add_func ("/general/connection-sort/autoconnect-priority", test_connection_sort_autoconnect_priority);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue