You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1994 lines
92 KiB

From dda06a471935a453f5e30d995c0a16b5f977397a Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Mon, 28 Mar 2022 22:26:15 +0200
Subject: [PATCH 01/11] platform: add nm_platform_ip_address_delete() helper
(cherry picked from commit a60a262574206976eacc405633c059e0f375f0a8)
(cherry picked from commit 0fc40735ab582f2ff9f319043d77d5f40253f103)
(cherry picked from commit 264296868b32a93bdbb21246828c52a282a53d50)
---
src/libnm-platform/nm-platform.h | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h
index 6f5cd5248f..baa3967db0 100644
--- a/src/libnm-platform/nm-platform.h
+++ b/src/libnm-platform/nm-platform.h
@@ -2097,6 +2097,29 @@ gboolean nm_platform_ip4_address_delete(NMPlatform *self,
gboolean
nm_platform_ip6_address_delete(NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen);
+static inline gboolean
+nm_platform_ip_address_delete(NMPlatform *self,
+ int addr_family,
+ int ifindex,
+ gconstpointer /* (const NMPlatformIPAddress *) */ addr)
+{
+ if (NM_IS_IPv4(addr_family)) {
+ const NMPlatformIP4Address *a = addr;
+
+ if (ifindex <= 0)
+ ifindex = a->ifindex;
+
+ return nm_platform_ip4_address_delete(self, ifindex, a->address, a->plen, a->peer_address);
+ } else {
+ const NMPlatformIP6Address *a = addr;
+
+ if (ifindex <= 0)
+ ifindex = a->ifindex;
+
+ return nm_platform_ip6_address_delete(self, ifindex, a->address, a->plen);
+ }
+}
+
gboolean nm_platform_ip_address_sync(NMPlatform *self,
int addr_family,
int ifindex,
--
2.35.1
From d403f25a67a48221e80971b6b0509b63c6de0a92 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Mon, 28 Mar 2022 21:13:09 +0200
Subject: [PATCH 02/11] platform: fix address order in
nm_platform_ip_address_sync()
In the past, nm_platform_ip_address_sync() only had the @known_addresses
argument. We would figure out which addresses to delete and which to preserve,
based on what addresses were known. That means, @known_addresses must have contained
all the addresses we wanted to preserve, even the external ones. That approach
was inherently racy.
Instead, nowadays we have the addresses we want to configure (@known_addresses)
and the addresses we want to delete (@prune_addresses). This started to change in
commit dadfc3abd510 ('platform: allow injecting the list of addresses to prune'),
but only commit 58287cbcc0c8 ('core: rework IP configuration in NetworkManager using
layer 3 configuration') actually changed to pass separate @prune_addresses argument.
However, the order of IP addresses matters and there is no sensible kernel API
to configure the order (short of adding them in the right order), we still need
to look at all the addresses, check their order, and possibly delete some.
That is, we need to handle addresses we want to delete (@prune_addresses)
but still look at all addresses in platform (@plat_addresses) to check
their order.
Now, first handle @prune_addresses. That's simple. These are just the
addresses we want to delete. Second, get the list of all addresses in
platform (@plat_addresses) and check the order.
Note that if there is an external address that interferes with our
desired order, we will leave it untouched. Thus, such external addresses
might prevent us from getting the order as desired. But that's just
how it is. Don't add addresses outside of NetworkManager to avoid that.
Fixes: 58287cbcc0c8 ('core: rework IP configuration in NetworkManager using layer 3 configuration')
(cherry picked from commit 80f8e23992b58aa0b6fd88de0d3973eea51691a4)
(cherry picked from commit 4c3197b37790c6c89c7b3df0e92a26e1f8719a5a)
(cherry picked from commit cd4601802de52f0239b5b8c19bd90ed9ccb6a50c)
---
src/libnm-platform/nm-platform.c | 207 +++++++++++++++++++------------
1 file changed, 126 insertions(+), 81 deletions(-)
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index 922f412df7..61fcf459ab 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -3889,9 +3889,8 @@ ip6_address_scope_cmp(gconstpointer p_a, gconstpointer p_b, gpointer increasing)
* If platform has such an address configured, it will be deleted
* at the beginning of the sync. Note that the array will be modified
* by the function.
- * Note that the addresses must be properly sorted, by their priority.
- * Create this list with nm_platform_ip_address_get_prune_list() which
- * gets the sorting right.
+ * Addresses that are both contained in @known_addresses and @addresses_prune
+ * will be configured.
*
* A convenience function to synchronize addresses for a specific interface
* with the least possible disturbance. It simply removes addresses that are
@@ -3906,11 +3905,12 @@ nm_platform_ip_address_sync(NMPlatform *self,
GPtrArray *known_addresses,
GPtrArray *addresses_prune)
{
- const gint32 now = nm_utils_get_monotonic_timestamp_sec();
- const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ const gint32 now = nm_utils_get_monotonic_timestamp_sec();
+ const int IS_IPv4 = NM_IS_IPv4(addr_family);
+ NMPLookup lookup;
gs_unref_hashtable GHashTable *known_addresses_idx = NULL;
- GPtrArray *plat_addresses;
- GHashTable *known_subnets = NULL;
+ gs_unref_ptrarray GPtrArray *plat_addresses = NULL;
+ GHashTable *known_subnets = NULL;
guint i_plat;
guint i_know;
guint i;
@@ -3918,6 +3918,9 @@ nm_platform_ip_address_sync(NMPlatform *self,
_CHECK_SELF(self, klass, FALSE);
+ /* @known_addresses (IPv4) are in decreasing priority order (highest priority addresses first).
+ * @known_addresses (IPv6) are in increasing priority order (highest priority addresses last) (we will sort them by scope next). */
+
/* The order we want to enforce is only among addresses with the same
* scope, as the kernel keeps addresses sorted by scope. Therefore,
* apply the same sorting to known addresses, so that we don't try to
@@ -3936,50 +3939,91 @@ nm_platform_ip_address_sync(NMPlatform *self,
&known_addresses_idx))
known_addresses = NULL;
- /* @plat_addresses must be sorted in decreasing priority order (highest priority addresses first), contrary to
- * @known_addresses which is in increasing priority order (lowest priority addresses first). */
- plat_addresses = addresses_prune;
+ if (nm_g_ptr_array_len(addresses_prune) > 0) {
+ /* First delete addresses that we should prune (and which are no longer tracked
+ * as @known_addresses. */
+ for (i = 0; i < addresses_prune->len; i++) {
+ const NMPObject *prune_obj = addresses_prune->pdata[i];
+
+ nm_assert(NM_IN_SET(NMP_OBJECT_GET_TYPE(prune_obj),
+ NMP_OBJECT_TYPE_IP4_ADDRESS,
+ NMP_OBJECT_TYPE_IP6_ADDRESS));
+
+ if (nm_g_hash_table_contains(known_addresses_idx, prune_obj))
+ continue;
+
+ nm_platform_ip_address_delete(self,
+ addr_family,
+ ifindex,
+ NMP_OBJECT_CAST_IP_ADDRESS(prune_obj));
+ }
+ }
+
+ /* @plat_addresses for IPv6 must be sorted in decreasing priority order (highest priority addresses first).
+ * IPv4 are probably unsorted or sorted with lowest priority first, but their order doesn't matter because
+ * we check the "secondary" flag. */
+ plat_addresses = nm_platform_lookup_clone(
+ self,
+ nmp_lookup_init_object(&lookup, NMP_OBJECT_TYPE_IP_ADDRESS(IS_IPv4), ifindex),
+ NULL,
+ NULL);
if (nm_g_ptr_array_len(plat_addresses) > 0) {
- /* Delete unknown addresses */
+ /* Delete addresses that interfere with our intended order. */
if (IS_IPv4) {
- GHashTable *plat_subnets;
+ gs_free bool *plat_handled_to_free = NULL;
+ bool *plat_handled = NULL;
+ GHashTable *plat_subnets;
+
+ /* For IPv4, we only consider it a conflict for addresses in the same
+ * subnet. That's where kernel will assign a primary/secondary flag.
+ * For different subnets, we don't define the order. */
plat_subnets = ip4_addr_subnets_build_index(plat_addresses, TRUE, TRUE);
for (i = 0; i < plat_addresses->len; i++) {
- const NMPObject *plat_obj;
+ const NMPObject *plat_obj = plat_addresses->pdata[i];
+ const NMPObject *known_obj;
const NMPlatformIP4Address *plat_address;
const GPtrArray *addr_list;
+ gboolean secondary;
- plat_obj = plat_addresses->pdata[i];
- if (!plat_obj) {
- /* Already deleted */
+ if (plat_handled && plat_handled[i])
continue;
- }
- plat_address = NMP_OBJECT_CAST_IP4_ADDRESS(plat_obj);
+ known_obj = nm_g_hash_table_lookup(known_addresses_idx, plat_obj);
- if (known_addresses) {
- const NMPObject *o;
+ if (!known_obj) {
+ /* this address is added externally. Even if it's presence would mess
+ * with our desired order, we cannot delete it. Skip it. */
+ if (!plat_handled) {
+ plat_handled = nm_malloc0_maybe_a(300,
+ sizeof(bool) * plat_addresses->len,
+ &plat_handled_to_free);
+ }
+ plat_handled[i] = TRUE;
+ continue;
+ }
- o = g_hash_table_lookup(known_addresses_idx, plat_obj);
- if (o) {
- gboolean secondary;
+ if (!known_subnets)
+ known_subnets = ip4_addr_subnets_build_index(known_addresses, FALSE, FALSE);
- if (!known_subnets)
- known_subnets =
- ip4_addr_subnets_build_index(known_addresses, FALSE, FALSE);
+ plat_address = NMP_OBJECT_CAST_IP4_ADDRESS(plat_obj);
- secondary =
- ip4_addr_subnets_is_secondary(o, known_subnets, known_addresses, NULL);
- if (secondary == NM_FLAGS_HAS(plat_address->n_ifa_flags, IFA_F_SECONDARY)) {
- /* if we have an existing known-address, with matching secondary role,
- * do not delete the platform-address. */
- continue;
- }
- }
+ secondary =
+ ip4_addr_subnets_is_secondary(known_obj, known_subnets, known_addresses, NULL);
+ if (secondary == NM_FLAGS_HAS(plat_address->n_ifa_flags, IFA_F_SECONDARY)) {
+ /* if we have an existing known-address, with matching secondary role,
+ * do not delete the platform-address. */
+ continue;
+ }
+
+ if (!plat_handled) {
+ plat_handled = nm_malloc0_maybe_a(300,
+ sizeof(bool) * plat_addresses->len,
+ &plat_handled_to_free);
}
+ plat_handled[i] = TRUE;
nm_platform_ip4_address_delete(self,
ifindex,
@@ -3999,22 +4043,27 @@ nm_platform_ip_address_sync(NMPlatform *self,
* addresses are deleted, so that we can start with a clean
* slate and add addresses in the right order. */
for (j = 1; j < addr_list->len; j++) {
- const NMPObject **o;
+ const NMPObject **o = ip4_addr_subnets_addr_list_get(addr_list, j);
+ guint o_idx;
- o = ip4_addr_subnets_addr_list_get(addr_list, j);
- nm_assert(o);
+ o_idx = (o - ((const NMPObject **) &plat_addresses->pdata[0]));
- if (*o) {
- const NMPlatformIP4Address *a;
+ nm_assert(o_idx < plat_addresses->len);
+ nm_assert(o == ((const NMPObject **) &plat_addresses->pdata[o_idx]));
- a = NMP_OBJECT_CAST_IP4_ADDRESS(*o);
- nm_platform_ip4_address_delete(self,
- ifindex,
- a->address,
- a->plen,
- a->peer_address);
- nmp_object_unref(*o);
- *o = NULL;
+ if (plat_handled[o_idx])
+ continue;
+
+ plat_handled[o_idx] = TRUE;
+
+ if (!nm_g_hash_table_contains(known_addresses_idx, *o)) {
+ /* Again, this is an external address. We cannot delete
+ * it to fix the address order. Pass. */
+ } else {
+ nm_platform_ip_address_delete(self,
+ AF_INET,
+ ifindex,
+ NMP_OBJECT_CAST_IP4_ADDRESS(*o));
}
}
}
@@ -4025,48 +4074,44 @@ nm_platform_ip_address_sync(NMPlatform *self,
IP6AddrScope cur_scope;
gboolean delete_remaining_addrs;
+ /* For IPv6, we only compare addresses per-scope. Addresses in different
+ * scopes don't have a defined order. */
+
g_ptr_array_sort_with_data(plat_addresses,
ip6_address_scope_cmp,
GINT_TO_POINTER(FALSE));
known_addresses_len = known_addresses ? known_addresses->len : 0;
- /* First, compare every address whether it is still a "known address", that is, whether
- * to keep it or to delete it.
- *
- * If we don't find a matching valid address in @known_addresses, we will delete
- * plat_addr.
- *
- * Certain addresses, like temporary addresses, are ignored by this function
- * if not run with full_sync. These addresses are usually not managed by NetworkManager
- * directly, or at least, they are not managed via nm_platform_ip6_address_sync().
- * Only in full_sync mode, we really want to get rid of them (usually, when we take
- * the interface down).
- *
- * Note that we mark handled addresses by setting it to %NULL in @plat_addresses array. */
+ /* First, check that existing addresses have a matching plen as the ones
+ * we are about to configure (@known_addresses). If not, delete them. */
for (i_plat = 0; i_plat < plat_addresses->len; i_plat++) {
- const NMPObject *plat_obj = plat_addresses->pdata[i_plat];
- const NMPObject *know_obj;
- const NMPlatformIP6Address *plat_addr = NMP_OBJECT_CAST_IP6_ADDRESS(plat_obj);
-
- if (known_addresses_idx) {
- know_obj = g_hash_table_lookup(known_addresses_idx, plat_obj);
- if (know_obj
- && plat_addr->plen == NMP_OBJECT_CAST_IP6_ADDRESS(know_obj)->plen) {
- /* technically, plen is not part of the ID for IPv6 addresses and thus
- * @plat_addr is essentially the same address as @know_addr (regrading
- * its identity, not its other attributes).
- * However, we cannot modify an existing addresses' plen without
- * removing and readding it. Thus, only keep plat_addr, if the plen
- * matches.
- *
- * keep this one, and continue */
- continue;
- }
+ const NMPObject *plat_obj = plat_addresses->pdata[i_plat];
+ const NMPObject *known_obj;
+
+ known_obj = nm_g_hash_table_lookup(known_addresses_idx, plat_obj);
+ if (!known_obj) {
+ /* We don't know this address. It was added externally. Keep it configured.
+ * We also don't want to delete the address below, so mark it as handled
+ * by clearing the pointer. */
+ nm_clear_pointer(&plat_addresses->pdata[i_plat], nmp_object_unref);
+ continue;
}
- nm_platform_ip6_address_delete(self, ifindex, plat_addr->address, plat_addr->plen);
- nmp_object_unref(g_steal_pointer(&plat_addresses->pdata[i_plat]));
+ if (NMP_OBJECT_CAST_IP6_ADDRESS(plat_obj)->plen
+ != NMP_OBJECT_CAST_IP6_ADDRESS(known_obj)->plen) {
+ /* technically, plen is not part of the ID for IPv6 addresses and thus
+ * @plat_addr is essentially the same address as @know_addr (w.r.t.
+ * its identity, not its other attributes).
+ * However, we cannot modify an existing addresses' plen without
+ * removing and readding it. Thus, we need to delete plat_addr. */
+ nm_platform_ip_address_delete(self,
+ AF_INET6,
+ ifindex,
+ NMP_OBJECT_CAST_IP6_ADDRESS(plat_obj));
+ /* Mark address as handled. */
+ nm_clear_pointer(&plat_addresses->pdata[i_plat], nmp_object_unref);
+ }
}
/* Next, we must preserve the priority of the routes. That is, source address
@@ -4077,7 +4122,7 @@ nm_platform_ip_address_sync(NMPlatform *self,
* @known_addresses (which has lowest priority first).
*
* If we find a first discrepancy, we need to delete all remaining addresses
- * with same scope from that point on, because below we must re-add all the
+ * for same scope from that point on, because below we must re-add all the
* addresses in the right order to get their priority right. */
cur_scope = IP6_ADDR_SCOPE_LOOPBACK;
delete_remaining_addrs = FALSE;
--
2.35.1
From e88a5a73f07d1593b1abe1e89a2b252559770d98 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Tue, 29 Mar 2022 16:44:29 +0200
Subject: [PATCH 03/11] platform: fix returning error from
nm_platform_ip_address_sync()
None of the callers really handle the return value of nm_platform_ip_address_sync()
or whether the function encountered problems. What would they anyway do
about that?
For IPv4 we were already ignoring errors to add addresses, but for IPv6 we
aborted. That seems wrong. As the caller does not really handle errors,
I think we should follow through and add all addresses in case of error.
Still, also collect a overall "success" of the function and return it.
(cherry picked from commit cedaa191d44fede4048a581f2cd132ec6b03d6e9)
(cherry picked from commit 8736cc86187d176ca7a7f1dbe5bdee0786c2e037)
(cherry picked from commit ebfbba550343a24b9e7b73051b0515c7fe637881)
---
src/libnm-platform/nm-platform.c | 25 +++++++++++--------------
1 file changed, 11 insertions(+), 14 deletions(-)
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index 61fcf459ab..97a86d8061 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -3877,14 +3877,9 @@ ip6_address_scope_cmp(gconstpointer p_a, gconstpointer p_b, gpointer increasing)
* @self: platform instance
* @addr_family: the address family AF_INET or AF_INET6.
* @ifindex: Interface index
- * @known_addresses: List of addresses. The list will be modified and only
- * addresses that were successfully added will be kept in the list.
- * That means, expired addresses and addresses that could not be added
- * will be dropped.
- * Hence, the input argument @known_addresses is also an output argument
- * telling which addresses were successfully added.
- * Addresses are removed by unrefing the instance via nmp_object_unref()
- * and leaving a NULL tombstone.
+ * @known_addresses: List of addresses. The list will be modified and
+ * expired addresses will be cleared (by calling nmp_object_unref()
+ * on the array element).
* @addresses_prune: (allow-none): the list of addresses to delete.
* If platform has such an address configured, it will be deleted
* at the beginning of the sync. Note that the array will be modified
@@ -3911,6 +3906,7 @@ nm_platform_ip_address_sync(NMPlatform *self,
gs_unref_hashtable GHashTable *known_addresses_idx = NULL;
gs_unref_ptrarray GPtrArray *plat_addresses = NULL;
GHashTable *known_subnets = NULL;
+ gboolean success;
guint i_plat;
guint i_know;
guint i;
@@ -4081,7 +4077,7 @@ nm_platform_ip_address_sync(NMPlatform *self,
ip6_address_scope_cmp,
GINT_TO_POINTER(FALSE));
- known_addresses_len = known_addresses ? known_addresses->len : 0;
+ known_addresses_len = nm_g_ptr_array_len(known_addresses);
/* First, check that existing addresses have a matching plen as the ones
* we are about to configure (@known_addresses). If not, delete them. */
@@ -4182,6 +4178,8 @@ next_plat:;
if (IS_IPv4)
ip4_addr_subnets_destroy_index(known_subnets, known_addresses);
+ success = TRUE;
+
/* Add missing addresses. New addresses are added by kernel with top
* priority.
*/
@@ -4217,9 +4215,8 @@ next_plat:;
lifetime,
preferred,
IFA_F_NOPREFIXROUTE,
- known_address->a4.label)) {
- /* ignore error, for unclear reasons. */
- }
+ known_address->a4.label))
+ success = FALSE;
} else {
if (!nm_platform_ip6_address_add(self,
ifindex,
@@ -4229,11 +4226,11 @@ next_plat:;
lifetime,
preferred,
IFA_F_NOPREFIXROUTE | known_address->a6.n_ifa_flags))
- return FALSE;
+ success = FALSE;
}
}
- return TRUE;
+ return success;
}
gboolean
--
2.35.1
From 87f194fddde0b54407d99748b7f6761e9bf5632a Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Thu, 31 Mar 2022 10:57:25 +0200
Subject: [PATCH 04/11] platform: fix undefined behavior for pointer comparison
in ip4_addr_subnets_is_plain_address()
Fixes: 2f68a5004153 ('platform: fix the order of addition of primary and secondary IPv4 addresses')
(cherry picked from commit 40f22e69c8c03fbbe40f3ba701c3540470f49dfe)
(cherry picked from commit 41b56cb2b9397407d24e00f95ba4ffb009212040)
(cherry picked from commit cea335c454fed307903835eb78b2bb715e0ce377)
---
src/libnm-platform/nm-platform.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index 97a86d8061..a61c8ae823 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -3698,8 +3698,8 @@ clear_and_next:
static gboolean
ip4_addr_subnets_is_plain_address(const GPtrArray *addresses, gconstpointer needle)
{
- return needle >= (gconstpointer) &addresses->pdata[0]
- && needle < (gconstpointer) &addresses->pdata[addresses->len];
+ return nm_ptr_to_uintptr(needle) >= nm_ptr_to_uintptr(&addresses->pdata[0])
+ && nm_ptr_to_uintptr(needle) < nm_ptr_to_uintptr(&addresses->pdata[addresses->len]);
}
static const NMPObject **
--
2.35.1
From 887239f75b382f46a8d89865de0a09484aaae93b Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Sat, 2 Apr 2022 10:34:17 +0200
Subject: [PATCH 05/11] platform: move known_subnets variable to inner scope in
nm_platform_ip_address_sync()
(cherry picked from commit e1431b43a2e02bdd010474df40ccf4417e8b7d08)
(cherry picked from commit a8e96e3c4b539391833b74432c3200df4e3a8223)
(cherry picked from commit 0f0d7d801b95198dd5f578dad4e719388cfd9147)
---
src/libnm-platform/nm-platform.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index a61c8ae823..06db58ad00 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -3905,7 +3905,6 @@ nm_platform_ip_address_sync(NMPlatform *self,
NMPLookup lookup;
gs_unref_hashtable GHashTable *known_addresses_idx = NULL;
gs_unref_ptrarray GPtrArray *plat_addresses = NULL;
- GHashTable *known_subnets = NULL;
gboolean success;
guint i_plat;
guint i_know;
@@ -3967,9 +3966,10 @@ nm_platform_ip_address_sync(NMPlatform *self,
if (nm_g_ptr_array_len(plat_addresses) > 0) {
/* Delete addresses that interfere with our intended order. */
if (IS_IPv4) {
+ GHashTable *known_subnets = NULL;
+ GHashTable *plat_subnets;
gs_free bool *plat_handled_to_free = NULL;
bool *plat_handled = NULL;
- GHashTable *plat_subnets;
/* For IPv4, we only consider it a conflict for addresses in the same
* subnet. That's where kernel will assign a primary/secondary flag.
@@ -4065,6 +4065,7 @@ nm_platform_ip_address_sync(NMPlatform *self,
}
}
ip4_addr_subnets_destroy_index(plat_subnets, plat_addresses);
+ ip4_addr_subnets_destroy_index(known_subnets, known_addresses);
} else {
guint known_addresses_len;
IP6AddrScope cur_scope;
@@ -4175,9 +4176,6 @@ next_plat:;
if (!known_addresses)
return TRUE;
- if (IS_IPv4)
- ip4_addr_subnets_destroy_index(known_subnets, known_addresses);
-
success = TRUE;
/* Add missing addresses. New addresses are added by kernel with top
--
2.35.1
From e97eda3965d925c39081830e75cd0397dbc5f03a Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Sat, 2 Apr 2022 10:32:55 +0200
Subject: [PATCH 06/11] platform: track IPv4 subnets with prefix length in
nm_platform_ip_address_sync()
The entire point of the dance in nm_platform_ip_address_sync() is to ensure that
conflicting IPv4 addresses are in their right order, that is, they have
the right primary/secondary flag.
Kernel only sets secondary flags for addresses that are in the same
subnet, and we also only care about the relative order of addresses
that are in the same subnet. In particular, because we rely on kernel's
"secondary" flag to implement this.
But kernel only treads addresses as secondary, if they share the exact
same subnet. For example, 192.168.0.5/24 and 192.168.0.6/25 would not
be treated as primary/secondary but just as unrelated addresses, even if
the address cleared of it's host part is the same.
This means, we must not only hash the network part of the addresses, but
also the prefix length. Implement that, by tracking the full NMPObject.
(cherry picked from commit 619dc2fcab809a1cae831c1866ce93189b575d53)
(cherry picked from commit 0bdb2e97d9a6bcd86889fb09765835a5886d13fb)
(cherry picked from commit 9149237287a550e44b3e3196dbb6786ccc3ea05c)
---
src/libnm-platform/nm-platform.c | 62 +++++++++++++++++++++-----------
1 file changed, 41 insertions(+), 21 deletions(-)
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index 06db58ad00..00a3fb2a0a 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -3733,6 +3733,30 @@ ip4_addr_subnets_destroy_index(GHashTable *subnets, const GPtrArray *addresses)
g_hash_table_unref(subnets);
}
+static guint
+_ip4_addr_subnets_hash(gconstpointer ptr)
+{
+ const NMPlatformIP4Address *addr = NMP_OBJECT_CAST_IP4_ADDRESS(ptr);
+ NMHashState h;
+
+ nm_hash_init(&h, 3282159733);
+ nm_hash_update_vals(&h,
+ addr->plen,
+ nm_utils_ip4_address_clear_host_address(addr->address, addr->plen));
+ return nm_hash_complete(&h);
+}
+
+static gboolean
+_ip4_addr_subnets_equal(gconstpointer p_a, gconstpointer p_b)
+{
+ const NMPlatformIP4Address *a = NMP_OBJECT_CAST_IP4_ADDRESS(p_a);
+ const NMPlatformIP4Address *b = NMP_OBJECT_CAST_IP4_ADDRESS(p_b);
+
+ return a->plen == b->plen
+ && (nm_utils_ip4_address_clear_host_address(a->address, a->plen)
+ == nm_utils_ip4_address_clear_host_address(b->address, b->plen));
+}
+
static GHashTable *
ip4_addr_subnets_build_index(const GPtrArray *addresses,
gboolean consider_flags,
@@ -3743,34 +3767,35 @@ ip4_addr_subnets_build_index(const GPtrArray *addresses,
nm_assert(addresses && addresses->len);
- subnets = g_hash_table_new(nm_direct_hash, NULL);
+ subnets = g_hash_table_new(_ip4_addr_subnets_hash, _ip4_addr_subnets_equal);
/* Build a hash table of all addresses per subnet */
for (i = 0; i < addresses->len; i++) {
+ const NMPObject **p_obj;
+ const NMPObject *obj;
const NMPlatformIP4Address *address;
- gpointer p_address;
GPtrArray *addr_list;
- guint32 net;
int position;
gpointer p;
if (!addresses->pdata[i])
continue;
- p_address = &addresses->pdata[i];
- address = NMP_OBJECT_CAST_IP4_ADDRESS(addresses->pdata[i]);
+ p_obj = (const NMPObject **) &addresses->pdata[i];
+ obj = *p_obj;
- net = address->address & _nm_utils_ip4_prefix_to_netmask(address->plen);
- if (!g_hash_table_lookup_extended(subnets, GUINT_TO_POINTER(net), NULL, &p)) {
- g_hash_table_insert(subnets, GUINT_TO_POINTER(net), p_address);
+ if (!g_hash_table_lookup_extended(subnets, obj, NULL, &p)) {
+ g_hash_table_insert(subnets, (gpointer) obj, p_obj);
continue;
}
nm_assert(p);
+ address = NMP_OBJECT_CAST_IP4_ADDRESS(obj);
+
if (full_index) {
if (ip4_addr_subnets_is_plain_address(addresses, p)) {
addr_list = g_ptr_array_new();
- g_hash_table_insert(subnets, GUINT_TO_POINTER(net), addr_list);
+ g_hash_table_insert(subnets, (gpointer) obj, addr_list);
g_ptr_array_add(addr_list, p);
} else
addr_list = p;
@@ -3779,13 +3804,13 @@ ip4_addr_subnets_build_index(const GPtrArray *addresses,
position = -1; /* append */
else
position = 0; /* prepend */
- g_ptr_array_insert(addr_list, position, p_address);
+ g_ptr_array_insert(addr_list, position, p_obj);
} else {
/* we only care about the primary. No need to track the secondaries
* as a GPtrArray. */
nm_assert(ip4_addr_subnets_is_plain_address(addresses, p));
if (consider_flags && !NM_FLAGS_HAS(address->n_ifa_flags, IFA_F_SECONDARY)) {
- g_hash_table_insert(subnets, GUINT_TO_POINTER(net), p_address);
+ g_hash_table_insert(subnets, (gpointer) obj, p_obj);
}
}
}
@@ -3811,16 +3836,11 @@ ip4_addr_subnets_is_secondary(const NMPObject *address,
const GPtrArray *addresses,
const GPtrArray **out_addr_list)
{
- const NMPlatformIP4Address *a;
- const GPtrArray *addr_list;
- gconstpointer p;
- guint32 net;
- const NMPObject **o;
-
- a = NMP_OBJECT_CAST_IP4_ADDRESS(address);
+ const GPtrArray *addr_list;
+ gconstpointer p;
+ const NMPObject **o;
- net = a->address & _nm_utils_ip4_prefix_to_netmask(a->plen);
- p = g_hash_table_lookup(subnets, GUINT_TO_POINTER(net));
+ p = g_hash_table_lookup(subnets, address);
nm_assert(p);
if (!ip4_addr_subnets_is_plain_address(addresses, p)) {
addr_list = p;
@@ -3966,7 +3986,7 @@ nm_platform_ip_address_sync(NMPlatform *self,
if (nm_g_ptr_array_len(plat_addresses) > 0) {
/* Delete addresses that interfere with our intended order. */
if (IS_IPv4) {
- GHashTable *known_subnets = NULL;
+ GHashTable *known_subnets = NULL;
GHashTable *plat_subnets;
gs_free bool *plat_handled_to_free = NULL;
bool *plat_handled = NULL;
--
2.35.1
From d3effaf3f81c763158c726045df750dd5c3c5e2b Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Tue, 29 Mar 2022 22:45:26 +0200
Subject: [PATCH 07/11] glib-aux: add
nm_utils_get_monotonic_timestamp_sec_cached() helper
(cherry picked from commit 3f4586532ffb8db2136bbb4ef906fd21d17d5bd2)
(cherry picked from commit 66237888e78aeae2f348b6b97c39c203a34ab7be)
(cherry picked from commit 754942038f536fcc79e476ab0ac38dbcf8e80a51)
---
src/libnm-glib-aux/nm-time-utils.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/libnm-glib-aux/nm-time-utils.h b/src/libnm-glib-aux/nm-time-utils.h
index 3c3e935f8d..461d6845fb 100644
--- a/src/libnm-glib-aux/nm-time-utils.h
+++ b/src/libnm-glib-aux/nm-time-utils.h
@@ -41,6 +41,12 @@ nm_utils_get_monotonic_timestamp_msec_cached(gint64 *cache_now)
return (*cache_now) ?: (*cache_now = nm_utils_get_monotonic_timestamp_msec());
}
+static inline gint32
+nm_utils_get_monotonic_timestamp_sec_cached(gint32 *cache_now)
+{
+ return (*cache_now) ?: (*cache_now = nm_utils_get_monotonic_timestamp_sec());
+}
+
gint64 nm_utils_clock_gettime_nsec(clockid_t clockid);
gint64 nm_utils_clock_gettime_msec(clockid_t clockid);
--
2.35.1
From 8ddff3cdccfb547b04a55a6a44221abf4e0525e8 Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Tue, 29 Mar 2022 22:45:56 +0200
Subject: [PATCH 08/11] platform: make "now" timestamp an in/out parameter to
nmp_utils_lifetime_get()
nmp_utils_lifetime_get() calculates the lifetime of addresses,
and it bases the result on a "now" timestamp.
If you have two addresses and calculate their expiry, then we want to
base it on top of the same "now" timestamp, meaning, we should
only call nm_utils_get_monotonic_timestamp_sec() once. This is also a
performance optimization. But much more importantly, when we make a
comparison at a certain moment, we need that all sides have the same
understanding of the current timestamp.
But nmp_utils_lifetime_get() does not always require the now timestamp.
And the caller doesn't know, whether it will need it (short of knowing
how nmp_utils_lifetime_get() is implemented). So, make the now parameter
an in/out argument. If we pass in an already valid now timestamp, use
that. Otherwise, fetch the current time and also return it.
(cherry picked from commit deb37401e95d4ea0025e406424c8da7c10bc9712)
(cherry picked from commit 9e40474c715e995c000b29db030b4a4990cc6e51)
(cherry picked from commit 99d77596cdc0a5d3861aebc03485d8cf9c02dd1e)
---
src/core/ndisc/nm-ndisc.c | 3 ++-
src/libnm-platform/nm-platform-utils.c | 12 +++++++-----
src/libnm-platform/nm-platform-utils.h | 2 +-
src/libnm-platform/nm-platform.c | 13 +++++++------
4 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/src/core/ndisc/nm-ndisc.c b/src/core/ndisc/nm-ndisc.c
index 969eacfaba..04b673e51d 100644
--- a/src/core/ndisc/nm-ndisc.c
+++ b/src/core/ndisc/nm-ndisc.c
@@ -996,6 +996,7 @@ nm_ndisc_set_config(NMNDisc *ndisc, const NML3ConfigData *l3cd)
const NMPObject *obj;
guint len;
guint i;
+ gint32 fake_now = NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000;
nm_assert(NM_IS_NDISC(ndisc));
nm_assert(nm_ndisc_get_node_type(ndisc) == NM_NDISC_NODE_TYPE_ROUTER);
@@ -1018,7 +1019,7 @@ nm_ndisc_set_config(NMNDisc *ndisc, const NML3ConfigData *l3cd)
lifetime = nmp_utils_lifetime_get(addr->timestamp,
addr->lifetime,
addr->preferred,
- NM_NDISC_EXPIRY_BASE_TIMESTAMP / 1000,
+ &fake_now,
&preferred);
if (!lifetime)
continue;
diff --git a/src/libnm-platform/nm-platform-utils.c b/src/libnm-platform/nm-platform-utils.c
index 9ad030df76..bebc53a851 100644
--- a/src/libnm-platform/nm-platform-utils.c
+++ b/src/libnm-platform/nm-platform-utils.c
@@ -2132,12 +2132,15 @@ guint32
nmp_utils_lifetime_get(guint32 timestamp,
guint32 lifetime,
guint32 preferred,
- gint32 now,
+ gint32 *cached_now,
guint32 *out_preferred)
{
- guint32 t_lifetime, t_preferred;
+ guint32 t_lifetime;
+ guint32 t_preferred;
+ gint32 now;
- nm_assert(now >= 0);
+ nm_assert(cached_now);
+ nm_assert(*cached_now >= 0);
if (timestamp == 0 && lifetime == 0) {
/* We treat lifetime==0 && timestamp==0 addresses as permanent addresses to allow easy
@@ -2150,8 +2153,7 @@ nmp_utils_lifetime_get(guint32 timestamp,
return NM_PLATFORM_LIFETIME_PERMANENT;
}
- if (now <= 0)
- now = nm_utils_get_monotonic_timestamp_sec();
+ now = nm_utils_get_monotonic_timestamp_sec_cached(cached_now);
t_lifetime = nmp_utils_lifetime_rebase_relative_time_on_now(timestamp, lifetime, now);
if (!t_lifetime) {
diff --git a/src/libnm-platform/nm-platform-utils.h b/src/libnm-platform/nm-platform-utils.h
index a9ccebb3e2..9f17da4886 100644
--- a/src/libnm-platform/nm-platform-utils.h
+++ b/src/libnm-platform/nm-platform-utils.h
@@ -86,7 +86,7 @@ nmp_utils_lifetime_rebase_relative_time_on_now(guint32 timestamp, guint32 durati
guint32 nmp_utils_lifetime_get(guint32 timestamp,
guint32 lifetime,
guint32 preferred,
- gint32 now,
+ gint32 *cached_now,
guint32 *out_preferred);
int nmp_utils_modprobe(GError **error, gboolean suppress_error_logging, const char *arg1, ...)
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index 00a3fb2a0a..ea7aad9398 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -3632,7 +3632,7 @@ static gboolean
_addr_array_clean_expired(int addr_family,
int ifindex,
GPtrArray *array,
- guint32 now,
+ gint32 *cached_now,
GHashTable **idx)
{
guint i;
@@ -3640,7 +3640,8 @@ _addr_array_clean_expired(int addr_family,
nm_assert_addr_family(addr_family);
nm_assert(ifindex > 0);
- nm_assert(now > 0);
+ nm_assert(cached_now);
+ nm_assert(*cached_now >= 0);
if (!array)
return FALSE;
@@ -3674,7 +3675,7 @@ _addr_array_clean_expired(int addr_family,
goto clear_and_next;
}
- if (!nmp_utils_lifetime_get(a->timestamp, a->lifetime, a->preferred, now, NULL))
+ if (!nmp_utils_lifetime_get(a->timestamp, a->lifetime, a->preferred, cached_now, NULL))
goto clear_and_next;
if (idx) {
@@ -3920,7 +3921,7 @@ nm_platform_ip_address_sync(NMPlatform *self,
GPtrArray *known_addresses,
GPtrArray *addresses_prune)
{
- const gint32 now = nm_utils_get_monotonic_timestamp_sec();
+ gint32 now = 0;
const int IS_IPv4 = NM_IS_IPv4(addr_family);
NMPLookup lookup;
gs_unref_hashtable GHashTable *known_addresses_idx = NULL;
@@ -3950,7 +3951,7 @@ nm_platform_ip_address_sync(NMPlatform *self,
if (!_addr_array_clean_expired(addr_family,
ifindex,
known_addresses,
- now,
+ &now,
&known_addresses_idx))
known_addresses = NULL;
@@ -4218,7 +4219,7 @@ next_plat:;
lifetime = nmp_utils_lifetime_get(known_address->ax.timestamp,
known_address->ax.lifetime,
known_address->ax.preferred,
- now,
+ &now,
&preferred);
nm_assert(lifetime > 0);
--
2.35.1
From 09a9467c8112ce29d097bc0c5d236e2da2108afe Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Tue, 29 Mar 2022 18:21:49 +0200
Subject: [PATCH 09/11] platform: make NMPlatformVTableAddress struct smaller
and pack NMPObjectType
(cherry picked from commit 7c92663f8d79375c78f6917d4c6e005d7accf2a6)
(cherry picked from commit 3a98ecfa0edce51c5ed8446bc3a74efc6ec6ac65)
(cherry picked from commit de4d10f1c1f754a1ea954e8bf073d7cdaa269f96)
---
src/libnm-platform/nm-platform.h | 6 +++---
src/libnm-platform/nmp-base.h | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h
index baa3967db0..d978c91b80 100644
--- a/src/libnm-platform/nm-platform.h
+++ b/src/libnm-platform/nm-platform.h
@@ -776,10 +776,10 @@ typedef struct {
#undef __NMPlatformObjWithIfindex_COMMON
typedef struct {
- gboolean is_ip4;
+ bool is_ip4;
+ gint8 addr_family;
+ guint8 sizeof_route;
NMPObjectType obj_type;
- int addr_family;
- gsize sizeof_route;
int (*route_cmp)(const NMPlatformIPXRoute *a,
const NMPlatformIPXRoute *b,
NMPlatformIPRouteCmpType cmp_type);
diff --git a/src/libnm-platform/nmp-base.h b/src/libnm-platform/nmp-base.h
index a80fd4d389..4863168855 100644
--- a/src/libnm-platform/nmp-base.h
+++ b/src/libnm-platform/nmp-base.h
@@ -110,7 +110,7 @@ typedef struct _NMPlatformIP6Route NMPlatformIP6Route;
typedef struct _NMPlatformLink NMPlatformLink;
typedef struct _NMPObject NMPObject;
-typedef enum {
+typedef enum _nm_packed {
NMP_OBJECT_TYPE_UNKNOWN,
NMP_OBJECT_TYPE_LINK,
--
2.35.1
From efbeb187430ffec0d50cd79d0867013ea289f5fa Mon Sep 17 00:00:00 2001
From: Thomas Haller <thaller@redhat.com>
Date: Tue, 29 Mar 2022 18:20:31 +0200
Subject: [PATCH 10/11] platform: add semantic comparison for IP addresses and
add "nm_platform_vtable_address"
We already have a comparison of NMPlatformIPXAddress with the modes
"full" and "id". The former is needed to fully compare two addresses,
the latter as identity for tracking addresses in the cache.
In NetworkManager we also use the NMPlatformIP[46]Address structure to
track the addresses we want to configure. When we add them in kernel,
we will later see them in the platform cache. However, some fields
will be slightly different. For example, "addr_source" address will
always be "kernel", because that one is not a field we configure in
kernel. Also, the "n_ifa_flags" probably differ (getting "permanent"
and "secondary" flags).
Add a compare function that can ignore such differences.
Also add nm_platform_vtable_address for accessing the IPv4 and IPv6
methods generically (based on an "IS_IPv4" variable).
(cherry picked from commit ef1b60c061f85b60329d37d62dc81683ff56f4b7)
(cherry picked from commit ea6625ce97629b287f484e0d5caeb0d08ed44843)
(cherry picked from commit 8f83aec9d3dd172dd297ba5394e61c85641dd754)
---
src/libnm-platform/nm-platform.c | 165 +++++++++++++++++++++++++------
src/libnm-platform/nm-platform.h | 49 ++++++++-
src/libnm-platform/nmp-object.c | 82 +++++++--------
3 files changed, 224 insertions(+), 72 deletions(-)
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index ea7aad9398..8459231dc2 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -7831,6 +7831,25 @@ _address_pretty_sort_get_prio_6(const struct in6_addr *addr)
return 6;
}
+static int
+_address_cmp_expiry(const NMPlatformIPAddress *a, const NMPlatformIPAddress *b)
+{
+ guint32 lifetime_a;
+ guint32 lifetime_b;
+ guint32 preferred_a;
+ guint32 preferred_b;
+ gint32 now = 0;
+
+ lifetime_a =
+ nmp_utils_lifetime_get(a->timestamp, a->lifetime, a->preferred, &now, &preferred_a);
+ lifetime_b =
+ nmp_utils_lifetime_get(b->timestamp, b->lifetime, b->preferred, &now, &preferred_b);
+
+ NM_CMP_DIRECT(lifetime_a, lifetime_b);
+ NM_CMP_DIRECT(preferred_a, preferred_b);
+ return 0;
+}
+
int
nm_platform_ip6_address_pretty_sort_cmp(const NMPlatformIP6Address *a1,
const NMPlatformIP6Address *a2,
@@ -7910,26 +7929,55 @@ nm_platform_ip4_address_hash_update(const NMPlatformIP4Address *obj, NMHashState
}
int
-nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a, const NMPlatformIP4Address *b)
+nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a,
+ const NMPlatformIP4Address *b,
+ NMPlatformIPAddressCmpType cmp_type)
{
NM_CMP_SELF(a, b);
+
NM_CMP_FIELD(a, b, ifindex);
- NM_CMP_FIELD(a, b, address);
NM_CMP_FIELD(a, b, plen);
- NM_CMP_FIELD(a, b, peer_address);
- NM_CMP_FIELD_UNSAFE(a, b, use_ip4_broadcast_address);
- if (a->use_ip4_broadcast_address)
- NM_CMP_FIELD(a, b, broadcast_address);
- NM_CMP_FIELD(a, b, addr_source);
- NM_CMP_FIELD(a, b, timestamp);
- NM_CMP_FIELD(a, b, lifetime);
- NM_CMP_FIELD(a, b, preferred);
- NM_CMP_FIELD(a, b, n_ifa_flags);
- NM_CMP_FIELD_STR(a, b, label);
- NM_CMP_FIELD_UNSAFE(a, b, a_acd_not_ready);
- NM_CMP_FIELD_UNSAFE(a, b, a_assume_config_once);
- NM_CMP_FIELD_UNSAFE(a, b, a_force_commit);
- return 0;
+ NM_CMP_FIELD(a, b, address);
+
+ switch (cmp_type) {
+ case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_ID:
+ /* for IPv4 addresses, you can add the same local address with differing peer-address
+ * (IFA_ADDRESS), provided that their net-part differs. */
+ NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX(a->peer_address, b->peer_address, a->plen);
+ return 0;
+ case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_SEMANTICALLY:
+ case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_FULL:
+ NM_CMP_FIELD(a, b, peer_address);
+ NM_CMP_FIELD_STR(a, b, label);
+ if (cmp_type == NM_PLATFORM_IP_ADDRESS_CMP_TYPE_SEMANTICALLY) {
+ NM_CMP_RETURN(_address_cmp_expiry((const NMPlatformIPAddress *) a,
+ (const NMPlatformIPAddress *) b));
+
+ /* Most flags are set by kernel. We only compare the ones that
+ * NetworkManager actively sets.
+ *
+ * NM actively only sets IFA_F_NOPREFIXROUTE (and IFA_F_MANAGETEMPADDR for IPv6),
+ * where nm_platform_ip_address_sync() always sets IFA_F_NOPREFIXROUTE.
+ * There are thus no flags to compare for IPv4. */
+
+ NM_CMP_DIRECT(nm_platform_ip4_broadcast_address_from_addr(a),
+ nm_platform_ip4_broadcast_address_from_addr(b));
+ } else {
+ NM_CMP_FIELD(a, b, timestamp);
+ NM_CMP_FIELD(a, b, lifetime);
+ NM_CMP_FIELD(a, b, preferred);
+ NM_CMP_FIELD(a, b, n_ifa_flags);
+ NM_CMP_FIELD(a, b, addr_source);
+ NM_CMP_FIELD_UNSAFE(a, b, use_ip4_broadcast_address);
+ if (a->use_ip4_broadcast_address)
+ NM_CMP_FIELD(a, b, broadcast_address);
+ NM_CMP_FIELD_UNSAFE(a, b, a_acd_not_ready);
+ NM_CMP_FIELD_UNSAFE(a, b, a_assume_config_once);
+ NM_CMP_FIELD_UNSAFE(a, b, a_force_commit);
+ }
+ return 0;
+ }
+ return nm_assert_unreachable_val(0);
}
void
@@ -7950,25 +7998,51 @@ nm_platform_ip6_address_hash_update(const NMPlatformIP6Address *obj, NMHashState
}
int
-nm_platform_ip6_address_cmp(const NMPlatformIP6Address *a, const NMPlatformIP6Address *b)
+nm_platform_ip6_address_cmp(const NMPlatformIP6Address *a,
+ const NMPlatformIP6Address *b,
+ NMPlatformIPAddressCmpType cmp_type)
{
const struct in6_addr *p_a, *p_b;
NM_CMP_SELF(a, b);
+
NM_CMP_FIELD(a, b, ifindex);
- NM_CMP_FIELD_MEMCMP(a, b, address);
- NM_CMP_FIELD(a, b, plen);
- p_a = nm_platform_ip6_address_get_peer(a);
- p_b = nm_platform_ip6_address_get_peer(b);
- NM_CMP_DIRECT_MEMCMP(p_a, p_b, sizeof(*p_a));
- NM_CMP_FIELD(a, b, addr_source);
- NM_CMP_FIELD(a, b, timestamp);
- NM_CMP_FIELD(a, b, lifetime);
- NM_CMP_FIELD(a, b, preferred);
- NM_CMP_FIELD(a, b, n_ifa_flags);
- NM_CMP_FIELD_UNSAFE(a, b, a_assume_config_once);
- NM_CMP_FIELD_UNSAFE(a, b, a_force_commit);
- return 0;
+ NM_CMP_FIELD_IN6ADDR(a, b, address);
+
+ switch (cmp_type) {
+ case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_ID:
+ /* for IPv6 addresses, the prefix length is not part of the primary identifier. */
+ return 0;
+ case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_SEMANTICALLY:
+ case NM_PLATFORM_IP_ADDRESS_CMP_TYPE_FULL:
+ NM_CMP_FIELD(a, b, plen);
+ p_a = nm_platform_ip6_address_get_peer(a);
+ p_b = nm_platform_ip6_address_get_peer(b);
+ NM_CMP_DIRECT_MEMCMP(p_a, p_b, sizeof(*p_a));
+ if (cmp_type == NM_PLATFORM_IP_ADDRESS_CMP_TYPE_SEMANTICALLY) {
+ NM_CMP_RETURN(_address_cmp_expiry((const NMPlatformIPAddress *) a,
+ (const NMPlatformIPAddress *) b));
+
+ /* Most flags are set by kernel. We only compare the ones that
+ * NetworkManager actively sets.
+ *
+ * NM actively only sets IFA_F_NOPREFIXROUTE and IFA_F_MANAGETEMPADDR,
+ * where nm_platform_ip_address_sync() always sets IFA_F_NOPREFIXROUTE.
+ * We thus only care about IFA_F_MANAGETEMPADDR. */
+ NM_CMP_DIRECT(a->n_ifa_flags & IFA_F_MANAGETEMPADDR,
+ b->n_ifa_flags & IFA_F_MANAGETEMPADDR);
+ } else {
+ NM_CMP_FIELD(a, b, timestamp);
+ NM_CMP_FIELD(a, b, lifetime);
+ NM_CMP_FIELD(a, b, preferred);
+ NM_CMP_FIELD(a, b, n_ifa_flags);
+ NM_CMP_FIELD(a, b, addr_source);
+ NM_CMP_FIELD_UNSAFE(a, b, a_assume_config_once);
+ NM_CMP_FIELD_UNSAFE(a, b, a_force_commit);
+ }
+ return 0;
+ }
+ return nm_assert_unreachable_val(0);
}
void
@@ -8924,6 +8998,37 @@ nm_platform_netns_push(NMPlatform *self, NMPNetns **netns)
/*****************************************************************************/
+const _NMPlatformVTableAddressUnion nm_platform_vtable_address = {
+ .v4 =
+ {
+ .is_ip4 = TRUE,
+ .obj_type = NMP_OBJECT_TYPE_IP4_ADDRESS,
+ .addr_family = AF_INET,
+ .sizeof_address = sizeof(NMPlatformIP4Address),
+ .address_cmp =
+ (int (*)(const NMPlatformIPXAddress *a,
+ const NMPlatformIPXAddress *b,
+ NMPlatformIPAddressCmpType cmp_type)) nm_platform_ip4_address_cmp,
+ .address_to_string = (const char *(*) (const NMPlatformIPXAddress *address,
+ char *buf,
+ gsize len)) nm_platform_ip4_address_to_string,
+ },
+ .v6 =
+ {
+ .is_ip4 = FALSE,
+ .obj_type = NMP_OBJECT_TYPE_IP6_ADDRESS,
+ .addr_family = AF_INET6,
+ .sizeof_address = sizeof(NMPlatformIP6Address),
+ .address_cmp =
+ (int (*)(const NMPlatformIPXAddress *a,
+ const NMPlatformIPXAddress *b,
+ NMPlatformIPAddressCmpType cmp_type)) nm_platform_ip6_address_cmp,
+ .address_to_string = (const char *(*) (const NMPlatformIPXAddress *address,
+ char *buf,
+ gsize len)) nm_platform_ip6_address_to_string,
+ },
+};
+
const _NMPlatformVTableRouteUnion nm_platform_vtable_route = {
.v4 =
{
diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h
index d978c91b80..203f8c7bbd 100644
--- a/src/libnm-platform/nm-platform.h
+++ b/src/libnm-platform/nm-platform.h
@@ -94,6 +94,14 @@ typedef enum {
NMP_NLM_FLAG_TEST = NMP_NLM_FLAG_F_EXCL,
} NMPNlmFlags;
+typedef enum {
+ NM_PLATFORM_IP_ADDRESS_CMP_TYPE_ID,
+
+ NM_PLATFORM_IP_ADDRESS_CMP_TYPE_SEMANTICALLY,
+
+ NM_PLATFORM_IP_ADDRESS_CMP_TYPE_FULL,
+} NMPlatformIPAddressCmpType;
+
typedef enum {
/* compare fields which kernel considers as similar routes.
* It is a looser comparisong then NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID
@@ -775,6 +783,27 @@ typedef struct {
#undef __NMPlatformObjWithIfindex_COMMON
+typedef struct {
+ bool is_ip4;
+ NMPObjectType obj_type;
+ gint8 addr_family;
+ guint8 sizeof_address;
+ int (*address_cmp)(const NMPlatformIPXAddress *a,
+ const NMPlatformIPXAddress *b,
+ NMPlatformIPAddressCmpType cmp_type);
+ const char *(*address_to_string)(const NMPlatformIPXAddress *address, char *buf, gsize len);
+} NMPlatformVTableAddress;
+
+typedef union {
+ struct {
+ NMPlatformVTableAddress v6;
+ NMPlatformVTableAddress v4;
+ };
+ NMPlatformVTableAddress vx[2];
+} _NMPlatformVTableAddressUnion;
+
+extern const _NMPlatformVTableAddressUnion nm_platform_vtable_address;
+
typedef struct {
bool is_ip4;
gint8 addr_family;
@@ -2311,8 +2340,24 @@ int nm_platform_lnk_vlan_cmp(const NMPlatformLnkVlan *a, const NMPlatformLnkVlan
int nm_platform_lnk_vrf_cmp(const NMPlatformLnkVrf *a, const NMPlatformLnkVrf *b);
int nm_platform_lnk_vxlan_cmp(const NMPlatformLnkVxlan *a, const NMPlatformLnkVxlan *b);
int nm_platform_lnk_wireguard_cmp(const NMPlatformLnkWireGuard *a, const NMPlatformLnkWireGuard *b);
-int nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a, const NMPlatformIP4Address *b);
-int nm_platform_ip6_address_cmp(const NMPlatformIP6Address *a, const NMPlatformIP6Address *b);
+int nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a,
+ const NMPlatformIP4Address *b,
+ NMPlatformIPAddressCmpType cmp_type);
+int nm_platform_ip6_address_cmp(const NMPlatformIP6Address *a,
+ const NMPlatformIP6Address *b,
+ NMPlatformIPAddressCmpType cmp_type);
+
+static inline int
+nm_platform_ip4_address_cmp_full(const NMPlatformIP4Address *a, const NMPlatformIP4Address *b)
+{
+ return nm_platform_ip4_address_cmp(a, b, NM_PLATFORM_IP_ADDRESS_CMP_TYPE_FULL);
+}
+
+static inline int
+nm_platform_ip6_address_cmp_full(const NMPlatformIP6Address *a, const NMPlatformIP6Address *b)
+{
+ return nm_platform_ip6_address_cmp(a, b, NM_PLATFORM_IP_ADDRESS_CMP_TYPE_FULL);
+}
int nm_platform_ip4_address_pretty_sort_cmp(const NMPlatformIP4Address *a1,
const NMPlatformIP4Address *a2);
diff --git a/src/libnm-platform/nmp-object.c b/src/libnm-platform/nmp-object.c
index d518e6e589..0102e943ff 100644
--- a/src/libnm-platform/nmp-object.c
+++ b/src/libnm-platform/nmp-object.c
@@ -1523,20 +1523,21 @@ nmp_object_id_cmp(const NMPObject *obj1, const NMPObject *obj2)
_vt_cmd_plobj_id_cmp(link, NMPlatformLink, { NM_CMP_FIELD(obj1, obj2, ifindex); });
-_vt_cmd_plobj_id_cmp(ip4_address, NMPlatformIP4Address, {
- NM_CMP_FIELD(obj1, obj2, ifindex);
- NM_CMP_FIELD(obj1, obj2, plen);
- NM_CMP_FIELD(obj1, obj2, address);
- /* for IPv4 addresses, you can add the same local address with differing peer-address
- * (IFA_ADDRESS), provided that their net-part differs. */
- NM_CMP_DIRECT_IN4ADDR_SAME_PREFIX(obj1->peer_address, obj2->peer_address, obj1->plen);
-});
+static int
+_vt_cmd_plobj_id_cmp_ip4_address(const NMPlatformObject *obj1, const NMPlatformObject *obj2)
+{
+ return nm_platform_ip4_address_cmp((const NMPlatformIP4Address *) obj1,
+ (const NMPlatformIP4Address *) obj2,
+ NM_PLATFORM_IP_ADDRESS_CMP_TYPE_ID);
+}
-_vt_cmd_plobj_id_cmp(ip6_address, NMPlatformIP6Address, {
- NM_CMP_FIELD(obj1, obj2, ifindex);
- /* for IPv6 addresses, the prefix length is not part of the primary identifier. */
- NM_CMP_FIELD_IN6ADDR(obj1, obj2, address);
-});
+static int
+_vt_cmd_plobj_id_cmp_ip6_address(const NMPlatformObject *obj1, const NMPlatformObject *obj2)
+{
+ return nm_platform_ip6_address_cmp((const NMPlatformIP6Address *) obj1,
+ (const NMPlatformIP6Address *) obj2,
+ NM_PLATFORM_IP_ADDRESS_CMP_TYPE_ID);
+}
_vt_cmd_plobj_id_cmp(qdisc, NMPlatformQdisc, {
NM_CMP_FIELD(obj1, obj2, ifindex);
@@ -1551,24 +1552,24 @@ _vt_cmd_plobj_id_cmp(tfilter, NMPlatformTfilter, {
static int
_vt_cmd_plobj_id_cmp_ip4_route(const NMPlatformObject *obj1, const NMPlatformObject *obj2)
{
- return nm_platform_ip4_route_cmp((NMPlatformIP4Route *) obj1,
- (NMPlatformIP4Route *) obj2,
+ return nm_platform_ip4_route_cmp((const NMPlatformIP4Route *) obj1,
+ (const NMPlatformIP4Route *) obj2,
NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID);
}
static int
_vt_cmd_plobj_id_cmp_ip6_route(const NMPlatformObject *obj1, const NMPlatformObject *obj2)
{
- return nm_platform_ip6_route_cmp((NMPlatformIP6Route *) obj1,
- (NMPlatformIP6Route *) obj2,
+ return nm_platform_ip6_route_cmp((const NMPlatformIP6Route *) obj1,
+ (const NMPlatformIP6Route *) obj2,
NM_PLATFORM_IP_ROUTE_CMP_TYPE_ID);
}
static int
_vt_cmd_plobj_id_cmp_routing_rule(const NMPlatformObject *obj1, const NMPlatformObject *obj2)
{
- return nm_platform_routing_rule_cmp((NMPlatformRoutingRule *) obj1,
- (NMPlatformRoutingRule *) obj2,
+ return nm_platform_routing_rule_cmp((const NMPlatformRoutingRule *) obj1,
+ (const NMPlatformRoutingRule *) obj2,
NM_PLATFORM_ROUTING_RULE_CMP_TYPE_ID);
}
@@ -3158,28 +3159,29 @@ const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
.cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_ip4_address,
.cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_ip4_address_to_string,
.cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_ip4_address_hash_update,
- .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_ip4_address_cmp,
+ .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_ip4_address_cmp_full,
+ },
+ [NMP_OBJECT_TYPE_IP6_ADDRESS - 1] =
+ {
+ .parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
+ .obj_type = NMP_OBJECT_TYPE_IP6_ADDRESS,
+ .sizeof_data = sizeof(NMPObjectIP6Address),
+ .sizeof_public = sizeof(NMPlatformIP6Address),
+ .obj_type_name = "ip6-address",
+ .addr_family = AF_INET6,
+ .rtm_gettype = RTM_GETADDR,
+ .signal_type_id = NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS,
+ .signal_type = NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
+ .supported_cache_ids = _supported_cache_ids_ipx_address,
+ .cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_address,
+ .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip6_address,
+ .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_ip6_address,
+ .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_ip6_address,
+ .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_ip6_address,
+ .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_ip6_address_to_string,
+ .cmd_plobj_hash_update = (CmdPlobjHashUpdateFunc) nm_platform_ip6_address_hash_update,
+ .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_ip6_address_cmp_full,
},
- [NMP_OBJECT_TYPE_IP6_ADDRESS
- - 1] = {.parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
- .obj_type = NMP_OBJECT_TYPE_IP6_ADDRESS,
- .sizeof_data = sizeof(NMPObjectIP6Address),
- .sizeof_public = sizeof(NMPlatformIP6Address),
- .obj_type_name = "ip6-address",
- .addr_family = AF_INET6,
- .rtm_gettype = RTM_GETADDR,
- .signal_type_id = NM_PLATFORM_SIGNAL_ID_IP6_ADDRESS,
- .signal_type = NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED,
- .supported_cache_ids = _supported_cache_ids_ipx_address,
- .cmd_obj_is_alive = _vt_cmd_obj_is_alive_ipx_address,
- .cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_ip6_address,
- .cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_ip6_address,
- .cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_ip6_address,
- .cmd_plobj_to_string_id = _vt_cmd_plobj_to_string_id_ip6_address,
- .cmd_plobj_to_string = (CmdPlobjToStringFunc) nm_platform_ip6_address_to_string,
- .cmd_plobj_hash_update =
- (CmdPlobjHashUpdateFunc) nm_platform_ip6_address_hash_update,
- .cmd_plobj_cmp = (CmdPlobjCmpFunc) nm_platform_ip6_address_cmp},
[NMP_OBJECT_TYPE_IP4_ROUTE - 1] =
{
.parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
--
2.35.1
From b9cb6401cc5efb4092e8a92af6ed509a986fe495 Mon Sep 17 00:00:00 2001
From: Fernando Fernandez Mancera <ffmancera@riseup.net>
Date: Tue, 19 Apr 2022 18:39:37 +0200
Subject: [PATCH 11/11] l3cfg: drop NM_L3_CFG_COMMIT_TYPE_ASSUME and
assume_config_once
ASSUME is causing more troubles than benefits it provides. This patch is
dropping NM_L3_CFG_COMMIT_TYPE_ASSUME and assume_config_once. NM3LCfg
will commit as if the sys-iface-state is MANAGED.
This patch is part of the effort to remove ASSUME from NetworkManager.
After ASSUME is dropped when starting NetworkManager it will take full
control of the interface, re-configuring it. The interface will be
managed from the start instead of assumed and then managed.
This will solve the situations where an interface is half-up and then a
restart happens. When NetworkManager is back it won't add the missing
addresses (which is what assume does) so the interface will fail during
the activation and will require a full activation.
https://bugzilla.redhat.com/show_bug.cgi?id=2050216
https://bugzilla.redhat.com/show_bug.cgi?id=2077605
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1196
(cherry picked from commit bf5927b978fccec1390bcc7d3d5719d7fe7c3450)
(cherry picked from commit a494c00901a56afe422c4944875de0340d305e8a)
(cherry picked from commit 05c3f384b641624edc1a951899bcb0f770972e28)
---
src/core/devices/nm-device.c | 4 ++-
src/core/nm-l3-config-data.c | 36 +++----------------------
src/core/nm-l3-config-data.h | 1 -
src/core/nm-l3-ipv4ll.c | 2 +-
src/core/nm-l3-ipv6ll.c | 9 +++----
src/core/nm-l3cfg.c | 32 +++-------------------
src/core/nm-l3cfg.h | 9 -------
src/core/tests/test-l3cfg.c | 12 ++++-----
src/libnm-platform/nm-platform.c | 46 ++++++++++----------------------
src/libnm-platform/nm-platform.h | 5 ----
src/libnm-platform/nmp-object.h | 15 -----------
11 files changed, 34 insertions(+), 137 deletions(-)
diff --git a/src/core/devices/nm-device.c b/src/core/devices/nm-device.c
index a11486d54b..264d75d936 100644
--- a/src/core/devices/nm-device.c
+++ b/src/core/devices/nm-device.c
@@ -3976,7 +3976,9 @@ _dev_l3_cfg_commit_type_reset(NMDevice *self)
commit_type = NM_L3_CFG_COMMIT_TYPE_NONE;
goto do_set;
case NM_DEVICE_SYS_IFACE_STATE_ASSUME:
- commit_type = NM_L3_CFG_COMMIT_TYPE_ASSUME;
+ /* TODO: NM_DEVICE_SYS_IFACE_STATE_ASSUME, will be dropped from the code.
+ * Meanwhile, the commit type must be updated. */
+ commit_type = NM_L3_CFG_COMMIT_TYPE_UPDATE;
goto do_set;
case NM_DEVICE_SYS_IFACE_STATE_MANAGED:
commit_type = NM_L3_CFG_COMMIT_TYPE_UPDATE;
diff --git a/src/core/nm-l3-config-data.c b/src/core/nm-l3-config-data.c
index 03593ea28c..1cabdb6c9b 100644
--- a/src/core/nm-l3-config-data.c
+++ b/src/core/nm-l3-config-data.c
@@ -1172,13 +1172,6 @@ _l3_config_data_add_obj(NMDedupMultiIndex *multi_idx,
modified = TRUE;
}
- /* OR assume_config_once flag */
- if (obj_new->ip_address.a_assume_config_once
- && !obj_old->ip_address.a_assume_config_once) {
- obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
- obj_new_stackinit.ip_address.a_assume_config_once = TRUE;
- modified = TRUE;
- }
break;
case NMP_OBJECT_TYPE_IP4_ROUTE:
case NMP_OBJECT_TYPE_IP6_ROUTE:
@@ -1189,13 +1182,6 @@ _l3_config_data_add_obj(NMDedupMultiIndex *multi_idx,
modified = TRUE;
}
- /* OR assume_config_once flag */
- if (obj_new->ip_route.r_assume_config_once
- && !obj_old->ip_route.r_assume_config_once) {
- obj_new = nmp_object_stackinit_obj(&obj_new_stackinit, obj_new);
- obj_new_stackinit.ip_route.r_assume_config_once = TRUE;
- modified = TRUE;
- }
break;
default:
nm_assert_not_reached();
@@ -3056,9 +3042,8 @@ nm_l3_config_data_merge(NML3ConfigData *self,
const NMPlatformIPAddress *a_src = NMP_OBJECT_CAST_IP_ADDRESS(obj);
NMPlatformIPXAddress a;
NML3ConfigMergeHookResult hook_result = {
- .ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT,
- .assume_config_once = NM_OPTION_BOOL_DEFAULT,
- .force_commit = NM_OPTION_BOOL_DEFAULT,
+ .ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT,
+ .force_commit = NM_OPTION_BOOL_DEFAULT,
};
#define _ensure_a() \
@@ -3091,12 +3076,6 @@ nm_l3_config_data_merge(NML3ConfigData *self,
a.a4.a_acd_not_ready = (!!hook_result.ip4acd_not_ready);
}
- if (hook_result.assume_config_once != NM_OPTION_BOOL_DEFAULT
- && (!!hook_result.assume_config_once) != a_src->a_assume_config_once) {
- _ensure_a();
- a.ax.a_assume_config_once = (!!hook_result.assume_config_once);
- }
-
if (hook_result.force_commit != NM_OPTION_BOOL_DEFAULT
&& (!!hook_result.force_commit) != a_src->a_force_commit) {
_ensure_a();
@@ -3121,9 +3100,8 @@ nm_l3_config_data_merge(NML3ConfigData *self,
const NMPlatformIPRoute *r_src = NMP_OBJECT_CAST_IP_ROUTE(obj);
NMPlatformIPXRoute r;
NML3ConfigMergeHookResult hook_result = {
- .ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT,
- .assume_config_once = NM_OPTION_BOOL_DEFAULT,
- .force_commit = NM_OPTION_BOOL_DEFAULT,
+ .ip4acd_not_ready = NM_OPTION_BOOL_DEFAULT,
+ .force_commit = NM_OPTION_BOOL_DEFAULT,
};
#define _ensure_r() \
@@ -3149,12 +3127,6 @@ nm_l3_config_data_merge(NML3ConfigData *self,
r.rx.ifindex = self->ifindex;
}
- if (hook_result.assume_config_once != NM_OPTION_BOOL_DEFAULT
- && (!!hook_result.assume_config_once) != r_src->r_assume_config_once) {
- _ensure_r();
- r.rx.r_assume_config_once = (!!hook_result.assume_config_once);
- }
-
if (hook_result.force_commit != NM_OPTION_BOOL_DEFAULT
&& (!!hook_result.force_commit) != r_src->r_force_commit) {
_ensure_r();
diff --git a/src/core/nm-l3-config-data.h b/src/core/nm-l3-config-data.h
index b7a1bb32f5..20a32c62aa 100644
--- a/src/core/nm-l3-config-data.h
+++ b/src/core/nm-l3-config-data.h
@@ -137,7 +137,6 @@ NML3ConfigData *nm_l3_config_data_new_from_platform(NMDedupMultiIndex *mu
typedef struct {
NMOptionBool ip4acd_not_ready;
- NMOptionBool assume_config_once;
NMOptionBool force_commit;
} NML3ConfigMergeHookResult;
diff --git a/src/core/nm-l3-ipv4ll.c b/src/core/nm-l3-ipv4ll.c
index 68cb17fb09..473f3c0f03 100644
--- a/src/core/nm-l3-ipv4ll.c
+++ b/src/core/nm-l3-ipv4ll.c
@@ -600,7 +600,7 @@ _l3cd_config_add(NML3IPv4LL *self)
nm_assert_not_reached();
self->l3cfg_commit_handle = nm_l3cfg_commit_type_register(self->l3cfg,
- NM_L3_CFG_COMMIT_TYPE_ASSUME,
+ NM_L3_CFG_COMMIT_TYPE_UPDATE,
self->l3cfg_commit_handle,
"ipv4ll");
nm_l3cfg_commit_on_idle_schedule(self->l3cfg, NM_L3_CFG_COMMIT_TYPE_AUTO);
diff --git a/src/core/nm-l3-ipv6ll.c b/src/core/nm-l3-ipv6ll.c
index 60da4ee8d7..2b9a1a0ef4 100644
--- a/src/core/nm-l3-ipv6ll.c
+++ b/src/core/nm-l3-ipv6ll.c
@@ -398,10 +398,7 @@ _lladdr_handle_changed(NML3IPv6LL *self)
* NML3IPv4LL, where we use NM_L3_CONFIG_MERGE_FLAGS_ONLY_FOR_ACD. The difference
* is that for IPv6 we let kernel do DAD, so we need to actually configure the
* address. For IPv4, we can run ACD without configuring anything in kernel,
- * and let the user decide how to proceed.
- *
- * Also in this case, we use the most graceful commit-type (NM_L3_CFG_COMMIT_TYPE_ASSUME),
- * but for that to work, we also need NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE flag. */
+ * and let the user decide how to proceed. */
l3cd = nm_l3_ipv6ll_get_l3cd(self);
@@ -421,7 +418,7 @@ _lladdr_handle_changed(NML3IPv6LL *self)
NM_DNS_PRIORITY_DEFAULT_NORMAL,
NM_L3_ACD_DEFEND_TYPE_ALWAYS,
0,
- NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE,
+ NM_L3CFG_CONFIG_FLAGS_NONE,
NM_L3_CONFIG_MERGE_FLAGS_NONE))
changed = TRUE;
} else {
@@ -430,7 +427,7 @@ _lladdr_handle_changed(NML3IPv6LL *self)
}
self->l3cfg_commit_handle = nm_l3cfg_commit_type_register(self->l3cfg,
- l3cd ? NM_L3_CFG_COMMIT_TYPE_ASSUME
+ l3cd ? NM_L3_CFG_COMMIT_TYPE_UPDATE
: NM_L3_CFG_COMMIT_TYPE_NONE,
self->l3cfg_commit_handle,
"ipv6ll");
diff --git a/src/core/nm-l3cfg.c b/src/core/nm-l3cfg.c
index eeb041d042..20058f2321 100644
--- a/src/core/nm-l3cfg.c
+++ b/src/core/nm-l3cfg.c
@@ -363,7 +363,6 @@ static NM_UTILS_ENUM2STR_DEFINE(_l3_cfg_commit_type_to_string,
NML3CfgCommitType,
NM_UTILS_ENUM2STR(NM_L3_CFG_COMMIT_TYPE_AUTO, "auto"),
NM_UTILS_ENUM2STR(NM_L3_CFG_COMMIT_TYPE_NONE, "none"),
- NM_UTILS_ENUM2STR(NM_L3_CFG_COMMIT_TYPE_ASSUME, "assume"),
NM_UTILS_ENUM2STR(NM_L3_CFG_COMMIT_TYPE_UPDATE, "update"),
NM_UTILS_ENUM2STR(NM_L3_CFG_COMMIT_TYPE_REAPPLY, "reapply"), );
@@ -768,14 +767,6 @@ _nm_n_acd_data_probe_new(NML3Cfg *self, in_addr_t addr, guint32 timeout_msec, gp
} \
G_STMT_END
-static gboolean
-_obj_state_data_get_assume_config_once(const ObjStateData *obj_state)
-{
- nm_assert_obj_state(NULL, obj_state);
-
- return nmp_object_get_assume_config_once(obj_state->obj);
-}
-
static ObjStateData *
_obj_state_data_new(const NMPObject *obj, const NMPObject *plobj)
{
@@ -1054,10 +1045,6 @@ _obj_states_sync_filter(NML3Cfg *self, const NMPObject *obj, NML3CfgCommitType c
nm_assert(c_list_is_empty(&obj_state->os_zombie_lst));
if (!obj_state->os_nm_configured) {
- if (commit_type == NM_L3_CFG_COMMIT_TYPE_ASSUME
- && !_obj_state_data_get_assume_config_once(obj_state))
- return FALSE;
-
obj_state->os_nm_configured = TRUE;
_LOGD("obj-state: configure-first-time: %s",
@@ -3088,7 +3075,6 @@ nm_l3cfg_commit_on_idle_schedule(NML3Cfg *self, NML3CfgCommitType commit_type)
nm_assert(NM_IS_L3CFG(self));
nm_assert(NM_IN_SET(commit_type,
NM_L3_CFG_COMMIT_TYPE_AUTO,
- NM_L3_CFG_COMMIT_TYPE_ASSUME,
NM_L3_CFG_COMMIT_TYPE_UPDATE,
NM_L3_CFG_COMMIT_TYPE_REAPPLY));
@@ -3503,7 +3489,6 @@ out_clear:
typedef struct {
NML3Cfg *self;
gconstpointer tag;
- bool assume_config_once;
bool to_commit;
bool force_commit_once;
} L3ConfigMergeHookAddObjData;
@@ -3523,11 +3508,9 @@ _l3_hook_add_obj_cb(const NML3ConfigData *l3cd,
nm_assert(obj);
nm_assert(hook_result);
nm_assert(hook_result->ip4acd_not_ready == NM_OPTION_BOOL_DEFAULT);
- nm_assert(hook_result->assume_config_once == NM_OPTION_BOOL_DEFAULT);
nm_assert(hook_result->force_commit == NM_OPTION_BOOL_DEFAULT);
- hook_result->assume_config_once = hook_data->assume_config_once;
- hook_result->force_commit = hook_data->force_commit_once;
+ hook_result->force_commit = hook_data->force_commit_once;
switch (NMP_OBJECT_GET_TYPE(obj)) {
case NMP_OBJECT_TYPE_IP4_ADDRESS:
@@ -3683,9 +3666,7 @@ _l3cfg_update_combined_config(NML3Cfg *self,
if (NM_FLAGS_HAS(l3cd_data->config_flags, NM_L3CFG_CONFIG_FLAGS_ONLY_FOR_ACD))
continue;
- hook_data.tag = l3cd_data->tag_confdata;
- hook_data.assume_config_once =
- NM_FLAGS_HAS(l3cd_data->config_flags, NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE);
+ hook_data.tag = l3cd_data->tag_confdata;
hook_data.force_commit_once = l3cd_data->force_commit_once;
nm_l3_config_data_merge(l3cd,
@@ -4212,8 +4193,7 @@ _l3_commit_one(NML3Cfg *self,
nm_assert(NM_IN_SET(commit_type,
NM_L3_CFG_COMMIT_TYPE_NONE,
NM_L3_CFG_COMMIT_TYPE_REAPPLY,
- NM_L3_CFG_COMMIT_TYPE_UPDATE,
- NM_L3_CFG_COMMIT_TYPE_ASSUME));
+ NM_L3_CFG_COMMIT_TYPE_UPDATE));
nm_assert_addr_family(addr_family);
_LOGT("committing IPv%c configuration (%s)",
@@ -4299,7 +4279,6 @@ _l3_commit(NML3Cfg *self, NML3CfgCommitType commit_type, gboolean is_idle)
nm_assert(NM_IN_SET(commit_type,
NM_L3_CFG_COMMIT_TYPE_NONE,
NM_L3_CFG_COMMIT_TYPE_AUTO,
- NM_L3_CFG_COMMIT_TYPE_ASSUME,
NM_L3_CFG_COMMIT_TYPE_UPDATE,
NM_L3_CFG_COMMIT_TYPE_REAPPLY));
nm_assert(self->priv.p->commit_reentrant_count == 0);
@@ -4423,10 +4402,7 @@ nm_l3cfg_commit_type_register(NML3Cfg *self,
char buf[64];
nm_assert(NM_IS_L3CFG(self));
- nm_assert(NM_IN_SET(commit_type,
- NM_L3_CFG_COMMIT_TYPE_NONE,
- NM_L3_CFG_COMMIT_TYPE_ASSUME,
- NM_L3_CFG_COMMIT_TYPE_UPDATE));
+ nm_assert(NM_IN_SET(commit_type, NM_L3_CFG_COMMIT_TYPE_NONE, NM_L3_CFG_COMMIT_TYPE_UPDATE));
/* It would be easy (and maybe convenient) to allow that @existing_handle
* can currently be registered on another NML3Cfg instance. But then we couldn't
diff --git a/src/core/nm-l3cfg.h b/src/core/nm-l3cfg.h
index 0ea6864661..f6ec39ced8 100644
--- a/src/core/nm-l3cfg.h
+++ b/src/core/nm-l3cfg.h
@@ -363,15 +363,6 @@ typedef enum _nm_packed {
/* Don't touch the interface. */
NM_L3_CFG_COMMIT_TYPE_NONE,
- /* ASSUME means to keep any pre-existing extra routes/addresses, while
- * also not adding routes/addresses that are not present yet. This is to
- * gracefully take over after restart, where the existing IP configuration
- * should not change.
- *
- * The flag NM_L3CFG_CONFIG_FLAGS_ASSUME_CONFIG_ONCE can make certain addresses/
- * routes commitable also during "assume". */
- NM_L3_CFG_COMMIT_TYPE_ASSUME,
-
/* UPDATE means to add new addresses/routes, while also removing addresses/routes
* that are no longer present (but were previously configured by NetworkManager).
* Routes/addresses that were removed externally won't be re-added, and routes/addresses
diff --git a/src/core/tests/test-l3cfg.c b/src/core/tests/test-l3cfg.c
index 5501079ec4..eebfbcf58e 100644
--- a/src/core/tests/test-l3cfg.c
+++ b/src/core/tests/test-l3cfg.c
@@ -382,13 +382,11 @@ test_l3cfg(gconstpointer test_data)
nm_l3cfg_commit_type_register(l3cfg0, NM_L3_CFG_COMMIT_TYPE_UPDATE, NULL, "test1");
if (!nmtst_get_rand_one_case_in(4)) {
- commit_type_2 =
- nm_l3cfg_commit_type_register(l3cfg0,
- nmtst_rand_select(NM_L3_CFG_COMMIT_TYPE_NONE,
- NM_L3_CFG_COMMIT_TYPE_ASSUME,
- NM_L3_CFG_COMMIT_TYPE_UPDATE),
- NULL,
- "test2");
+ commit_type_2 = nm_l3cfg_commit_type_register(
+ l3cfg0,
+ nmtst_rand_select(NM_L3_CFG_COMMIT_TYPE_NONE, NM_L3_CFG_COMMIT_TYPE_UPDATE),
+ NULL,
+ "test2");
} else
commit_type_2 = NULL;
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index 8459231dc2..b1ae168f66 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -6312,7 +6312,6 @@ nm_platform_ip4_address_to_string(const NMPlatformIP4Address *address, char *buf
"%s" /* label */
" src %s"
"%s" /* a_acd_not_ready */
- "%s" /* a_assume_config_once */
"%s" /* a_force_commit */
"",
s_address,
@@ -6332,7 +6331,6 @@ nm_platform_ip4_address_to_string(const NMPlatformIP4Address *address, char *buf
str_label,
nmp_utils_ip_config_source_to_string(address->addr_source, s_source, sizeof(s_source)),
address->a_acd_not_ready ? " ip4acd-not-ready" : "",
- address->a_assume_config_once ? " assume-config-once" : "",
address->a_force_commit ? " force-commit" : "");
g_free(str_peer);
return buf;
@@ -6453,7 +6451,6 @@ nm_platform_ip6_address_to_string(const NMPlatformIP6Address *address, char *buf
buf,
len,
"%s/%d lft %s pref %s%s%s%s%s src %s"
- "%s" /* a_assume_config_once */
"%s" /* a_force_commit */
"",
s_address,
@@ -6465,7 +6462,6 @@ nm_platform_ip6_address_to_string(const NMPlatformIP6Address *address, char *buf
str_dev,
_to_string_ifa_flags(address->n_ifa_flags, s_flags, sizeof(s_flags)),
nmp_utils_ip_config_source_to_string(address->addr_source, s_source, sizeof(s_source)),
- address->a_assume_config_once ? " assume-config-once" : "",
address->a_force_commit ? " force-commit" : "");
g_free(str_peer);
return buf;
@@ -6569,7 +6565,6 @@ nm_platform_ip4_route_to_string(const NMPlatformIP4Route *route, char *buf, gsiz
"%s" /* initcwnd */
"%s" /* initrwnd */
"%s" /* mtu */
- "%s" /* r_assume_config_once */
"%s" /* r_force_commit */
"",
nm_net_aux_rtnl_rtntype_n2a_maybe_buf(nm_platform_route_type_uncoerce(route->type_coerced),
@@ -6628,7 +6623,6 @@ nm_platform_ip4_route_to_string(const NMPlatformIP4Route *route, char *buf, gsiz
route->lock_mtu ? "lock " : "",
route->mtu)
: "",
- route->r_assume_config_once ? " assume-config-once" : "",
route->r_force_commit ? " force-commit" : "");
return buf;
}
@@ -6704,7 +6698,6 @@ nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsiz
"%s" /* initrwnd */
"%s" /* mtu */
"%s" /* pref */
- "%s" /* r_assume_config_once */
"%s" /* r_force_commit */
"",
nm_net_aux_rtnl_rtntype_n2a_maybe_buf(nm_platform_route_type_uncoerce(route->type_coerced),
@@ -6767,7 +6760,6 @@ nm_platform_ip6_route_to_string(const NMPlatformIP6Route *route, char *buf, gsiz
" pref %s",
nm_icmpv6_router_pref_to_string(route->rt_pref, str_pref2, sizeof(str_pref2)))
: "",
- route->r_assume_config_once ? " assume-config-once" : "",
route->r_force_commit ? " force-commit" : "");
return buf;
@@ -7923,7 +7915,6 @@ nm_platform_ip4_address_hash_update(const NMPlatformIP4Address *obj, NMHashState
NM_HASH_COMBINE_BOOLS(guint8,
obj->use_ip4_broadcast_address,
obj->a_acd_not_ready,
- obj->a_assume_config_once,
obj->a_force_commit));
nm_hash_update_strarr(h, obj->label);
}
@@ -7972,7 +7963,6 @@ nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a,
if (a->use_ip4_broadcast_address)
NM_CMP_FIELD(a, b, broadcast_address);
NM_CMP_FIELD_UNSAFE(a, b, a_acd_not_ready);
- NM_CMP_FIELD_UNSAFE(a, b, a_assume_config_once);
NM_CMP_FIELD_UNSAFE(a, b, a_force_commit);
}
return 0;
@@ -7983,18 +7973,17 @@ nm_platform_ip4_address_cmp(const NMPlatformIP4Address *a,
void
nm_platform_ip6_address_hash_update(const NMPlatformIP6Address *obj, NMHashState *h)
{
- nm_hash_update_vals(
- h,
- obj->ifindex,
- obj->addr_source,
- obj->timestamp,
- obj->lifetime,
- obj->preferred,
- obj->n_ifa_flags,
- obj->plen,
- obj->address,
- obj->peer_address,
- NM_HASH_COMBINE_BOOLS(guint8, obj->a_assume_config_once, obj->a_force_commit));
+ nm_hash_update_vals(h,
+ obj->ifindex,
+ obj->addr_source,
+ obj->timestamp,
+ obj->lifetime,
+ obj->preferred,
+ obj->n_ifa_flags,
+ obj->plen,
+ obj->address,
+ obj->peer_address,
+ NM_HASH_COMBINE_BOOLS(guint8, obj->a_force_commit));
}
int
@@ -8037,7 +8026,6 @@ nm_platform_ip6_address_cmp(const NMPlatformIP6Address *a,
NM_CMP_FIELD(a, b, preferred);
NM_CMP_FIELD(a, b, n_ifa_flags);
NM_CMP_FIELD(a, b, addr_source);
- NM_CMP_FIELD_UNSAFE(a, b, a_assume_config_once);
NM_CMP_FIELD_UNSAFE(a, b, a_force_commit);
}
return 0;
@@ -8142,7 +8130,7 @@ nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj,
obj->initrwnd,
obj->mtu,
obj->r_rtm_flags,
- NM_HASH_COMBINE_BOOLS(guint16,
+ NM_HASH_COMBINE_BOOLS(guint8,
obj->metric_any,
obj->table_any,
obj->lock_window,
@@ -8150,7 +8138,6 @@ nm_platform_ip4_route_hash_update(const NMPlatformIP4Route *obj,
obj->lock_initcwnd,
obj->lock_initrwnd,
obj->lock_mtu,
- obj->r_assume_config_once,
obj->r_force_commit));
break;
}
@@ -8241,10 +8228,8 @@ nm_platform_ip4_route_cmp(const NMPlatformIP4Route *a,
NM_CMP_FIELD(a, b, initcwnd);
NM_CMP_FIELD(a, b, initrwnd);
NM_CMP_FIELD(a, b, mtu);
- if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL) {
- NM_CMP_FIELD_UNSAFE(a, b, r_assume_config_once);
+ if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL)
NM_CMP_FIELD_UNSAFE(a, b, r_force_commit);
- }
break;
}
return 0;
@@ -8337,7 +8322,6 @@ nm_platform_ip6_route_hash_update(const NMPlatformIP6Route *obj,
obj->lock_initcwnd,
obj->lock_initrwnd,
obj->lock_mtu,
- obj->r_assume_config_once,
obj->r_force_commit),
obj->window,
obj->cwnd,
@@ -8421,10 +8405,8 @@ nm_platform_ip6_route_cmp(const NMPlatformIP6Route *a,
NM_CMP_DIRECT(_route_pref_normalize(a->rt_pref), _route_pref_normalize(b->rt_pref));
else
NM_CMP_FIELD(a, b, rt_pref);
- if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL) {
- NM_CMP_FIELD_UNSAFE(a, b, r_assume_config_once);
+ if (cmp_type == NM_PLATFORM_IP_ROUTE_CMP_TYPE_FULL)
NM_CMP_FIELD_UNSAFE(a, b, r_force_commit);
- }
break;
}
return 0;
diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h
index 203f8c7bbd..dcbafdc6e8 100644
--- a/src/libnm-platform/nm-platform.h
+++ b/src/libnm-platform/nm-platform.h
@@ -331,8 +331,6 @@ typedef enum {
/* Meta flags not honored by NMPlatform (netlink code). Instead, they can be
* used by the upper layers which use NMPlatformIPRoute to track addresses that
* should be configured. */ \
- /* Whether the address is should be configured once during assume. */ \
- bool a_assume_config_once : 1; \
bool a_force_commit : 1; \
\
guint8 plen; \
@@ -476,12 +474,9 @@ typedef union {
* This field overrides "table_coerced" field. If "table_any" is true, then
* the "table_coerced" field is ignored (unlike for the metric). */ \
bool table_any : 1; \
- \
/* Meta flags not honored by NMPlatform (netlink code). Instead, they can be
* used by the upper layers which use NMPlatformIPRoute to track routes that
* should be configured. */ \
- /* Whether the route is should be configured once during assume. */ \
- bool r_assume_config_once : 1; \
/* Whether the route should be committed even if it was removed externally. */ \
bool r_force_commit : 1; \
\
diff --git a/src/libnm-platform/nmp-object.h b/src/libnm-platform/nmp-object.h
index 784dcc2dec..36d7fefb72 100644
--- a/src/libnm-platform/nmp-object.h
+++ b/src/libnm-platform/nmp-object.h
@@ -1097,21 +1097,6 @@ nm_platform_lookup_object_by_addr_family(NMPlatform *platform,
/*****************************************************************************/
-static inline gboolean
-nmp_object_get_assume_config_once(const NMPObject *obj)
-{
- switch (NMP_OBJECT_GET_TYPE(obj)) {
- case NMP_OBJECT_TYPE_IP4_ADDRESS:
- case NMP_OBJECT_TYPE_IP6_ADDRESS:
- return NMP_OBJECT_CAST_IP_ADDRESS(obj)->a_assume_config_once;
- case NMP_OBJECT_TYPE_IP4_ROUTE:
- case NMP_OBJECT_TYPE_IP6_ROUTE:
- return NMP_OBJECT_CAST_IP_ROUTE(obj)->r_assume_config_once;
- default:
- return nm_assert_unreachable_val(FALSE);
- }
-}
-
static inline gboolean
nmp_object_get_force_commit(const NMPObject *obj)
{
--
2.35.1