summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-07-11 14:25:08 +0200
committerThomas Haller <thaller@redhat.com>2017-07-25 06:44:12 +0200
commit5fcca9ba3e37152b9fbe645a8436cacbcf846dc5 (patch)
tree8817c6fe9134bba3ca2e39815714099d9febe5e2
parentf749920f9c2f13d9d1762a832b08bb626b8aa922 (diff)
downloadNetworkManager-5fcca9ba3e37152b9fbe645a8436cacbcf846dc5.tar.gz
platform: refactor nm_platform_ip4_address_sync()
To reuse array of NMPObject instances instead of creating a GArray clone. Also get rid of the nm_platform_ipx_address_get_all() functions.
-rw-r--r--src/nm-ip4-config.c33
-rw-r--r--src/nm-ip6-config.c17
-rw-r--r--src/platform/nm-platform.c421
-rw-r--r--src/platform/nm-platform.h6
-rw-r--r--src/platform/tests/test-address.c8
-rw-r--r--src/platform/tests/test-cleanup.c8
-rw-r--r--src/platform/tests/test-common.c30
-rw-r--r--src/platform/tests/test-common.h3
8 files changed, 297 insertions, 229 deletions
diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c
index ee79d0bd1a..ec47f0e9a0 100644
--- a/src/nm-ip4-config.c
+++ b/src/nm-ip4-config.c
@@ -654,30 +654,16 @@ nm_ip4_config_capture (NMDedupMultiIndex *multi_idx, NMPlatform *platform, int i
gboolean
nm_ip4_config_commit (const NMIP4Config *self, NMPlatform *platform, NMRouteManager *route_manager, int ifindex, gboolean routes_full_sync, gint64 default_route_metric)
{
- gs_unref_ptrarray GPtrArray *added_addresses = NULL;
- gs_unref_array GArray *addresses = NULL;
+ gs_unref_ptrarray GPtrArray *addresses = NULL;
const NMDedupMultiHeadEntry *head_entry;
g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (self != NULL, FALSE);
- /* Addresses */
- {
- NMDedupMultiIter iter;
-
- head_entry = nm_ip4_config_lookup_addresses (self);
- addresses = g_array_sized_new (FALSE, FALSE,
- sizeof (NMPlatformIP4Address),
- head_entry ? head_entry->len : 0);
- nm_dedup_multi_iter_for_each (&iter, head_entry) {
- g_array_append_vals (addresses,
- NMP_OBJECT_CAST_IP4_ADDRESS (iter.current->obj),
- 1);
- }
- }
+ addresses = nm_dedup_multi_objs_to_ptr_array_head (nm_ip4_config_lookup_addresses (self),
+ NULL, NULL);
- nm_platform_ip4_address_sync (platform, ifindex, addresses,
- default_route_metric >= 0 ? &added_addresses : NULL);
+ nm_platform_ip4_address_sync (platform, ifindex, addresses);
/* Routes */
{
@@ -691,14 +677,19 @@ nm_ip4_config_commit (const NMIP4Config *self, NMPlatform *platform, NMRouteMana
routes = g_array_sized_new (FALSE, FALSE, sizeof (NMPlatformIP4Route), head_entry ? head_entry->len : 0);
if ( default_route_metric >= 0
- && added_addresses) {
+ && addresses) {
/* For IPv6, we explicitly add the device-routes (onlink) to NMIP6Config.
* As we don't do that for IPv4, add it here shortly before syncing
* the routes. For NMRouteManager these routes are very much important. */
- for (i = 0; i < added_addresses->len; i++) {
- const NMPlatformIP4Address *addr = added_addresses->pdata[i];
+ for (i = 0; i < addresses->len; i++) {
+ const NMPObject *o = addresses->pdata[i];
+ const NMPlatformIP4Address *addr;
NMPlatformIP4Route route = { 0 };
+ if (!o)
+ continue;
+
+ addr = NMP_OBJECT_CAST_IP4_ADDRESS (o);
if (addr->plen == 0)
continue;
diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c
index 03a55de891..b4ac4873e2 100644
--- a/src/nm-ip6-config.c
+++ b/src/nm-ip6-config.c
@@ -509,26 +509,15 @@ nm_ip6_config_commit (const NMIP6Config *self,
int ifindex,
gboolean routes_full_sync)
{
- gs_unref_array GArray *addresses = NULL;
+ gs_unref_ptrarray GPtrArray *addresses = NULL;
const NMDedupMultiHeadEntry *head_entry;
g_return_val_if_fail (ifindex > 0, FALSE);
g_return_val_if_fail (self != NULL, FALSE);
/* Addresses */
- {
- NMDedupMultiIter iter;
-
- head_entry = nm_ip6_config_lookup_addresses (self);
- addresses = g_array_sized_new (FALSE, FALSE,
- sizeof (NMPlatformIP6Address),
- head_entry ? head_entry->len : 0);
- nm_dedup_multi_iter_for_each (&iter, head_entry) {
- g_array_append_vals (addresses,
- NMP_OBJECT_CAST_IP6_ADDRESS (iter.current->obj),
- 1);
- }
- }
+ addresses = nm_dedup_multi_objs_to_ptr_array_head (nm_ip6_config_lookup_addresses (self),
+ NULL, NULL);
nm_platform_ip6_address_sync (platform, ifindex, addresses, TRUE);
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 176f377bdb..5c330c432f 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -2831,40 +2831,6 @@ nm_platform_ip6_address_get_peer (const NMPlatformIP6Address *addr)
return &addr->peer_address;
}
-static GArray *
-ipx_address_get_all (NMPlatform *self, int ifindex, NMPObjectType obj_type)
-{
- NMPLookup lookup;
-
- nm_assert (NM_IN_SET (obj_type, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS));
- nmp_lookup_init_addrroute (&lookup,
- obj_type,
- ifindex);
- return nmp_cache_lookup_to_array (nmp_cache_lookup (nm_platform_get_cache (self), &lookup),
- obj_type,
- FALSE /*addresses are always visible. */);
-}
-
-GArray *
-nm_platform_ip4_address_get_all (NMPlatform *self, int ifindex)
-{
- _CHECK_SELF (self, klass, NULL);
-
- g_return_val_if_fail (ifindex > 0, NULL);
-
- return ipx_address_get_all (self, ifindex, NMP_OBJECT_TYPE_IP4_ADDRESS);
-}
-
-GArray *
-nm_platform_ip6_address_get_all (NMPlatform *self, int ifindex)
-{
- _CHECK_SELF (self, klass, NULL);
-
- g_return_val_if_fail (ifindex > 0, NULL);
-
- return ipx_address_get_all (self, ifindex, NMP_OBJECT_TYPE_IP6_ADDRESS);
-}
-
gboolean
nm_platform_ip4_address_add (NMPlatform *self,
int ifindex,
@@ -3004,37 +2970,14 @@ nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr addr
return NMP_OBJECT_CAST_IP6_ADDRESS (obj);
}
-static const NMPlatformIP4Address *
-array_contains_ip4_address (const GArray *addresses, const NMPlatformIP4Address *address, gint32 now)
-{
- guint len = addresses ? addresses->len : 0;
- guint i;
-
- for (i = 0; i < len; i++) {
- const NMPlatformIP4Address *candidate = &g_array_index (addresses, NMPlatformIP4Address, i);
-
- if ( candidate->address == address->address
- && candidate->plen == address->plen
- && ((candidate->peer_address ^ address->peer_address) & nm_utils_ip4_prefix_to_netmask (address->plen)) == 0) {
- guint32 lifetime, preferred;
-
- if (nm_utils_lifetime_get (candidate->timestamp, candidate->lifetime, candidate->preferred,
- now, &lifetime, &preferred))
- return candidate;
- }
- }
-
- return NULL;
-}
-
static gboolean
-array_contains_ip6_address (const GArray *addresses, const NMPlatformIP6Address *address, gint32 now)
+array_contains_ip6_address (const GPtrArray *addresses, const NMPlatformIP6Address *address, gint32 now)
{
guint len = addresses ? addresses->len : 0;
guint i;
for (i = 0; i < len; i++) {
- NMPlatformIP6Address *candidate = &g_array_index (addresses, NMPlatformIP6Address, i);
+ NMPlatformIP6Address *candidate = NMP_OBJECT_CAST_IP6_ADDRESS (addresses->pdata[i]);
if (IN6_ARE_ADDR_EQUAL (&candidate->address, &address->address) && candidate->plen == address->plen) {
guint32 lifetime, preferred;
@@ -3049,69 +2992,100 @@ array_contains_ip6_address (const GArray *addresses, const NMPlatformIP6Address
}
static gboolean
-_ptr_inside_ip4_addr_array (const GArray *array, gconstpointer needle)
+ip4_addr_subnets_is_plain_address (const GPtrArray *addresses, gconstpointer needle)
+{
+ return needle >= (gconstpointer) &addresses->pdata[0]
+ && needle < (gconstpointer) &addresses->pdata[addresses->len];
+}
+
+static const NMPObject **
+ip4_addr_subnets_addr_list_get (const GPtrArray *addr_list, guint idx)
{
- return needle >= (gconstpointer) &g_array_index (array, const NMPlatformIP4Address, 0)
- && needle < (gconstpointer) &g_array_index (array, const NMPlatformIP4Address, array->len);
+ nm_assert (addr_list);
+ nm_assert (addr_list->len > 1);
+ nm_assert (idx < addr_list->len);
+ nm_assert (addr_list->pdata[idx]);
+ nm_assert ( !(*((gpointer *) addr_list->pdata[idx]))
+ || NMP_OBJECT_CAST_IP4_ADDRESS (*((gpointer *) addr_list->pdata[idx])));
+ nm_assert (idx == 0 || ip4_addr_subnets_addr_list_get (addr_list, idx - 1));
+ return addr_list->pdata[idx];
}
static void
-ip4_addr_subnets_destroy_index (GHashTable *ht, const GArray *addresses)
+ip4_addr_subnets_destroy_index (GHashTable *subnets, const GPtrArray *addresses)
{
GHashTableIter iter;
gpointer p;
- g_hash_table_iter_init (&iter, ht);
+ if (!subnets)
+ return;
+ g_hash_table_iter_init (&iter, subnets);
while (g_hash_table_iter_next (&iter, NULL, &p)) {
- if (!_ptr_inside_ip4_addr_array (addresses, p)) {
+ if (!ip4_addr_subnets_is_plain_address (addresses, p))
g_ptr_array_free ((GPtrArray *) p, TRUE);
- }
}
- g_hash_table_unref (ht);
+ g_hash_table_unref (subnets);
}
static GHashTable *
-ip4_addr_subnets_build_index (const GArray *addresses, gboolean consider_flags)
+ip4_addr_subnets_build_index (const GPtrArray *addresses,
+ gboolean consider_flags,
+ gboolean full_index)
{
- const NMPlatformIP4Address *address;
- gpointer p;
GHashTable *subnets;
- GPtrArray *ptr;
- guint32 net;
guint i;
- gint position;
- if (!addresses)
- return NULL;
+ nm_assert (addresses && addresses->len);
- subnets = g_hash_table_new_full (g_direct_hash,
- g_direct_equal,
- NULL,
- NULL);
+ subnets = g_hash_table_new (NULL, NULL);
/* Build a hash table of all addresses per subnet */
for (i = 0; i < addresses->len; i++) {
- address = &g_array_index (addresses, const NMPlatformIP4Address, i);
+ 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]);
+
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), (gpointer) address);
+ g_hash_table_insert (subnets, GUINT_TO_POINTER (net), p_address);
continue;
}
- if (_ptr_inside_ip4_addr_array (addresses, p)) {
- ptr = g_ptr_array_new ();
- g_hash_table_insert (subnets, GUINT_TO_POINTER (net), ptr);
- g_ptr_array_add (ptr, p);
- } else
- ptr = p;
-
- if (!consider_flags || NM_FLAGS_HAS (address->n_ifa_flags, IFA_F_SECONDARY))
- position = -1; /* append */
- else
- position = 0; /* prepend */
-
- g_ptr_array_insert (ptr, position, (gpointer) address);
+ nm_assert (p);
+
+ 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_ptr_array_add (addr_list, p);
+ } else
+ addr_list = p;
+
+ if ( !consider_flags
+ || NM_FLAGS_HAS (address->n_ifa_flags, IFA_F_SECONDARY))
+ position = -1; /* append */
+ else
+ position = 0; /* prepend */
+ g_ptr_array_insert (addr_list, position, p_address);
+ } else {
+ /* we only care about the primay. 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);
+ }
+ }
}
return subnets;
@@ -3130,22 +3104,32 @@ ip4_addr_subnets_build_index (const GArray *addresses, gboolean consider_flags)
* Returns: %TRUE if the address is secondary, %FALSE otherwise
*/
static gboolean
-ip4_addr_subnets_is_secondary (const NMPlatformIP4Address *address, GHashTable *subnets, const GArray *addresses, GPtrArray **out_addr_list)
-{
- GPtrArray *addr_list;
- gpointer p;
+ip4_addr_subnets_is_secondary (const NMPObject *address,
+ GHashTable *subnets,
+ 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);
- net = address->address & nm_utils_ip4_prefix_to_netmask (address->plen);
+ net = a->address & nm_utils_ip4_prefix_to_netmask (a->plen);
p = g_hash_table_lookup (subnets, GUINT_TO_POINTER (net));
nm_assert (p);
- if (!_ptr_inside_ip4_addr_array (addresses, p)) {
+ if (!ip4_addr_subnets_is_plain_address (addresses, p)) {
addr_list = p;
+ nm_assert (addr_list->len > 1);
NM_SET_OUT (out_addr_list, addr_list);
- if (addr_list->pdata[0] != address)
+ o = ip4_addr_subnets_addr_list_get (addr_list, 0);
+ nm_assert (o && *o);
+ if (*o != address)
return TRUE;
} else {
- nm_assert ((gconstpointer) address == p);
+ nm_assert (address == *((gconstpointer *) p));
NM_SET_OUT (out_addr_list, NULL);
}
return FALSE;
@@ -3155,11 +3139,14 @@ ip4_addr_subnets_is_secondary (const NMPlatformIP4Address *address, GHashTable *
* nm_platform_ip4_address_sync:
* @self: platform instance
* @ifindex: Interface index
- * @known_addresses: List of addresses
- * @out_added_addresses: (out): (allow-none): if not %NULL, return a #GPtrArray
- * with the addresses added. The pointers point into @known_addresses.
- * It possibly does not contain all addresses from @known_address because
- * some addresses might be expired.
+ * @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 succesfully added.
+ * Addresses are removed by unrefing the instance via nmp_object_unref()
+ * and leaving a NULL tombstone.
*
* A convenience function to synchronize addresses for a specific interface
* with the least possible disturbance. It simply removes addresses that are
@@ -3168,102 +3155,162 @@ ip4_addr_subnets_is_secondary (const NMPlatformIP4Address *address, GHashTable *
* Returns: %TRUE on success.
*/
gboolean
-nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, GPtrArray **out_added_addresses)
+nm_platform_ip4_address_sync (NMPlatform *self,
+ int ifindex,
+ GPtrArray *known_addresses)
{
- GArray *addresses;
- NMPlatformIP4Address *address;
+ gs_unref_ptrarray GPtrArray *plat_addresses = NULL;
const NMPlatformIP4Address *known_address;
gint32 now = nm_utils_get_monotonic_timestamp_s ();
- GHashTable *plat_subnets;
- GHashTable *known_subnets;
- GPtrArray *ptr;
- int i, j;
+ GHashTable *plat_subnets = NULL;
+ GHashTable *known_subnets = NULL;
+ gs_unref_hashtable GHashTable *known_addresses_idx = NULL;
+ guint i, j, len;
+ NMPLookup lookup;
+ guint32 lifetime, preferred;
_CHECK_SELF (self, klass, FALSE);
- addresses = nm_platform_ip4_address_get_all (self, ifindex);
- plat_subnets = ip4_addr_subnets_build_index (addresses, TRUE);
- known_subnets = ip4_addr_subnets_build_index (known_addresses, 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, &lifetime, &preferred))
+ goto delete_and_next;
+
+ if (G_UNLIKELY (!known_addresses_idx)) {
+ known_addresses_idx = g_hash_table_new ((GHashFunc) nmp_object_hash,
+ (GEqualFunc) nmp_object_equal);
+ }
+ if (!nm_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,
+ nmp_lookup_init_addrroute (&lookup,
+ NMP_OBJECT_TYPE_IP4_ADDRESS,
+ ifindex),
+ NULL, NULL);
+ if (plat_addresses)
+ plat_subnets = ip4_addr_subnets_build_index (plat_addresses, TRUE, TRUE);
/* Delete unknown addresses */
- for (i = 0; i < addresses->len; i++) {
- address = &g_array_index (addresses, NMPlatformIP4Address, i);
+ len = plat_addresses ? plat_addresses->len : 0;
+ for (i = 0; i < len; i++) {
+ const NMPObject *plat_obj;
+ const NMPlatformIP4Address *plat_address;
+ const GPtrArray *addr_list;
- if (!address->ifindex) {
+ plat_obj = plat_addresses->pdata[i];
+ if (!plat_obj) {
/* Already deleted */
continue;
}
- known_address = array_contains_ip4_address (known_addresses, address, now);
- if (known_address) {
- gboolean secondary;
+ plat_address = NMP_OBJECT_CAST_IP4_ADDRESS (plat_obj);
- secondary = ip4_addr_subnets_is_secondary (known_address, known_subnets, known_addresses, NULL);
- /* Ignore the matching address if it has a different primary/slave
- * role. */
- if (secondary != NM_FLAGS_HAS (address->n_ifa_flags, IFA_F_SECONDARY))
- known_address = NULL;
+ if (known_addresses) {
+ const NMPObject *o;
+
+ 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);
+
+ 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;
+ }
+ }
}
- if (!known_address) {
- nm_platform_ip4_address_delete (self, ifindex,
- address->address,
- address->plen,
- address->peer_address);
- if ( !ip4_addr_subnets_is_secondary (address, plat_subnets, addresses, &ptr)
- && ptr) {
- /* If we just deleted a primary addresses and there were
- * secondary ones the kernel can do two things, depending on
- * version and sysctl setting: delete also secondary addresses
- * or promote a secondary to primary. Ensure that secondary
- * addresses are deleted, so that we can start with a clean
- * slate and add addresses in the right order. */
- for (j = 1; j < ptr->len; j++) {
- address = ptr->pdata[j];
+ nm_platform_ip4_address_delete (self, ifindex,
+ plat_address->address,
+ plat_address->plen,
+ plat_address->peer_address);
+
+ if ( !ip4_addr_subnets_is_secondary (plat_obj, plat_subnets, plat_addresses, &addr_list)
+ && addr_list) {
+ /* If we just deleted a primary addresses and there were
+ * secondary ones the kernel can do two things, depending on
+ * version and sysctl setting: delete also secondary addresses
+ * or promote a secondary to primary. Ensure that secondary
+ * 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;
+
+ o = ip4_addr_subnets_addr_list_get (addr_list, j);
+ nm_assert (o);
+
+ if (*o) {
+ const NMPlatformIP4Address *a;
+
+ a = NMP_OBJECT_CAST_IP4_ADDRESS (*o);
nm_platform_ip4_address_delete (self, ifindex,
- address->address,
- address->plen,
- address->peer_address);
- address->ifindex = 0;
+ a->address,
+ a->plen,
+ a->peer_address);
+ nmp_object_unref (*o);
+ *o = NULL;
}
}
}
}
- ip4_addr_subnets_destroy_index (plat_subnets, addresses);
- g_array_free (addresses, TRUE);
-
- if (out_added_addresses)
- *out_added_addresses = NULL;
+ ip4_addr_subnets_destroy_index (plat_subnets, plat_addresses);
+ ip4_addr_subnets_destroy_index (known_subnets, known_addresses);
if (!known_addresses)
return TRUE;
/* Add missing addresses */
for (i = 0; i < known_addresses->len; i++) {
- guint32 lifetime, preferred;
+ const NMPObject *o;
+
+ o = known_addresses->pdata[i];
+ if (!o)
+ continue;
- known_address = &g_array_index (known_addresses, NMPlatformIP4Address, i);
+ known_address = NMP_OBJECT_CAST_IP4_ADDRESS (o);
if (!nm_utils_lifetime_get (known_address->timestamp, known_address->lifetime, known_address->preferred,
now, &lifetime, &preferred))
- continue;
+ goto delete_and_next2;
if (!nm_platform_ip4_address_add (self, ifindex, known_address->address, known_address->plen,
known_address->peer_address, lifetime, preferred,
- 0, known_address->label)) {
- ip4_addr_subnets_destroy_index (known_subnets, known_addresses);
- return FALSE;
- }
+ 0, known_address->label))
+ goto delete_and_next2;
- if (out_added_addresses) {
- if (!*out_added_addresses)
- *out_added_addresses = g_ptr_array_new ();
- g_ptr_array_add (*out_added_addresses, (gpointer) known_address);
- }
+ continue;
+delete_and_next2:
+ nmp_object_unref (o);
+ known_addresses->pdata[i] = NULL;
}
- ip4_addr_subnets_destroy_index (known_subnets, known_addresses);
-
return TRUE;
}
@@ -3271,7 +3318,8 @@ nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known
* nm_platform_ip6_address_sync:
* @self: platform instance
* @ifindex: Interface index
- * @known_addresses: List of addresses
+ * @known_addresses: List of IPv6 addresses, as NMPObject. The list
+ * is not modified.
* @keep_link_local: Don't remove link-local address
*
* A convenience function to synchronize addresses for a specific interface
@@ -3281,33 +3329,42 @@ nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known
* Returns: %TRUE on success.
*/
gboolean
-nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, gboolean keep_link_local)
+nm_platform_ip6_address_sync (NMPlatform *self,
+ int ifindex,
+ const GPtrArray *known_addresses,
+ gboolean keep_link_local)
{
- GArray *addresses;
+ gs_unref_ptrarray GPtrArray *plat_addresses = NULL;
NMPlatformIP6Address *address;
gint32 now = nm_utils_get_monotonic_timestamp_s ();
- int i;
+ guint i;
+ NMPLookup lookup;
/* Delete unknown addresses */
- addresses = nm_platform_ip6_address_get_all (self, ifindex);
- for (i = 0; i < addresses->len; i++) {
- address = &g_array_index (addresses, NMPlatformIP6Address, i);
-
- /* Leave link local address management to the kernel */
- if (keep_link_local && IN6_IS_ADDR_LINKLOCAL (&address->address))
- continue;
+ plat_addresses = nm_platform_lookup_clone (self,
+ nmp_lookup_init_addrroute (&lookup,
+ NMP_OBJECT_TYPE_IP6_ADDRESS,
+ ifindex),
+ NULL, NULL);
+ if (plat_addresses) {
+ for (i = 0; i < plat_addresses->len; i++) {
+ address = NMP_OBJECT_CAST_IP6_ADDRESS (plat_addresses->pdata[i]);
+
+ /* Leave link local address management to the kernel */
+ if (keep_link_local && IN6_IS_ADDR_LINKLOCAL (&address->address))
+ continue;
- if (!array_contains_ip6_address (known_addresses, address, now))
- nm_platform_ip6_address_delete (self, ifindex, address->address, address->plen);
+ if (!array_contains_ip6_address (known_addresses, address, now))
+ nm_platform_ip6_address_delete (self, ifindex, address->address, address->plen);
+ }
}
- g_array_free (addresses, TRUE);
if (!known_addresses)
return TRUE;
/* Add missing addresses */
for (i = 0; i < known_addresses->len; i++) {
- const NMPlatformIP6Address *known_address = &g_array_index (known_addresses, NMPlatformIP6Address, i);
+ const NMPlatformIP6Address *known_address = NMP_OBJECT_CAST_IP6_ADDRESS (known_addresses->pdata[i]);
guint32 lifetime, preferred;
if (NM_FLAGS_HAS (known_address->n_ifa_flags, IFA_F_TEMPORARY)) {
@@ -3333,7 +3390,7 @@ nm_platform_address_flush (NMPlatform *self, int ifindex)
{
_CHECK_SELF (self, klass, FALSE);
- return nm_platform_ip4_address_sync (self, ifindex, NULL, NULL)
+ return nm_platform_ip4_address_sync (self, ifindex, NULL)
&& nm_platform_ip6_address_sync (self, ifindex, NULL, FALSE);
}
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index f8297c0318..8ff6d5eda8 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -931,8 +931,6 @@ NMPlatformError nm_platform_link_sit_add (NMPlatform *self,
const NMPlatformLink **out_link);
const NMPlatformIP6Address *nm_platform_ip6_address_get (NMPlatform *self, int ifindex, struct in6_addr address);
-GArray *nm_platform_ip4_address_get_all (NMPlatform *self, int ifindex);
-GArray *nm_platform_ip6_address_get_all (NMPlatform *self, int ifindex);
gboolean nm_platform_ip4_address_add (NMPlatform *self,
int ifindex,
in_addr_t address,
@@ -952,8 +950,8 @@ gboolean nm_platform_ip6_address_add (NMPlatform *self,
guint32 flags);
gboolean nm_platform_ip4_address_delete (NMPlatform *self, int ifindex, in_addr_t address, guint8 plen, in_addr_t peer_address);
gboolean nm_platform_ip6_address_delete (NMPlatform *self, int ifindex, struct in6_addr address, guint8 plen);
-gboolean nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, GPtrArray **out_added_addresses);
-gboolean nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GArray *known_addresses, gboolean keep_link_local);
+gboolean nm_platform_ip4_address_sync (NMPlatform *self, int ifindex, GPtrArray *known_addresse);
+gboolean nm_platform_ip6_address_sync (NMPlatform *self, int ifindex, const GPtrArray *known_addresses, gboolean keep_link_local);
gboolean nm_platform_address_flush (NMPlatform *self, int ifindex);
const NMPlatformIP4Route *nm_platform_ip4_route_get (NMPlatform *self, int ifindex, in_addr_t network, guint8 plen, guint32 metric);
diff --git a/src/platform/tests/test-address.c b/src/platform/tests/test-address.c
index 2ff07b8dc4..93851ff7e8 100644
--- a/src/platform/tests/test-address.c
+++ b/src/platform/tests/test-address.c
@@ -102,7 +102,7 @@ test_ip4_address_general (void)
accept_signals (address_changed, 0, 1);
/* Test address listing */
- addresses = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
+ addresses = nmtstp_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
g_assert (addresses);
g_assert_cmpint (addresses->len, ==, 1);
address = &g_array_index (addresses, NMPlatformIP4Address, 0);
@@ -152,7 +152,7 @@ test_ip6_address_general (void)
accept_signals (address_changed, 0, 1);
/* Test address listing */
- addresses = nm_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex);
+ addresses = nmtstp_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex);
g_assert (addresses);
g_assert_cmpint (addresses->len, ==, 1);
address = &g_array_index (addresses, NMPlatformIP6Address, 0);
@@ -329,7 +329,7 @@ test_ip4_address_peer_zero (void)
nmtstp_ip4_address_add (NULL, EX, ifindex, addr, plen, r_peers[i], lifetime, preferred, 0, label);
- addrs = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
+ addrs = nmtstp_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
g_assert (addrs);
g_assert_cmpint (addrs->len, ==, i + 1);
g_array_unref (addrs);
@@ -344,7 +344,7 @@ test_ip4_address_peer_zero (void)
nmtstp_ip4_address_del (NULL, EX, ifindex, addr, plen, r_peers[i]);
- addrs = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
+ addrs = nmtstp_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
g_assert (addrs);
g_assert_cmpint (addrs->len, ==, G_N_ELEMENTS (peers) - i - 1);
g_array_unref (addrs);
diff --git a/src/platform/tests/test-cleanup.c b/src/platform/tests/test-cleanup.c
index 690ba35a53..937cd12c7d 100644
--- a/src/platform/tests/test-cleanup.c
+++ b/src/platform/tests/test-cleanup.c
@@ -70,8 +70,8 @@ test_cleanup_internal (void)
nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, network6, plen6, gateway6, in6addr_any, metric, mss);
nmtstp_ip6_route_add (NM_PLATFORM_GET, ifindex, NM_IP_CONFIG_SOURCE_USER, in6addr_any, 0, gateway6, in6addr_any, metric, mss);
- addresses4 = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
- addresses6 = nm_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex);
+ addresses4 = nmtstp_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
+ addresses6 = nmtstp_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex);
routes4 = nmtstp_ip4_route_get_all (NM_PLATFORM_GET, ifindex);
routes6 = nmtstp_ip6_route_get_all (NM_PLATFORM_GET, ifindex);
@@ -88,8 +88,8 @@ test_cleanup_internal (void)
/* Delete interface with all addresses and routes */
g_assert (nm_platform_link_delete (NM_PLATFORM_GET, ifindex));
- addresses4 = nm_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
- addresses6 = nm_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex);
+ addresses4 = nmtstp_platform_ip4_address_get_all (NM_PLATFORM_GET, ifindex);
+ addresses6 = nmtstp_platform_ip6_address_get_all (NM_PLATFORM_GET, ifindex);
routes4 = nmtstp_ip4_route_get_all (NM_PLATFORM_GET, ifindex);
routes6 = nmtstp_ip6_route_get_all (NM_PLATFORM_GET, ifindex);
diff --git a/src/platform/tests/test-common.c b/src/platform/tests/test-common.c
index 62c2c83fd1..10753f1f08 100644
--- a/src/platform/tests/test-common.c
+++ b/src/platform/tests/test-common.c
@@ -70,6 +70,36 @@ _init_platform (NMPlatform **platform, gboolean external_command)
/*****************************************************************************/
+static GArray *
+_ipx_address_get_all (NMPlatform *self, int ifindex, NMPObjectType obj_type)
+{
+ NMPLookup lookup;
+
+ g_assert (NM_IS_PLATFORM (self));
+ g_assert (ifindex > 0);
+ g_assert (NM_IN_SET (obj_type, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS));
+ nmp_lookup_init_addrroute (&lookup,
+ obj_type,
+ ifindex);
+ return nmp_cache_lookup_to_array (nm_platform_lookup (self, &lookup),
+ obj_type,
+ FALSE /*addresses are always visible. */);
+}
+
+GArray *
+nmtstp_platform_ip4_address_get_all (NMPlatform *self, int ifindex)
+{
+ return _ipx_address_get_all (self, ifindex, NMP_OBJECT_TYPE_IP4_ADDRESS);
+}
+
+GArray *
+nmtstp_platform_ip6_address_get_all (NMPlatform *self, int ifindex)
+{
+ return _ipx_address_get_all (self, ifindex, NMP_OBJECT_TYPE_IP6_ADDRESS);
+}
+
+/*****************************************************************************/
+
SignalData *
add_signal_full (const char *name, NMPlatformSignalChangeType change_type, GCallback callback, int ifindex, const char *ifname)
{
diff --git a/src/platform/tests/test-common.h b/src/platform/tests/test-common.h
index b9e879ff62..9cef6f358d 100644
--- a/src/platform/tests/test-common.h
+++ b/src/platform/tests/test-common.h
@@ -214,6 +214,9 @@ nmtstp_ip6_route_get_all (NMPlatform *platform,
/*****************************************************************************/
+GArray *nmtstp_platform_ip4_address_get_all (NMPlatform *self, int ifindex);
+GArray *nmtstp_platform_ip6_address_get_all (NMPlatform *self, int ifindex);
+
const NMPlatformLink *nmtstp_link_get_typed (NMPlatform *platform, int ifindex, const char *name, NMLinkType link_type);
const NMPlatformLink *nmtstp_link_get (NMPlatform *platform, int ifindex, const char *name);