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.
This commit is contained in:
Thomas Haller 2017-07-11 14:25:08 +02:00
parent f749920f9c
commit 5fcca9ba3e
8 changed files with 293 additions and 225 deletions

View file

@ -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;
addresses = nm_dedup_multi_objs_to_ptr_array_head (nm_ip4_config_lookup_addresses (self),
NULL, NULL);
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);
}
}
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;

View file

@ -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);

View file

@ -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) &g_array_index (array, const NMPlatformIP4Address, 0)
&& needle < (gconstpointer) &g_array_index (array, const NMPlatformIP4Address, array->len);
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)
{
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;
nm_assert (p);
if (!consider_flags || NM_FLAGS_HAS (address->n_ifa_flags, IFA_F_SECONDARY))
position = -1; /* append */
else
position = 0; /* prepend */
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;
g_ptr_array_insert (ptr, position, (gpointer) address);
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)
ip4_addr_subnets_is_secondary (const NMPObject *address,
GHashTable *subnets,
const GPtrArray *addresses,
const GPtrArray **out_addr_list)
{
GPtrArray *addr_list;
gpointer p;
const NMPlatformIP4Address *a;
const GPtrArray *addr_list;
gconstpointer p;
guint32 net;
const NMPObject **o;
net = address->address & nm_utils_ip4_prefix_to_netmask (address->plen);
a = NMP_OBJECT_CAST_IP4_ADDRESS (address);
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;
known_address = &g_array_index (known_addresses, NMPlatformIP4Address, i);
o = known_addresses->pdata[i];
if (!o)
continue;
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);
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;
/* 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);
}

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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)
{

View file

@ -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);