diff options
author | Thomas Haller <thaller@redhat.com> | 2022-05-03 10:01:06 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-05-03 10:19:16 +0200 |
commit | 28f8320c66e506fd460fd979ebca93d98ff2464e (patch) | |
tree | 202306d8e9c14ef93b6c9a09a41893b7304be5f3 | |
parent | 0810b58c53b7b4f30c20e5f13ca419890e554b69 (diff) | |
parent | 34ce3421868b9ef55aea0d6b18dfa8a008c4fdc4 (diff) |
platform: merge branch 'th/platform-address-sync-one-by-one'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1200
(cherry picked from commit 7dda0b94bc6f89ad50e2a5421e4c126518a0b764)
-rw-r--r-- | src/libnm-platform/nm-platform.c | 69 |
1 files changed, 46 insertions, 23 deletions
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c index b29c07de84..84345b3c91 100644 --- a/src/libnm-platform/nm-platform.c +++ b/src/libnm-platform/nm-platform.c @@ -4029,9 +4029,10 @@ nm_platform_ip_address_sync(NMPlatform *self, gint32 now = 0; const int IS_IPv4 = NM_IS_IPv4(addr_family); NMPLookup lookup; - const gboolean EXTRA_LOGGING = FALSE; - gs_unref_hashtable GHashTable *known_addresses_idx = NULL; - gs_unref_ptrarray GPtrArray *plat_addresses = NULL; + const gboolean EXTRA_LOGGING = FALSE; + gs_unref_hashtable GHashTable *known_addresses_idx = NULL; + gs_unref_hashtable GHashTable *plat_addrs_to_delete = NULL; + gs_unref_ptrarray GPtrArray *plat_addresses = NULL; gboolean success; guint i_plat; guint i_know; @@ -4040,6 +4041,19 @@ nm_platform_ip_address_sync(NMPlatform *self, _CHECK_SELF(self, klass, FALSE); +#define _plat_addrs_to_delete_ensure(ptr) \ + ({ \ + GHashTable **_ptr = (ptr); \ + \ + if (!*_ptr) { \ + *_ptr = g_hash_table_new_full((GHashFunc) nmp_object_id_hash, \ + (GEqualFunc) nmp_object_id_equal, \ + (GDestroyNotify) nmp_object_unref, \ + NULL); \ + } \ + *_ptr; \ + }) + /* Disabled. Enable this for printf debugging. */ if (EXTRA_LOGGING) { char sbuf[NM_UTILS_TO_STRING_BUFFER_SIZE]; @@ -4197,11 +4211,8 @@ nm_platform_ip_address_sync(NMPlatform *self, } plat_handled[i] = TRUE; - nm_platform_ip4_address_delete(self, - ifindex, - plat_address->address, - plat_address->plen, - plat_address->peer_address); + g_hash_table_add(_plat_addrs_to_delete_ensure(&plat_addrs_to_delete), + (gpointer) nmp_object_ref(plat_obj)); if (!ip4_addr_subnets_is_secondary(plat_obj, plat_subnets, @@ -4231,12 +4242,11 @@ nm_platform_ip_address_sync(NMPlatform *self, 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)); + continue; } + + g_hash_table_add(_plat_addrs_to_delete_ensure(&plat_addrs_to_delete), + (gpointer) nmp_object_ref(*o)); } } } @@ -4272,7 +4282,10 @@ nm_platform_ip_address_sync(NMPlatform *self, * @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. */ + * removing and readding it. Thus, we need to delete plat_addr. + * + * We don't just add this address to @plat_addrs_to_delete, because + * it's too different. Instead, delete and re-add below. */ nm_platform_ip_address_delete(self, AF_INET6, ifindex, @@ -4298,9 +4311,9 @@ nm_platform_ip_address_sync(NMPlatform *self, i_know = nm_g_ptr_array_len(known_addresses); while (i_plat > 0) { - const NMPlatformIP6Address *plat_addr = - NMP_OBJECT_CAST_IP6_ADDRESS(plat_addresses->pdata[--i_plat]); - IP6AddrScope plat_scope; + const NMPObject *plat_obj = plat_addresses->pdata[--i_plat]; + const NMPlatformIP6Address *plat_addr = NMP_OBJECT_CAST_IP6_ADDRESS(plat_obj); + IP6AddrScope plat_scope; if (!plat_addr) continue; @@ -4313,7 +4326,6 @@ nm_platform_ip_address_sync(NMPlatform *self, } if (!delete_remaining_addrs) { - delete_remaining_addrs = TRUE; while (i_know > 0) { const NMPlatformIP6Address *know_addr = NMP_OBJECT_CAST_IP6_ADDRESS(known_addresses->pdata[--i_know]); @@ -4328,18 +4340,18 @@ nm_platform_ip_address_sync(NMPlatform *self, if (IN6_ARE_ADDR_EQUAL(&plat_addr->address, &know_addr->address)) { /* we have a match. Mark address as handled. */ - i_know++; - delete_remaining_addrs = FALSE; goto next_plat; } - /* plat_address has no match. Now delete_remaining_addrs is TRUE and we will - * delete all the remaining addresses with cur_scope. */ + /* "plat_address" has no match. "delete_remaining_addrs" will be set to TRUE and we will + * delete all the remaining addresses with "cur_scope". */ break; } + delete_remaining_addrs = TRUE; } - nm_platform_ip6_address_delete(self, ifindex, plat_addr->address, plat_addr->plen); + g_hash_table_add(_plat_addrs_to_delete_ensure(&plat_addrs_to_delete), + (gpointer) nmp_object_ref(plat_obj)); next_plat:; } } @@ -4384,6 +4396,17 @@ next_plat:; nm_assert(lifetime > 0); plat_obj = nm_platform_ip_address_get(self, addr_family, ifindex, known_address); + + if (plat_obj && nm_g_hash_table_contains(plat_addrs_to_delete, plat_obj)) { + /* This address exists, but it had the wrong priority earlier. We + * cannot just update it, we need to remove it first. */ + nm_platform_ip_address_delete(self, + addr_family, + ifindex, + NMP_OBJECT_CAST_IP_ADDRESS(plat_obj)); + plat_obj = NULL; + } + if (plat_obj && nm_platform_vtable_address.vx[IS_IPv4].address_cmp( known_address, |