mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-15 12:34:55 +00:00
core: merge branch 'th/device-route-metric-rh1505893'
https://bugzilla.redhat.com/show_bug.cgi?id=1505893
This commit is contained in:
commit
b2273ce3dd
|
@ -241,7 +241,13 @@ GPtrArray *_nm_utils_copy_object_array (const GPtrArray *array);
|
|||
|
||||
gssize _nm_utils_ptrarray_find_first (gconstpointer *list, gssize len, gconstpointer needle);
|
||||
|
||||
gssize _nm_utils_ptrarray_find_binary_search (gconstpointer *list, gsize len, gconstpointer needle, GCompareDataFunc cmpfcn, gpointer user_data);
|
||||
gssize _nm_utils_ptrarray_find_binary_search (gconstpointer *list,
|
||||
gsize len,
|
||||
gconstpointer needle,
|
||||
GCompareDataFunc cmpfcn,
|
||||
gpointer user_data,
|
||||
gssize *out_idx_first,
|
||||
gssize *out_idx_last);
|
||||
gssize _nm_utils_array_find_binary_search (gconstpointer list, gsize elem_size, gsize len, gconstpointer needle, GCompareDataFunc cmpfcn, gpointer user_data);
|
||||
|
||||
GSList * _nm_utils_strv_to_slist (char **strv, gboolean deep_copy);
|
||||
|
|
|
@ -646,36 +646,82 @@ _nm_utils_ptrarray_find_first (gconstpointer *list, gssize len, gconstpointer ne
|
|||
}
|
||||
|
||||
gssize
|
||||
_nm_utils_ptrarray_find_binary_search (gconstpointer *list, gsize len, gconstpointer needle, GCompareDataFunc cmpfcn, gpointer user_data)
|
||||
_nm_utils_ptrarray_find_binary_search (gconstpointer *list,
|
||||
gsize len,
|
||||
gconstpointer needle,
|
||||
GCompareDataFunc cmpfcn,
|
||||
gpointer user_data,
|
||||
gssize *out_idx_first,
|
||||
gssize *out_idx_last)
|
||||
{
|
||||
gssize imin, imax, imid;
|
||||
gssize imin, imax, imid, i2min, i2max, i2mid;
|
||||
int cmp;
|
||||
|
||||
g_return_val_if_fail (list || !len, ~((gssize) 0));
|
||||
g_return_val_if_fail (cmpfcn, ~((gssize) 0));
|
||||
|
||||
imin = 0;
|
||||
if (len == 0)
|
||||
return ~imin;
|
||||
if (len > 0) {
|
||||
imax = len - 1;
|
||||
|
||||
imax = len - 1;
|
||||
while (imin <= imax) {
|
||||
imid = imin + (imax - imin) / 2;
|
||||
|
||||
while (imin <= imax) {
|
||||
imid = imin + (imax - imin) / 2;
|
||||
cmp = cmpfcn (list[imid], needle, user_data);
|
||||
if (cmp == 0) {
|
||||
/* we found a matching entry at index imid.
|
||||
*
|
||||
* Does the caller request the first/last index as well (in case that
|
||||
* there are multiple entries which compare equal). */
|
||||
|
||||
cmp = cmpfcn (list[imid], needle, user_data);
|
||||
if (cmp == 0)
|
||||
return imid;
|
||||
if (out_idx_first) {
|
||||
i2min = imin;
|
||||
i2max = imid + 1;
|
||||
while (i2min <= i2max) {
|
||||
i2mid = i2min + (i2max - i2min) / 2;
|
||||
|
||||
if (cmp < 0)
|
||||
imin = imid + 1;
|
||||
else
|
||||
imax = imid - 1;
|
||||
cmp = cmpfcn (list[i2mid], needle, user_data);
|
||||
if (cmp == 0)
|
||||
i2max = i2mid -1;
|
||||
else {
|
||||
nm_assert (cmp < 0);
|
||||
i2min = i2mid + 1;
|
||||
}
|
||||
}
|
||||
*out_idx_first = i2min;
|
||||
}
|
||||
if (out_idx_last) {
|
||||
i2min = imid + 1;
|
||||
i2max = imax;
|
||||
while (i2min <= i2max) {
|
||||
i2mid = i2min + (i2max - i2min) / 2;
|
||||
|
||||
cmp = cmpfcn (list[i2mid], needle, user_data);
|
||||
if (cmp == 0)
|
||||
i2min = i2mid + 1;
|
||||
else {
|
||||
nm_assert (cmp > 0);
|
||||
i2max = i2mid - 1;
|
||||
}
|
||||
}
|
||||
*out_idx_last = i2min - 1;
|
||||
}
|
||||
return imid;
|
||||
}
|
||||
|
||||
if (cmp < 0)
|
||||
imin = imid + 1;
|
||||
else
|
||||
imax = imid - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* return the inverse of @imin. This is a negative number, but
|
||||
* also is ~imin the position where the value should be inserted. */
|
||||
return ~imin;
|
||||
imin = ~imin;
|
||||
NM_SET_OUT (out_idx_first, imin);
|
||||
NM_SET_OUT (out_idx_last, imin);
|
||||
return imin;
|
||||
}
|
||||
|
||||
gssize
|
||||
|
|
|
@ -6149,7 +6149,7 @@ static void
|
|||
_test_find_binary_search_do (const int *array, gsize len)
|
||||
{
|
||||
gsize i;
|
||||
gssize idx;
|
||||
gssize idx, idx_first, idx_last;
|
||||
gs_free gconstpointer *parray = g_new (gconstpointer, len);
|
||||
const int NEEDLE = 0;
|
||||
gconstpointer pneedle = GINT_TO_POINTER (NEEDLE);
|
||||
|
@ -6160,10 +6160,10 @@ _test_find_binary_search_do (const int *array, gsize len)
|
|||
|
||||
expected_result = _nm_utils_ptrarray_find_first (parray, len, pneedle);
|
||||
|
||||
idx = _nm_utils_ptrarray_find_binary_search (parray, len, pneedle, _test_find_binary_search_cmp, NULL);
|
||||
if (expected_result >= 0)
|
||||
idx = _nm_utils_ptrarray_find_binary_search (parray, len, pneedle, _test_find_binary_search_cmp, NULL, &idx_first, &idx_last);
|
||||
if (expected_result >= 0) {
|
||||
g_assert_cmpint (expected_result, ==, idx);
|
||||
else {
|
||||
} else {
|
||||
gssize idx2 = ~idx;
|
||||
g_assert_cmpint (idx, <, 0);
|
||||
|
||||
|
@ -6172,6 +6172,8 @@ _test_find_binary_search_do (const int *array, gsize len)
|
|||
g_assert (idx2 - 1 < 0 || _test_find_binary_search_cmp (parray[idx2 - 1], pneedle, NULL) < 0);
|
||||
g_assert (idx2 >= len || _test_find_binary_search_cmp (parray[idx2], pneedle, NULL) > 0);
|
||||
}
|
||||
g_assert_cmpint (idx, ==, idx_first);
|
||||
g_assert_cmpint (idx, ==, idx_last);
|
||||
for (i = 0; i < len; i++) {
|
||||
int cmp;
|
||||
|
||||
|
@ -6272,6 +6274,94 @@ test_nm_utils_ptrarray_find_binary_search (void)
|
|||
test_find_binary_search_do (-3, -2, -1, 1, 2, 3, 4);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define BIN_SEARCH_W_DUPS_LEN 100
|
||||
#define BIN_SEARCH_W_DUPS_JITTER 10
|
||||
|
||||
static int
|
||||
_test_bin_search2_cmp (gconstpointer pa,
|
||||
gconstpointer pb,
|
||||
gpointer user_data)
|
||||
{
|
||||
int a = GPOINTER_TO_INT (pa);
|
||||
int b = GPOINTER_TO_INT (pb);
|
||||
|
||||
g_assert (a >= 0 && a <= BIN_SEARCH_W_DUPS_LEN + BIN_SEARCH_W_DUPS_JITTER);
|
||||
g_assert (b >= 0 && b <= BIN_SEARCH_W_DUPS_LEN + BIN_SEARCH_W_DUPS_JITTER);
|
||||
NM_CMP_DIRECT (a, b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_test_bin_search2_cmp_p (gconstpointer pa,
|
||||
gconstpointer pb,
|
||||
gpointer user_data)
|
||||
{
|
||||
return _test_bin_search2_cmp (*((gpointer *) pa), *((gpointer *) pb), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
test_nm_utils_ptrarray_find_binary_search_with_duplicates (void)
|
||||
{
|
||||
gssize idx, idx2, idx_first2, idx_first, idx_last;
|
||||
int i_test, i_len, i;
|
||||
gssize j;
|
||||
gconstpointer arr[BIN_SEARCH_W_DUPS_LEN];
|
||||
const int N_TEST = 10;
|
||||
|
||||
for (i_test = 0; i_test < N_TEST; i_test++) {
|
||||
for (i_len = 0; i_len < BIN_SEARCH_W_DUPS_LEN; i_len++) {
|
||||
|
||||
/* fill with random numbers... surely there are some duplicates
|
||||
* there... or maybe even there are none... */
|
||||
for (i = 0; i < i_len; i++)
|
||||
arr[i] = GINT_TO_POINTER (nmtst_get_rand_int () % (i_len + BIN_SEARCH_W_DUPS_JITTER));
|
||||
g_qsort_with_data (arr,
|
||||
i_len,
|
||||
sizeof (gpointer),
|
||||
_test_bin_search2_cmp_p,
|
||||
NULL);
|
||||
for (i = 0; i < i_len + BIN_SEARCH_W_DUPS_JITTER; i++) {
|
||||
gconstpointer p = GINT_TO_POINTER (i);
|
||||
|
||||
idx = _nm_utils_ptrarray_find_binary_search (arr, i_len, p, _test_bin_search2_cmp, NULL, &idx_first, &idx_last);
|
||||
|
||||
idx_first2 = _nm_utils_ptrarray_find_first (arr, i_len, p);
|
||||
|
||||
idx2 = _nm_utils_array_find_binary_search (arr, sizeof (gpointer), i_len, &p, _test_bin_search2_cmp_p, NULL);
|
||||
g_assert_cmpint (idx, ==, idx2);
|
||||
|
||||
if (idx_first2 < 0) {
|
||||
g_assert_cmpint (idx, <, 0);
|
||||
g_assert_cmpint (idx, ==, idx_first);
|
||||
g_assert_cmpint (idx, ==, idx_last);
|
||||
idx = ~idx;
|
||||
g_assert_cmpint (idx, >=, 0);
|
||||
g_assert_cmpint (idx, <=, i_len);
|
||||
if (i_len == 0)
|
||||
g_assert_cmpint (idx, ==, 0);
|
||||
else {
|
||||
g_assert (idx == i_len || GPOINTER_TO_INT (arr[idx]) > i);
|
||||
g_assert (idx == 0 || GPOINTER_TO_INT (arr[idx - 1]) < i);
|
||||
}
|
||||
} else {
|
||||
g_assert_cmpint (idx_first, ==, idx_first2);
|
||||
g_assert_cmpint (idx_first, >=, 0);
|
||||
g_assert_cmpint (idx_last, <, i_len);
|
||||
g_assert_cmpint (idx_first, <=, idx_last);
|
||||
g_assert_cmpint (idx, >=, idx_first);
|
||||
g_assert_cmpint (idx, <=, idx_last);
|
||||
for (j = idx_first; j < idx_last; j++)
|
||||
g_assert (GPOINTER_TO_INT (arr[j]) == i);
|
||||
g_assert (idx_first == 0 || GPOINTER_TO_INT (arr[idx_first - 1]) < i);
|
||||
g_assert (idx_last == i_len - 1 || GPOINTER_TO_INT (arr[idx_last + 1]) > i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
test_nm_utils_enum_from_str_do (GType type, const char *str,
|
||||
|
@ -6962,6 +7052,7 @@ int main (int argc, char **argv)
|
|||
g_test_add_func ("/core/general/_glib_compat_g_ptr_array_insert", test_g_ptr_array_insert);
|
||||
g_test_add_func ("/core/general/_glib_compat_g_hash_table_get_keys_as_array", test_g_hash_table_get_keys_as_array);
|
||||
g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search", test_nm_utils_ptrarray_find_binary_search);
|
||||
g_test_add_func ("/core/general/_nm_utils_ptrarray_find_binary_search_with_duplicates", test_nm_utils_ptrarray_find_binary_search_with_duplicates);
|
||||
g_test_add_func ("/core/general/_nm_utils_strstrdictkey", test_nm_utils_strstrdictkey);
|
||||
g_test_add_func ("/core/general/nm_ptrarray_len", test_nm_ptrarray_len);
|
||||
|
||||
|
|
|
@ -1721,8 +1721,8 @@ nm_device_get_metered (NMDevice *self)
|
|||
return NM_DEVICE_GET_PRIVATE (self)->metered;
|
||||
}
|
||||
|
||||
static guint32
|
||||
_get_route_metric_default (NMDevice *self)
|
||||
guint32
|
||||
nm_device_get_route_metric_default (NMDeviceType device_type)
|
||||
{
|
||||
/* Device 'priority' is used for the default route-metric and is based on
|
||||
* the device type. The settings ipv4.route-metric and ipv6.route-metric
|
||||
|
@ -1741,7 +1741,7 @@ _get_route_metric_default (NMDevice *self)
|
|||
* metrics (except for IPv6, where 0 means 1024).
|
||||
*/
|
||||
|
||||
switch (nm_device_get_device_type (self)) {
|
||||
switch (device_type) {
|
||||
/* 50 is reserved for VPN (NM_VPN_ROUTE_METRIC_DEFAULT) */
|
||||
case NM_DEVICE_TYPE_ETHERNET:
|
||||
case NM_DEVICE_TYPE_VETH:
|
||||
|
@ -1870,7 +1870,10 @@ nm_device_get_route_metric (NMDevice *self,
|
|||
if (route_metric >= 0)
|
||||
goto out;
|
||||
}
|
||||
route_metric = _get_route_metric_default (self);
|
||||
|
||||
route_metric = nm_manager_device_route_metric_reserve (nm_manager_get (),
|
||||
nm_device_get_ip_ifindex (self),
|
||||
nm_device_get_device_type (self));
|
||||
out:
|
||||
return nm_utils_ip_route_metric_normalize (addr_family, route_metric);
|
||||
}
|
||||
|
@ -12609,6 +12612,11 @@ _cleanup_generic_pre (NMDevice *self, CleanupType cleanup_type)
|
|||
|
||||
_cancel_activation (self);
|
||||
|
||||
if (cleanup_type != CLEANUP_TYPE_KEEP) {
|
||||
nm_manager_device_route_metric_clear (nm_manager_get (),
|
||||
nm_device_get_ip_ifindex (self));
|
||||
}
|
||||
|
||||
if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE
|
||||
&& priv->fw_state >= FIREWALL_STATE_INITIALIZED
|
||||
&& priv->fw_mgr
|
||||
|
@ -13639,6 +13647,7 @@ nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze)
|
|||
gboolean success_read;
|
||||
int ifindex;
|
||||
const NMPlatformLink *pllink;
|
||||
const NMConfigDeviceStateData *dev_state;
|
||||
|
||||
if (priv->hw_addr_perm) {
|
||||
/* the permanent hardware address is only read once and not
|
||||
|
@ -13698,23 +13707,19 @@ nm_device_update_permanent_hw_address (NMDevice *self, gboolean force_freeze)
|
|||
/* We also persist our choice of the fake address to the device state
|
||||
* file to use the same address on restart of NetworkManager.
|
||||
* First, try to reload the address from the state file. */
|
||||
{
|
||||
gs_free NMConfigDeviceStateData *dev_state = NULL;
|
||||
|
||||
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)
|
||||
&& !nm_utils_hwaddr_matches (buf, priv->hw_addr_len, priv->hw_addr, -1)) {
|
||||
_LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use from statefile: %s, current: %s)",
|
||||
success_read
|
||||
? "read HW addr length of permanent MAC address differs"
|
||||
: "unable to read permanent MAC address",
|
||||
dev_state->perm_hw_addr_fake,
|
||||
priv->hw_addr);
|
||||
priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, priv->hw_addr_len);
|
||||
goto notify_and_out;
|
||||
}
|
||||
dev_state = nm_config_device_state_get (nm_config_get (), 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)
|
||||
&& !nm_utils_hwaddr_matches (buf, priv->hw_addr_len, priv->hw_addr, -1)) {
|
||||
_LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use from statefile: %s, current: %s)",
|
||||
success_read
|
||||
? "read HW addr length of permanent MAC address differs"
|
||||
: "unable to read permanent MAC address",
|
||||
dev_state->perm_hw_addr_fake,
|
||||
priv->hw_addr);
|
||||
priv->hw_addr_perm = nm_utils_hwaddr_ntoa (buf, priv->hw_addr_len);
|
||||
goto notify_and_out;
|
||||
}
|
||||
|
||||
_LOGD (LOGD_PLATFORM | LOGD_ETHER, "hw-addr: %s (use current: %s)",
|
||||
|
|
|
@ -450,6 +450,8 @@ NMMetered nm_device_get_metered (NMDevice *dev);
|
|||
guint32 nm_device_get_route_table (NMDevice *self, int addr_family, gboolean fallback_main);
|
||||
guint32 nm_device_get_route_metric (NMDevice *dev, int addr_family);
|
||||
|
||||
guint32 nm_device_get_route_metric_default (NMDeviceType device_type);
|
||||
|
||||
const char * nm_device_get_hw_address (NMDevice *dev);
|
||||
const char * nm_device_get_permanent_hw_address (NMDevice *self);
|
||||
const char * nm_device_get_permanent_hw_address_full (NMDevice *self,
|
||||
|
|
246
src/nm-config.c
246
src/nm-config.c
|
@ -121,6 +121,14 @@ typedef struct {
|
|||
* because the state changes only on explicit actions from the daemon
|
||||
* itself. */
|
||||
State *state;
|
||||
|
||||
/* the hash table of device states. It is only loaded from disk
|
||||
* once and kept immutable afterwards.
|
||||
*
|
||||
* We also read all state file at once. We don't want to support
|
||||
* that they are changed outside of NM (at least not while NM is running).
|
||||
* Hence, we read them once, that's it. */
|
||||
GHashTable *device_states;
|
||||
} NMConfigPrivate;
|
||||
|
||||
struct _NMConfig {
|
||||
|
@ -182,6 +190,33 @@ nm_config_keyfile_get_boolean (const GKeyFile *keyfile,
|
|||
return nm_config_parse_boolean (str, default_value);
|
||||
}
|
||||
|
||||
gint64
|
||||
nm_config_keyfile_get_int64 (const GKeyFile *keyfile,
|
||||
const char *section,
|
||||
const char *key,
|
||||
guint base,
|
||||
gint64 min,
|
||||
gint64 max,
|
||||
gint64 fallback)
|
||||
{
|
||||
gint64 v;
|
||||
int errsv;
|
||||
char *str;
|
||||
|
||||
g_return_val_if_fail (keyfile, fallback);
|
||||
g_return_val_if_fail (section, fallback);
|
||||
g_return_val_if_fail (key, fallback);
|
||||
|
||||
str = g_key_file_get_value ((GKeyFile *) keyfile, section, key, NULL);
|
||||
v = _nm_utils_ascii_str_to_int64 (str, base, min, max, fallback);
|
||||
if (str) {
|
||||
errsv = errno;
|
||||
g_free (str);
|
||||
errno = errsv;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
char *
|
||||
nm_config_keyfile_get_value (const GKeyFile *keyfile,
|
||||
const char *section,
|
||||
|
@ -1898,6 +1933,7 @@ _nm_config_state_set (NMConfig *self,
|
|||
#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_PERM_HW_ADDR_FAKE "perm-hw-addr-fake"
|
||||
#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_CONNECTION_UUID "connection-uuid"
|
||||
#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_NM_OWNED "nm-owned"
|
||||
#define DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROUTE_METRIC_DEFAULT "route-metric-default"
|
||||
|
||||
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (_device_state_managed_type_to_str, NMConfigDeviceStateManagedType,
|
||||
NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT ("unknown"),
|
||||
|
@ -1917,47 +1953,54 @@ _config_device_state_data_new (int ifindex, GKeyFile *kf)
|
|||
gsize perm_hw_addr_fake_len;
|
||||
gint nm_owned = -1;
|
||||
char *p;
|
||||
guint32 route_metric_default;
|
||||
|
||||
nm_assert (kf);
|
||||
nm_assert (ifindex > 0);
|
||||
|
||||
if (kf) {
|
||||
switch (nm_config_keyfile_get_boolean (kf,
|
||||
DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
|
||||
DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_MANAGED,
|
||||
-1)) {
|
||||
case TRUE:
|
||||
managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED;
|
||||
connection_uuid = nm_config_keyfile_get_value (kf,
|
||||
DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
|
||||
DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_CONNECTION_UUID,
|
||||
NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY);
|
||||
break;
|
||||
case FALSE:
|
||||
managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNMANAGED;
|
||||
break;
|
||||
case -1:
|
||||
/* missing property in keyfile. */
|
||||
break;
|
||||
}
|
||||
|
||||
perm_hw_addr_fake = nm_config_keyfile_get_value (kf,
|
||||
DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
|
||||
DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_PERM_HW_ADDR_FAKE,
|
||||
NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY);
|
||||
if (perm_hw_addr_fake) {
|
||||
char *normalized;
|
||||
|
||||
normalized = nm_utils_hwaddr_canonical (perm_hw_addr_fake, -1);
|
||||
g_free (perm_hw_addr_fake);
|
||||
perm_hw_addr_fake = normalized;
|
||||
}
|
||||
|
||||
nm_owned = nm_config_keyfile_get_boolean (kf,
|
||||
DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
|
||||
DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_NM_OWNED,
|
||||
-1);
|
||||
switch (nm_config_keyfile_get_boolean (kf,
|
||||
DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
|
||||
DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_MANAGED,
|
||||
-1)) {
|
||||
case TRUE:
|
||||
managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_MANAGED;
|
||||
connection_uuid = nm_config_keyfile_get_value (kf,
|
||||
DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
|
||||
DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_CONNECTION_UUID,
|
||||
NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY);
|
||||
break;
|
||||
case FALSE:
|
||||
managed_type = NM_CONFIG_DEVICE_STATE_MANAGED_TYPE_UNMANAGED;
|
||||
break;
|
||||
case -1:
|
||||
/* missing property in keyfile. */
|
||||
break;
|
||||
}
|
||||
|
||||
perm_hw_addr_fake = nm_config_keyfile_get_value (kf,
|
||||
DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
|
||||
DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_PERM_HW_ADDR_FAKE,
|
||||
NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY);
|
||||
if (perm_hw_addr_fake) {
|
||||
char *normalized;
|
||||
|
||||
normalized = nm_utils_hwaddr_canonical (perm_hw_addr_fake, -1);
|
||||
g_free (perm_hw_addr_fake);
|
||||
perm_hw_addr_fake = normalized;
|
||||
}
|
||||
|
||||
nm_owned = nm_config_keyfile_get_boolean (kf,
|
||||
DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
|
||||
DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_NM_OWNED,
|
||||
-1);
|
||||
|
||||
/* metric zero is not a valid metric. While zero valid for IPv4, for IPv6 it is an alias
|
||||
* for 1024. Since we handle here IPv4 and IPv6 the same, we cannot allow zero. */
|
||||
route_metric_default = nm_config_keyfile_get_int64 (kf,
|
||||
DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
|
||||
DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROUTE_METRIC_DEFAULT,
|
||||
10, 1, G_MAXUINT32, 0);
|
||||
|
||||
connection_uuid_len = connection_uuid ? strlen (connection_uuid) + 1 : 0;
|
||||
perm_hw_addr_fake_len = perm_hw_addr_fake ? strlen (perm_hw_addr_fake) + 1 : 0;
|
||||
|
||||
|
@ -1970,6 +2013,7 @@ _config_device_state_data_new (int ifindex, GKeyFile *kf)
|
|||
device_state->connection_uuid = NULL;
|
||||
device_state->perm_hw_addr_fake = NULL;
|
||||
device_state->nm_owned = nm_owned;
|
||||
device_state->route_metric_default = route_metric_default;
|
||||
|
||||
p = (char *) (&device_state[1]);
|
||||
if (connection_uuid) {
|
||||
|
@ -2007,31 +2051,75 @@ nm_config_device_state_load (int ifindex)
|
|||
|
||||
kf = nm_config_create_keyfile ();
|
||||
if (!g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, NULL))
|
||||
g_clear_pointer (&kf, g_key_file_unref);
|
||||
return NULL;
|
||||
|
||||
device_state = _config_device_state_data_new (ifindex, kf);
|
||||
nm_owned_str = device_state->nm_owned == TRUE ?
|
||||
", nm-owned=1" :
|
||||
(device_state->nm_owned == FALSE ? ", nm-owned=0" : "");
|
||||
|
||||
|
||||
_LOGT ("device-state: %s #%d (%s); managed=%s%s%s%s%s%s%s%s",
|
||||
_LOGT ("device-state: %s #%d (%s); managed=%s%s%s%s%s%s%s%s, route-metric-default=%"G_GUINT32_FORMAT,
|
||||
kf ? "read" : "miss",
|
||||
ifindex, path,
|
||||
_device_state_managed_type_to_str (device_state->managed),
|
||||
NM_PRINT_FMT_QUOTED (device_state->connection_uuid, ", connection-uuid=", device_state->connection_uuid, "", ""),
|
||||
NM_PRINT_FMT_QUOTED (device_state->perm_hw_addr_fake, ", perm-hw-addr-fake=", device_state->perm_hw_addr_fake, "", ""),
|
||||
nm_owned_str);
|
||||
nm_owned_str,
|
||||
device_state->route_metric_default);
|
||||
|
||||
return device_state;
|
||||
}
|
||||
|
||||
static int
|
||||
_device_state_parse_filename (const char *filename)
|
||||
{
|
||||
if (!filename || !filename[0])
|
||||
return 0;
|
||||
if (!NM_STRCHAR_ALL (filename, ch, g_ascii_isdigit (ch)))
|
||||
return 0;
|
||||
return _nm_utils_ascii_str_to_int64 (filename, 10, 1, G_MAXINT, 0);
|
||||
}
|
||||
|
||||
GHashTable *
|
||||
nm_config_device_state_load_all (void)
|
||||
{
|
||||
GHashTable *states;
|
||||
GDir *dir;
|
||||
const char *fn;
|
||||
int ifindex;
|
||||
|
||||
states = g_hash_table_new_full (nm_direct_hash, NULL, NULL, g_free);
|
||||
|
||||
dir = g_dir_open (NM_CONFIG_DEVICE_STATE_DIR, 0, NULL);
|
||||
if (!dir)
|
||||
return states;
|
||||
|
||||
while ((fn = g_dir_read_name (dir))) {
|
||||
NMConfigDeviceStateData *state;
|
||||
|
||||
ifindex = _device_state_parse_filename (fn);
|
||||
if (ifindex <= 0)
|
||||
continue;
|
||||
|
||||
state = nm_config_device_state_load (ifindex);
|
||||
if (!state)
|
||||
continue;
|
||||
|
||||
if (!nm_g_hash_table_insert (states, GINT_TO_POINTER (ifindex), state))
|
||||
nm_assert_not_reached ();
|
||||
}
|
||||
g_dir_close (dir);
|
||||
|
||||
return states;
|
||||
}
|
||||
|
||||
gboolean
|
||||
nm_config_device_state_write (int ifindex,
|
||||
NMConfigDeviceStateManagedType managed,
|
||||
const char *perm_hw_addr_fake,
|
||||
const char *connection_uuid,
|
||||
gint nm_owned)
|
||||
gint nm_owned,
|
||||
guint32 route_metric_default)
|
||||
{
|
||||
char path[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR) + 60];
|
||||
GError *local = NULL;
|
||||
|
@ -2073,17 +2161,24 @@ nm_config_device_state_write (int ifindex,
|
|||
nm_owned);
|
||||
}
|
||||
|
||||
if (route_metric_default != 0) {
|
||||
g_key_file_set_int64 (kf,
|
||||
DEVICE_RUN_STATE_KEYFILE_GROUP_DEVICE,
|
||||
DEVICE_RUN_STATE_KEYFILE_KEY_DEVICE_ROUTE_METRIC_DEFAULT,
|
||||
route_metric_default);
|
||||
}
|
||||
|
||||
if (!g_key_file_save_to_file (kf, path, &local)) {
|
||||
_LOGW ("device-state: write #%d (%s) failed: %s", ifindex, path, local->message);
|
||||
g_error_free (local);
|
||||
return FALSE;
|
||||
}
|
||||
_LOGT ("device-state: write #%d (%s); managed=%s%s%s%s%s%s%s",
|
||||
_LOGT ("device-state: write #%d (%s); managed=%s%s%s%s%s%s%s, route-metric-default=%"G_GUINT32_FORMAT,
|
||||
ifindex, path,
|
||||
_device_state_managed_type_to_str (managed),
|
||||
NM_PRINT_FMT_QUOTED (connection_uuid, ", connection-uuid=", connection_uuid, "", ""),
|
||||
NM_PRINT_FMT_QUOTED (perm_hw_addr_fake, ", perm-hw-addr-fake=", perm_hw_addr_fake, "", ""));
|
||||
NM_PRINT_FMT_QUOTED (perm_hw_addr_fake, ", perm-hw-addr-fake=", perm_hw_addr_fake, "", ""),
|
||||
route_metric_default);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -2094,7 +2189,6 @@ nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes)
|
|||
const char *fn;
|
||||
int ifindex;
|
||||
gsize fn_len;
|
||||
gsize i;
|
||||
char buf[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR"/") + 30 + 3] = NM_CONFIG_DEVICE_STATE_DIR"/";
|
||||
char *buf_p = &buf[NM_STRLEN (NM_CONFIG_DEVICE_STATE_DIR"/")];
|
||||
|
||||
|
@ -2105,24 +2199,20 @@ nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes)
|
|||
return;
|
||||
|
||||
while ((fn = g_dir_read_name (dir))) {
|
||||
fn_len = strlen (fn);
|
||||
|
||||
/* skip over file names that are not plain integers. */
|
||||
for (i = 0; i < fn_len; i++) {
|
||||
if (!g_ascii_isdigit (fn[i]))
|
||||
break;
|
||||
}
|
||||
if (fn_len == 0 || i != fn_len)
|
||||
ifindex = _device_state_parse_filename (fn);
|
||||
if (ifindex <= 0)
|
||||
continue;
|
||||
|
||||
ifindex = _nm_utils_ascii_str_to_int64 (fn, 10, 1, G_MAXINT, 0);
|
||||
if (!ifindex)
|
||||
continue;
|
||||
|
||||
if (g_hash_table_contains (seen_ifindexes, GINT_TO_POINTER (ifindex)))
|
||||
continue;
|
||||
|
||||
memcpy (buf_p, fn, fn_len + 1);
|
||||
fn_len = strlen (fn) + 1;
|
||||
nm_assert (&buf_p[fn_len] < &buf[G_N_ELEMENTS (buf)]);
|
||||
memcpy (buf_p, fn, fn_len);
|
||||
nm_assert (({
|
||||
char bb[30];
|
||||
nm_sprintf_buf (bb, "%d", ifindex);
|
||||
nm_streq0 (bb, buf_p);
|
||||
}));
|
||||
_LOGT ("device-state: prune #%d (%s)", ifindex, buf);
|
||||
(void) unlink (buf);
|
||||
}
|
||||
|
@ -2132,6 +2222,46 @@ nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
static GHashTable *
|
||||
_device_state_get_all (NMConfig *self)
|
||||
{
|
||||
NMConfigPrivate *priv = NM_CONFIG_GET_PRIVATE (self);
|
||||
|
||||
if (G_UNLIKELY (!priv->device_states))
|
||||
priv->device_states = nm_config_device_state_load_all ();
|
||||
return priv->device_states;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_config_device_state_get_all:
|
||||
* @self: the #NMConfig
|
||||
*
|
||||
* This function exists to give convenient access to all
|
||||
* device states. Do not ever try to modify the returned
|
||||
* hash, it's supposed to be immutable.
|
||||
*
|
||||
* Returns: the internal #GHashTable object with all device states.
|
||||
*/
|
||||
const GHashTable *
|
||||
nm_config_device_state_get_all (NMConfig *self)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_CONFIG (self), NULL);
|
||||
|
||||
return _device_state_get_all (self);
|
||||
}
|
||||
|
||||
const NMConfigDeviceStateData *
|
||||
nm_config_device_state_get (NMConfig *self,
|
||||
int ifindex)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_CONFIG (self), NULL);
|
||||
g_return_val_if_fail (ifindex > 0 , NULL);
|
||||
|
||||
return g_hash_table_lookup (_device_state_get_all (self), GINT_TO_POINTER (ifindex));
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
nm_config_reload (NMConfig *self, NMConfigChangeFlags reload_flags)
|
||||
{
|
||||
|
|
|
@ -166,6 +166,13 @@ gint nm_config_keyfile_get_boolean (const GKeyFile *keyfile,
|
|||
const char *section,
|
||||
const char *key,
|
||||
gint default_value);
|
||||
gint64 nm_config_keyfile_get_int64 (const GKeyFile *keyfile,
|
||||
const char *section,
|
||||
const char *key,
|
||||
guint base,
|
||||
gint64 min,
|
||||
gint64 max,
|
||||
gint64 fallback);
|
||||
char *nm_config_keyfile_get_value (const GKeyFile *keyfile,
|
||||
const char *section,
|
||||
const char *key,
|
||||
|
@ -206,6 +213,9 @@ struct _NMConfigDeviceStateData {
|
|||
int ifindex;
|
||||
NMConfigDeviceStateManagedType managed;
|
||||
|
||||
/* a value of zero means that no metric is set. */
|
||||
guint32 route_metric_default;
|
||||
|
||||
/* the UUID of the last settings-connection active
|
||||
* on the device. */
|
||||
const char *connection_uuid;
|
||||
|
@ -214,17 +224,24 @@ struct _NMConfigDeviceStateData {
|
|||
|
||||
/* whether the device was nm-owned (0/1) or -1 for
|
||||
* non-software devices. */
|
||||
gint nm_owned;
|
||||
int nm_owned:3;
|
||||
};
|
||||
|
||||
NMConfigDeviceStateData *nm_config_device_state_load (int ifindex);
|
||||
GHashTable *nm_config_device_state_load_all (void);
|
||||
gboolean nm_config_device_state_write (int ifindex,
|
||||
NMConfigDeviceStateManagedType managed,
|
||||
const char *perm_hw_addr_fake,
|
||||
const char *connection_uuid,
|
||||
gint nm_owned);
|
||||
gint nm_owned,
|
||||
guint32 route_metric_default);
|
||||
|
||||
void nm_config_device_state_prune_unseen (GHashTable *seen_ifindexes);
|
||||
|
||||
const GHashTable *nm_config_device_state_get_all (NMConfig *self);
|
||||
const NMConfigDeviceStateData *nm_config_device_state_get (NMConfig *self,
|
||||
int ifindex);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif /* __NETWORKMANAGER_CONFIG_H__ */
|
||||
|
|
246
src/nm-manager.c
246
src/nm-manager.c
|
@ -161,6 +161,8 @@ typedef struct {
|
|||
|
||||
NMAuthManager *auth_mgr;
|
||||
|
||||
GHashTable *device_route_metrics;
|
||||
|
||||
GSList *auth_chains;
|
||||
GHashTable *sleep_devices;
|
||||
|
||||
|
@ -325,6 +327,237 @@ static NM_CACHED_QUARK_FCN ("autoconnect-root", autoconnect_root_quark)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
int ifindex;
|
||||
guint32 aspired_metric;
|
||||
guint32 effective_metric;
|
||||
} DeviceRouteMetricData;
|
||||
|
||||
static DeviceRouteMetricData *
|
||||
_device_route_metric_data_new (int ifindex, guint32 metric)
|
||||
{
|
||||
DeviceRouteMetricData *data;
|
||||
|
||||
nm_assert (ifindex > 0);
|
||||
|
||||
/* For IPv4, metrics can use the entire uint32 bit range. For IPv6,
|
||||
* zero is treated like 1024. Since we handle IPv4 and IPv6 identically,
|
||||
* we cannot allow a zero metric here.
|
||||
*/
|
||||
nm_assert (metric > 0);
|
||||
|
||||
data = g_slice_new0 (DeviceRouteMetricData);
|
||||
data->ifindex = ifindex;
|
||||
data->aspired_metric = metric;
|
||||
data->effective_metric = metric;
|
||||
return data;
|
||||
}
|
||||
|
||||
static guint
|
||||
_device_route_metric_data_by_ifindex_hash (gconstpointer p)
|
||||
{
|
||||
const DeviceRouteMetricData *data = p;
|
||||
NMHashState h;
|
||||
|
||||
nm_hash_init (&h, 1030338191);
|
||||
nm_hash_update_vals (&h, data->ifindex);
|
||||
return nm_hash_complete (&h);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_device_route_metric_data_by_ifindex_equal (gconstpointer pa, gconstpointer pb)
|
||||
{
|
||||
const DeviceRouteMetricData *a = pa;
|
||||
const DeviceRouteMetricData *b = pb;
|
||||
|
||||
return a->ifindex == b->ifindex;
|
||||
}
|
||||
|
||||
static guint32
|
||||
_device_route_metric_get (NMManager *self,
|
||||
int ifindex,
|
||||
NMDeviceType device_type,
|
||||
gboolean lookup_only)
|
||||
{
|
||||
NMManagerPrivate *priv;
|
||||
const DeviceRouteMetricData *d2;
|
||||
DeviceRouteMetricData *data;
|
||||
DeviceRouteMetricData data_lookup;
|
||||
const NMDedupMultiHeadEntry *all_links_head;
|
||||
NMPObject links_needle;
|
||||
guint n_links;
|
||||
gboolean cleaned = FALSE;
|
||||
GHashTableIter h_iter;
|
||||
|
||||
g_return_val_if_fail (NM_IS_MANAGER (self), 0);
|
||||
|
||||
if (ifindex <= 0) {
|
||||
if (lookup_only)
|
||||
return 0;
|
||||
return nm_device_get_route_metric_default (device_type);
|
||||
}
|
||||
|
||||
priv = NM_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
if ( lookup_only
|
||||
&& !priv->device_route_metrics)
|
||||
return 0;
|
||||
|
||||
if (G_UNLIKELY (!priv->device_route_metrics)) {
|
||||
const GHashTable *h;
|
||||
const NMConfigDeviceStateData *device_state;
|
||||
|
||||
priv->device_route_metrics = g_hash_table_new_full (_device_route_metric_data_by_ifindex_hash,
|
||||
_device_route_metric_data_by_ifindex_equal,
|
||||
NULL,
|
||||
nm_g_slice_free_fcn (DeviceRouteMetricData));
|
||||
cleaned = TRUE;
|
||||
|
||||
/* we need to pre-populate the cache for all (still existing) devices from the state-file */
|
||||
h = nm_config_device_state_get_all (priv->config);
|
||||
if (!h)
|
||||
goto initited;
|
||||
|
||||
g_hash_table_iter_init (&h_iter, (GHashTable *) h);
|
||||
while (g_hash_table_iter_next (&h_iter, NULL, (gpointer *) &device_state)) {
|
||||
if (!device_state->route_metric_default)
|
||||
continue;
|
||||
if (!nm_platform_link_get (priv->platform, device_state->ifindex)) {
|
||||
/* we have the entry in the state file, but (currently) no such
|
||||
* ifindex exists in platform. Most likely the entry is obsolete,
|
||||
* hence we skip it. */
|
||||
continue;
|
||||
}
|
||||
if (!nm_g_hash_table_add (priv->device_route_metrics,
|
||||
_device_route_metric_data_new (device_state->ifindex,
|
||||
device_state->route_metric_default)))
|
||||
nm_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
initited:
|
||||
data_lookup.ifindex = ifindex;
|
||||
|
||||
data = g_hash_table_lookup (priv->device_route_metrics, &data_lookup);
|
||||
if (data)
|
||||
return data->effective_metric;
|
||||
if (lookup_only)
|
||||
return 0;
|
||||
|
||||
if (!cleaned) {
|
||||
/* get the number of all links in the platform cache. */
|
||||
all_links_head = nm_platform_lookup_all (priv->platform,
|
||||
NMP_CACHE_ID_TYPE_OBJECT_TYPE,
|
||||
nmp_object_stackinit_id_link (&links_needle, 1));
|
||||
n_links = all_links_head ? all_links_head->len : 0;
|
||||
|
||||
/* on systems where a lot of devices are created and go away, the index contains
|
||||
* a lot of stale entries. We must from time to time clean them up.
|
||||
*
|
||||
* Do do this cleanup, whenever we have more enties then 2 times the number of links. */
|
||||
if (G_UNLIKELY (g_hash_table_size (priv->device_route_metrics) > NM_MAX (20, n_links * 2))) {
|
||||
/* from time to time, we need to do some house-keeping and prune stale entries.
|
||||
* Otherwise, on a system where interfaces frequently come and go (docker), we
|
||||
* keep growing this cache for ifindexes that no longer exist. */
|
||||
g_hash_table_iter_init (&h_iter, priv->device_route_metrics);
|
||||
while (g_hash_table_iter_next (&h_iter, NULL, (gpointer *) &d2)) {
|
||||
if (!nm_platform_link_get (priv->platform, d2->ifindex))
|
||||
g_hash_table_iter_remove (&h_iter);
|
||||
}
|
||||
cleaned = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
data = _device_route_metric_data_new (ifindex, nm_device_get_route_metric_default (device_type));
|
||||
|
||||
/* unfortunately, there is no stright forward way to lookup all reserved metrics.
|
||||
* Note, that we don't only have to know which metrics are currently reserved,
|
||||
* but also, which metrics are now seemingly un-used but caused another reserved
|
||||
* metric to be bumped. Hence, the naive O(n^2) search :( */
|
||||
again:
|
||||
g_hash_table_iter_init (&h_iter, priv->device_route_metrics);
|
||||
while (g_hash_table_iter_next (&h_iter, NULL, (gpointer *) &d2)) {
|
||||
if ( data->effective_metric < d2->aspired_metric
|
||||
|| data->effective_metric > d2->effective_metric) {
|
||||
/* no overlap. Skip. */
|
||||
continue;
|
||||
}
|
||||
if ( !cleaned
|
||||
&& !nm_platform_link_get (priv->platform, d2->ifindex)) {
|
||||
/* the metric seems taken, but there is no such interface. This entry
|
||||
* is stale, forget about it. */
|
||||
g_hash_table_iter_remove (&h_iter);
|
||||
continue;
|
||||
}
|
||||
data->effective_metric = d2->effective_metric;
|
||||
if (data->effective_metric == G_MAXUINT32) {
|
||||
/* we cannot bump any further. Done. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (data->effective_metric - data->aspired_metric > 50) {
|
||||
/* as one active interface reserves an entire range of metrics
|
||||
* (from aspired_metric to effective_metric), that means if you
|
||||
* alternatingly activate two interfaces, their metric will
|
||||
* juggle up.
|
||||
*
|
||||
* Limit this, don't bump the metric more then 50 times. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* bump the metric, and search again. */
|
||||
data->effective_metric++;
|
||||
goto again;
|
||||
}
|
||||
|
||||
_LOGT (LOGD_DEVICE, "default-route-metric: ifindex %d reserves metric %u (aspired %u)",
|
||||
data->ifindex, data->effective_metric, data->aspired_metric);
|
||||
|
||||
if (!nm_g_hash_table_add (priv->device_route_metrics, data))
|
||||
nm_assert_not_reached ();
|
||||
|
||||
return data->effective_metric;
|
||||
}
|
||||
|
||||
guint32
|
||||
nm_manager_device_route_metric_reserve (NMManager *self,
|
||||
int ifindex,
|
||||
NMDeviceType device_type)
|
||||
{
|
||||
guint32 metric;
|
||||
|
||||
metric = _device_route_metric_get (self, ifindex, device_type, FALSE);
|
||||
nm_assert (metric != 0);
|
||||
return metric;
|
||||
}
|
||||
|
||||
guint32
|
||||
nm_manager_device_route_metric_get (NMManager *self,
|
||||
int ifindex)
|
||||
{
|
||||
return _device_route_metric_get (self, ifindex, NM_DEVICE_TYPE_UNKNOWN, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
nm_manager_device_route_metric_clear (NMManager *self,
|
||||
int ifindex)
|
||||
{
|
||||
NMManagerPrivate *priv;
|
||||
DeviceRouteMetricData data_lookup;
|
||||
|
||||
priv = NM_MANAGER_GET_PRIVATE (self);
|
||||
|
||||
if (!priv->device_route_metrics)
|
||||
return;
|
||||
data_lookup.ifindex = ifindex;
|
||||
if (g_hash_table_remove (priv->device_route_metrics, &data_lookup)) {
|
||||
_LOGT (LOGD_DEVICE, "default-route-metric: ifindex %d released",
|
||||
ifindex);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_delete_volatile_connection_do (NMManager *self,
|
||||
NMSettingsConnection *connection)
|
||||
|
@ -2641,10 +2874,9 @@ platform_query_devices (NMManager *self)
|
|||
return;
|
||||
for (i = 0; i < links->len; i++) {
|
||||
const NMPlatformLink *link = NMP_OBJECT_CAST_LINK (links->pdata[i]);
|
||||
gs_free NMConfigDeviceStateData *dev_state = NULL;
|
||||
|
||||
dev_state = nm_config_device_state_load (link->ifindex);
|
||||
const NMConfigDeviceStateData *dev_state;
|
||||
|
||||
dev_state = nm_config_device_state_get (priv->config, link->ifindex);
|
||||
platform_link_added (self,
|
||||
link->ifindex,
|
||||
link,
|
||||
|
@ -5200,6 +5432,7 @@ nm_manager_write_device_state (NMManager *self)
|
|||
const char *uuid = NULL;
|
||||
const char *perm_hw_addr_fake = NULL;
|
||||
gboolean perm_hw_addr_is_fake;
|
||||
guint32 route_metric_default;
|
||||
|
||||
ifindex = nm_device_get_ip_ifindex (device);
|
||||
if (ifindex <= 0)
|
||||
|
@ -5229,11 +5462,14 @@ nm_manager_write_device_state (NMManager *self)
|
|||
|
||||
nm_owned = nm_device_is_software (device) ? nm_device_is_nm_owned (device) : -1;
|
||||
|
||||
route_metric_default = nm_manager_device_route_metric_get (self, ifindex);
|
||||
|
||||
if (nm_config_device_state_write (ifindex,
|
||||
managed_type,
|
||||
perm_hw_addr_fake,
|
||||
uuid,
|
||||
nm_owned))
|
||||
nm_owned,
|
||||
route_metric_default))
|
||||
g_hash_table_add (seen_ifindexes, GINT_TO_POINTER (ifindex));
|
||||
}
|
||||
|
||||
|
@ -6612,6 +6848,8 @@ dispose (GObject *object)
|
|||
|
||||
nm_clear_g_source (&priv->timestamp_update_id);
|
||||
|
||||
g_clear_pointer (&priv->device_route_metrics, g_hash_table_destroy);
|
||||
|
||||
G_OBJECT_CLASS (nm_manager_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
|
|
@ -115,6 +115,16 @@ NMDevice * nm_manager_get_device_by_ifindex (NMManager *manager,
|
|||
NMDevice * nm_manager_get_device_by_path (NMManager *manager,
|
||||
const char *path);
|
||||
|
||||
guint32 nm_manager_device_route_metric_reserve (NMManager *self,
|
||||
int ifindex,
|
||||
NMDeviceType device_type);
|
||||
|
||||
guint32 nm_manager_device_route_metric_get (NMManager *self,
|
||||
int ifindex);
|
||||
|
||||
void nm_manager_device_route_metric_clear (NMManager *self,
|
||||
int ifindex);
|
||||
|
||||
char * nm_manager_get_connection_iface (NMManager *self,
|
||||
NMConnection *connection,
|
||||
NMDevice **out_parent,
|
||||
|
|
Loading…
Reference in a new issue