platform: capture NMIP[46]Config from platform with correct (reversed) order of IP addresses

Fix the order of IP addresses when assuming devices (service restart).

The order of IP addresses matters to kernel for selection of source IP
address.

If all other properties are equal ([1]), for IPv6, the address added *last*
will be preferred. That is the address you see *first*` in `ip -6 addr show`.
NMPlatform also preserves that order, so the address *first* is the most
important one.

On the other hand, in a connection profile, `ipv6.addresses` lists
addresses in increasing priority (the last address is the primary one).
That is for compatibility with initscripts, which iterates over the
list of addresses and calls `ip addr add` (meaning, the last address
will be added last and is thus preferred by kernel).

As the priority order in the profile is reversed, also the priority
order in NMIP[46]Config is reversed. Fix creating an NMIP[46]Config
instance from platform addresses to honor the priority.

This has real consequences. When restarting NetworkManager, the interface
stays up with the addresses configured in the right order. After
restart, the device gets assumed, which means that the NMIP[46]Config
instance from the connection is not yet set, only the config from the
platform gets synchronized. Previously the order was wrong, so during
restart the order of IP addresses was reverted.

[1] https://access.redhat.com/solutions/189153

https://bugzilla.redhat.com/show_bug.cgi?id=1988751
This commit is contained in:
Thomas Haller 2021-08-17 11:21:17 +02:00
parent 9c99c948fd
commit c631aa48f0
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
2 changed files with 2 additions and 26 deletions

View file

@ -512,22 +512,6 @@ _notify_routes(NMIP4Config *self)
/*****************************************************************************/
static int
sort_captured_addresses(const CList *lst_a, const CList *lst_b, gconstpointer user_data)
{
const NMPlatformIP4Address *addr_a =
NMP_OBJECT_CAST_IP4_ADDRESS(c_list_entry(lst_a, NMDedupMultiEntry, lst_entries)->obj);
const NMPlatformIP4Address *addr_b =
NMP_OBJECT_CAST_IP4_ADDRESS(c_list_entry(lst_b, NMDedupMultiEntry, lst_entries)->obj);
nm_assert(addr_a);
nm_assert(addr_b);
/* Primary addresses first */
return NM_FLAGS_HAS(addr_a->n_ifa_flags, IFA_F_SECONDARY)
- NM_FLAGS_HAS(addr_b->n_ifa_flags, IFA_F_SECONDARY);
}
NMIP4Config *
nm_ip4_config_clone(const NMIP4Config *self)
{
@ -559,7 +543,7 @@ nm_ip4_config_capture(NMDedupMultiIndex *multi_idx, NMPlatform *platform, int if
head_entry = nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex);
if (head_entry) {
nmp_cache_iter_for_each (&iter, head_entry, &plobj) {
nmp_cache_iter_for_each_reverse (&iter, head_entry, &plobj) {
if (!_nm_ip_config_add_obj(priv->multi_idx,
&priv->idx_ip4_addresses_,
ifindex,
@ -571,9 +555,6 @@ nm_ip4_config_capture(NMDedupMultiIndex *multi_idx, NMPlatform *platform, int if
NULL))
nm_assert_not_reached();
}
head_entry = nm_ip4_config_lookup_addresses(self);
nm_assert(head_entry);
nm_dedup_multi_head_entry_sort(head_entry, sort_captured_addresses, NULL);
_notify_addresses(self);
}

View file

@ -316,7 +316,7 @@ nm_ip6_config_capture(NMDedupMultiIndex * multi_idx,
head_entry = nm_platform_lookup_object(platform, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex);
if (head_entry) {
nmp_cache_iter_for_each (&iter, head_entry, &plobj) {
nmp_cache_iter_for_each_reverse (&iter, head_entry, &plobj) {
if (!_nm_ip_config_add_obj(priv->multi_idx,
&priv->idx_ip6_addresses_,
ifindex,
@ -328,11 +328,6 @@ nm_ip6_config_capture(NMDedupMultiIndex * multi_idx,
NULL))
nm_assert_not_reached();
}
head_entry = nm_ip6_config_lookup_addresses(self);
nm_assert(head_entry);
nm_dedup_multi_head_entry_sort(head_entry,
sort_captured_addresses,
GINT_TO_POINTER(use_temporary));
_notify_addresses(self);
}