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.
This commit is contained in:
@@ -3125,6 +3125,60 @@ nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr addr
|
|||||||
return NMP_OBJECT_CAST_IP6_ADDRESS (obj);
|
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
|
static int
|
||||||
array_ip6_address_position (const GPtrArray *addresses,
|
array_ip6_address_position (const GPtrArray *addresses,
|
||||||
const NMPlatformIP6Address *address,
|
const NMPlatformIP6Address *address,
|
||||||
@@ -3336,39 +3390,8 @@ nm_platform_ip4_address_sync (NMPlatform *self,
|
|||||||
|
|
||||||
_CHECK_SELF (self, klass, FALSE);
|
_CHECK_SELF (self, klass, FALSE);
|
||||||
|
|
||||||
if (known_addresses) {
|
if (!_addr_array_clean_expired (AF_INET, ifindex, known_addresses, now, &known_addresses_idx))
|
||||||
/* remove all addresses that are already expired. */
|
known_addresses = NULL;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
plat_addresses = nm_platform_lookup_clone (self,
|
plat_addresses = nm_platform_lookup_clone (self,
|
||||||
nmp_lookup_init_object (&lookup,
|
nmp_lookup_init_object (&lookup,
|
||||||
|
Reference in New Issue
Block a user