summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2018-02-07 22:21:31 +0100
committerThomas Haller <thaller@redhat.com>2018-02-09 17:40:01 +0100
commit7f223cb82720cb04f7cd0de9d3759d0b76d4aa53 (patch)
tree25aa2ae895485f77eabcf4da28da47f010521702
parent7459548f2351a11f00f19c26fa98dc19e88258cd (diff)
downloadNetworkManager-7f223cb82720cb04f7cd0de9d3759d0b76d4aa53.tar.gz
platform: refactor initial cleanup of know-addresses list in nm_platform_ip4_address_sync()
We do a pre-run that constructs an index of all addresses and drops addresses that are already expired. Move this code to a separate function, it will be reused for IPv6. Also, note that nm_platform_ip4_address_sync() has only 2 callers. Both callers make sure to not pass duplicate known addresses, because the addresses also come from a cache. Make that a requirement and assert against unique addresses. If we would allow duplicate addresses, we would have to handle them in a defined way (like, dropping the ones with lower priority). That would be more complicated, and since no caller is supposed to provide duplicate addresses, don't bother but assert.
-rw-r--r--src/platform/nm-platform.c89
1 files changed, 56 insertions, 33 deletions
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index c475d07a11..8a53f7c6a4 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -3125,6 +3125,60 @@ nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr addr
return NMP_OBJECT_CAST_IP6_ADDRESS (obj);
}
+static gboolean
+_addr_array_clean_expired (int addr_family, int ifindex, GPtrArray *array, guint32 now, GHashTable **idx)
+{
+ guint i;
+ gboolean any_addrs = FALSE;
+
+ nm_assert_addr_family (addr_family);
+ nm_assert (ifindex > 0);
+ nm_assert (now > 0);
+
+ if (!array)
+ return FALSE;
+
+ /* remove all addresses that are already expired. */
+ for (i = 0; i < array->len; i++) {
+ const NMPlatformIPAddress *a = NMP_OBJECT_CAST_IP_ADDRESS (array->pdata[i]);
+
+#if NM_MORE_ASSERTS > 10
+ nm_assert (a);
+ nm_assert (a->ifindex == ifindex);
+ {
+ const NMPObject *o = NMP_OBJECT_UP_CAST (a);
+ guint j;
+
+ nm_assert (NMP_OBJECT_GET_CLASS (o)->addr_family == addr_family);
+ for (j = i + 1; j < array->len; j++) {
+ const NMPObject *o2 = array->pdata[j];
+
+ nm_assert (NMP_OBJECT_GET_TYPE (o) == NMP_OBJECT_GET_TYPE (o2));
+ nm_assert (!nmp_object_id_equal (o, o2));
+ }
+ }
+#endif
+
+ if (nm_utils_lifetime_get (a->timestamp, a->lifetime, a->preferred,
+ now, NULL)) {
+ if (idx) {
+ if (G_UNLIKELY (!*idx)) {
+ *idx = g_hash_table_new ((GHashFunc) nmp_object_id_hash,
+ (GEqualFunc) nmp_object_id_equal);
+ }
+ if (!g_hash_table_add (*idx, (gpointer) NMP_OBJECT_UP_CAST (a)))
+ nm_assert_not_reached ();
+ }
+ any_addrs = TRUE;
+ continue;
+ }
+
+ nmp_object_unref (g_steal_pointer (&array->pdata[i]));
+ }
+
+ return any_addrs;
+}
+
static int
array_ip6_address_position (const GPtrArray *addresses,
const NMPlatformIP6Address *address,
@@ -3336,39 +3390,8 @@ nm_platform_ip4_address_sync (NMPlatform *self,
_CHECK_SELF (self, klass, FALSE);
- if (known_addresses) {
- /* remove all addresses that are already expired. */
- for (i = 0; i < known_addresses->len; i++) {
- const NMPObject *o;
-
- o = known_addresses->pdata[i];
- nm_assert (o);
-
- known_address = NMP_OBJECT_CAST_IP4_ADDRESS (known_addresses->pdata[i]);
-
- if (!nm_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred,
- now, NULL))
- goto delete_and_next;
-
- if (G_UNLIKELY (!known_addresses_idx)) {
- known_addresses_idx = g_hash_table_new ((GHashFunc) nmp_object_id_hash,
- (GEqualFunc) nmp_object_id_equal);
- }
- if (!g_hash_table_insert (known_addresses_idx, (gpointer) o, (gpointer) o)) {
- /* duplicate? Keep only the first instance. */
- goto delete_and_next;
- }
-
- continue;
-delete_and_next:
- nmp_object_unref (o);
- known_addresses->pdata[i] = NULL;
- }
-
- if ( !known_addresses_idx
- || g_hash_table_size (known_addresses_idx) == 0)
- known_addresses = NULL;
- }
+ if (!_addr_array_clean_expired (AF_INET, ifindex, known_addresses, now, &known_addresses_idx))
+ known_addresses = NULL;
plat_addresses = nm_platform_lookup_clone (self,
nmp_lookup_init_object (&lookup,