summary refs log tree commit diff
path: root/src/platform/nmp-object.h
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2020-10-05 22:27:18 +0200
committerMichael Biebl <biebl@debian.org>2020-10-05 22:27:18 +0200
commitaafc1dbe4712c86189bbc1d4d54ad8cb4c69be7e (patch)
treea2a9bb4d007339a0b1304540388230ccedac32bd /src/platform/nmp-object.h
parente7b44ef4c80907346ec7492a09c45277459924fc (diff)
New upstream version 1.27.90 upstream/1.27.90
Diffstat (limited to 'src/platform/nmp-object.h')
-rw-r--r--src/platform/nmp-object.h1456
1 files changed, 793 insertions, 663 deletions
diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h
index 44525ed0..58f54dbe 100644
--- a/src/platform/nmp-object.h
+++ b/src/platform/nmp-object.h
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * Copyright (C) 2015 - 2018 Red Hat, Inc.
  */
@@ -18,90 +18,86 @@ struct udev_device;
 
 /* "struct __kernel_timespec" uses "long long", but we use gint64. In practice,
  * these are the same types. */
-G_STATIC_ASSERT (sizeof (long long) == sizeof (gint64));
+G_STATIC_ASSERT(sizeof(long long) == sizeof(gint64));
 
 typedef struct {
-	/* like "struct __kernel_timespec". */
-	gint64 tv_sec;
-	gint64 tv_nsec;
+    /* like "struct __kernel_timespec". */
+    gint64 tv_sec;
+    gint64 tv_nsec;
 } NMPTimespec64;
 
 /*****************************************************************************/
 
 typedef union {
-	struct sockaddr     sa;
-	struct sockaddr_in  in;
-	struct sockaddr_in6 in6;
+    struct sockaddr     sa;
+    struct sockaddr_in  in;
+    struct sockaddr_in6 in6;
 } NMSockAddrUnion;
 
 #define NM_SOCK_ADDR_UNION_INIT_UNSPEC \
-	{ \
-		.sa = { \
-			.sa_family = AF_UNSPEC, \
-		}, \
-	}
+    {                                  \
+        .sa = {                        \
+            .sa_family = AF_UNSPEC,    \
+        },                             \
+    }
 
-int nm_sock_addr_union_cmp (const NMSockAddrUnion *a,
-                            const NMSockAddrUnion *b);
+int nm_sock_addr_union_cmp(const NMSockAddrUnion *a, const NMSockAddrUnion *b);
 
-void nm_sock_addr_union_hash_update (const NMSockAddrUnion *a,
-                                     NMHashState *h);
+void nm_sock_addr_union_hash_update(const NMSockAddrUnion *a, NMHashState *h);
 
-void nm_sock_addr_union_cpy (NMSockAddrUnion *dst,
-                             gconstpointer src /* unaligned (const NMSockAddrUnion *) */);
+void nm_sock_addr_union_cpy(NMSockAddrUnion *dst,
+                            gconstpointer    src /* unaligned (const NMSockAddrUnion *) */);
 
-void nm_sock_addr_union_cpy_untrusted (NMSockAddrUnion *dst,
-                                       gconstpointer src /* unaligned (const NMSockAddrUnion *) */,
-                                       gsize src_len);
+void nm_sock_addr_union_cpy_untrusted(NMSockAddrUnion *dst,
+                                      gconstpointer src /* unaligned (const NMSockAddrUnion *) */,
+                                      gsize         src_len);
 
-const char *nm_sock_addr_union_to_string (const NMSockAddrUnion *sa,
-                                          char *buf,
-                                          gsize len);
+const char *nm_sock_addr_union_to_string(const NMSockAddrUnion *sa, char *buf, gsize len);
 
 /*****************************************************************************/
 
 typedef struct {
-	NMIPAddr addr;
-	guint8 family;
-	guint8 mask;
+    NMIPAddr addr;
+    guint8   family;
+    guint8   mask;
 } NMPWireGuardAllowedIP;
 
 typedef struct _NMPWireGuardPeer {
-	NMSockAddrUnion endpoint;
+    NMSockAddrUnion endpoint;
 
-	NMPTimespec64 last_handshake_time;
+    NMPTimespec64 last_handshake_time;
 
-	guint64 rx_bytes;
-	guint64 tx_bytes;
+    guint64 rx_bytes;
+    guint64 tx_bytes;
 
-	union {
-		const NMPWireGuardAllowedIP *allowed_ips;
-		guint _construct_idx_start;
-	};
-	union {
-		guint allowed_ips_len;
-		guint _construct_idx_end;
-	};
+    union {
+        const NMPWireGuardAllowedIP *allowed_ips;
+        guint                        _construct_idx_start;
+    };
+    union {
+        guint allowed_ips_len;
+        guint _construct_idx_end;
+    };
 
-	guint16 persistent_keepalive_interval;
+    guint16 persistent_keepalive_interval;
 
-	guint8 public_key[NMP_WIREGUARD_PUBLIC_KEY_LEN];
-	guint8 preshared_key[NMP_WIREGUARD_SYMMETRIC_KEY_LEN];
+    guint8 public_key[NMP_WIREGUARD_PUBLIC_KEY_LEN];
+    guint8 preshared_key[NMP_WIREGUARD_SYMMETRIC_KEY_LEN];
 } NMPWireGuardPeer;
 
 /*****************************************************************************/
 
 typedef enum { /*< skip >*/
-	NMP_OBJECT_TO_STRING_ID,
-	NMP_OBJECT_TO_STRING_PUBLIC,
-	NMP_OBJECT_TO_STRING_ALL,
+               NMP_OBJECT_TO_STRING_ID,
+               NMP_OBJECT_TO_STRING_PUBLIC,
+               NMP_OBJECT_TO_STRING_ALL,
 } NMPObjectToStringMode;
 
 typedef enum { /*< skip >*/
-	NMP_CACHE_OPS_UNCHANGED       = NM_PLATFORM_SIGNAL_NONE,
-	NMP_CACHE_OPS_ADDED           = NM_PLATFORM_SIGNAL_ADDED,
-	NMP_CACHE_OPS_UPDATED         = NM_PLATFORM_SIGNAL_CHANGED,
-	NMP_CACHE_OPS_REMOVED         = NM_PLATFORM_SIGNAL_REMOVED,
+               NMP_CACHE_OPS_UNCHANGED = NM_PLATFORM_SIGNAL_NONE,
+               NMP_CACHE_OPS_ADDED     = NM_PLATFORM_SIGNAL_ADDED,
+               NMP_CACHE_OPS_UPDATED   = NM_PLATFORM_SIGNAL_CHANGED,
+               NMP_CACHE_OPS_REMOVED   = NM_PLATFORM_SIGNAL_REMOVED,
 } NMPCacheOpsType;
 
 /* The NMPCacheIdType are the different index types.
@@ -121,878 +117,1012 @@ typedef enum { /*< skip >*/
  * matching v4/v6 and ifindex -- or maybe not at all if it isn't visible.
  * */
 typedef enum { /*< skip >*/
-	NMP_CACHE_ID_TYPE_NONE,
-
-	/* all the objects of a certain type.
-	 *
-	 * This index is special. It is the only one that contains *all* object.
-	 * Other indexes may consider some object as non "partitionable", hence
-	 * they don't track all objects.
-	 *
-	 * Hence, this index type is used when looking at all objects (still
-	 * partitioned by type).
-	 *
-	 * Also, note that links may be considered invisible. This index type
-	 * expose all links, even invisible ones. For addresses/routes, this
-	 * distinction doesn't exist, as all addresses/routes that are alive
-	 * are visible as well. */
-	NMP_CACHE_ID_TYPE_OBJECT_TYPE,
-
-	/* index for the link objects by ifname. */
-	NMP_CACHE_ID_TYPE_LINK_BY_IFNAME,
-
-	/* indices for the visible default-routes, ignoring ifindex.
-	 * This index only contains two partitions: all visible default-routes,
-	 * separate for IPv4 and IPv6. */
-	NMP_CACHE_ID_TYPE_DEFAULT_ROUTES,
-
-	/* all the objects that have an ifindex (by object-type) for an ifindex. */
-	NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX,
-
-	/* Consider all the destination fields of a route, that is, the ID without the ifindex
-	 * and gateway (meaning: network/plen,metric).
-	 * The reason for this is that `ip route change` can replace an existing route
-	 * and modify its ifindex/gateway. Effectively, that means it deletes an existing
-	 * route and adds a different one (as the ID of the route changes). However, it only
-	 * sends one RTM_NEWADDR notification without notifying about the deletion. We detect
-	 * that by having this index to contain overlapping routes which require special
-	 * cache-resync. */
-	NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID,
-
-	/* a filter for objects that track an explicit address family.
-	 *
-	 * Note that currently on NMPObjectRoutingRule is indexed by this filter. */
-	NMP_CACHE_ID_TYPE_OBJECT_BY_ADDR_FAMILY,
-
-	__NMP_CACHE_ID_TYPE_MAX,
-	NMP_CACHE_ID_TYPE_MAX = __NMP_CACHE_ID_TYPE_MAX - 1,
+               NMP_CACHE_ID_TYPE_NONE,
+
+               /* all the objects of a certain type.
+     *
+     * This index is special. It is the only one that contains *all* object.
+     * Other indexes may consider some object as non "partitionable", hence
+     * they don't track all objects.
+     *
+     * Hence, this index type is used when looking at all objects (still
+     * partitioned by type).
+     *
+     * Also, note that links may be considered invisible. This index type
+     * expose all links, even invisible ones. For addresses/routes, this
+     * distinction doesn't exist, as all addresses/routes that are alive
+     * are visible as well. */
+               NMP_CACHE_ID_TYPE_OBJECT_TYPE,
+
+               /* index for the link objects by ifname. */
+               NMP_CACHE_ID_TYPE_LINK_BY_IFNAME,
+
+               /* indices for the visible default-routes, ignoring ifindex.
+     * This index only contains two partitions: all visible default-routes,
+     * separate for IPv4 and IPv6. */
+               NMP_CACHE_ID_TYPE_DEFAULT_ROUTES,
+
+               /* all the objects that have an ifindex (by object-type) for an ifindex. */
+               NMP_CACHE_ID_TYPE_OBJECT_BY_IFINDEX,
+
+               /* Consider all the destination fields of a route, that is, the ID without the ifindex
+     * and gateway (meaning: network/plen,metric).
+     * The reason for this is that `ip route change` can replace an existing route
+     * and modify its ifindex/gateway. Effectively, that means it deletes an existing
+     * route and adds a different one (as the ID of the route changes). However, it only
+     * sends one RTM_NEWADDR notification without notifying about the deletion. We detect
+     * that by having this index to contain overlapping routes which require special
+     * cache-resync. */
+               NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID,
+
+               /* a filter for objects that track an explicit address family.
+     *
+     * Note that currently on NMPObjectRoutingRule is indexed by this filter. */
+               NMP_CACHE_ID_TYPE_OBJECT_BY_ADDR_FAMILY,
+
+               __NMP_CACHE_ID_TYPE_MAX,
+               NMP_CACHE_ID_TYPE_MAX = __NMP_CACHE_ID_TYPE_MAX - 1,
 } NMPCacheIdType;
 
 typedef struct {
-	NMDedupMultiObjClass parent;
-	const char *obj_type_name;
-	int sizeof_data;
-	int sizeof_public;
-	NMPObjectType obj_type;
-	int addr_family;
-	int rtm_gettype;
-	NMPlatformSignalIdType signal_type_id;
-	const char *signal_type;
-
-	const guint8 *supported_cache_ids;
-
-	/* Only for NMPObjectLnk* types. */
-	NMLinkType lnk_link_type;
-
-	void (*cmd_obj_hash_update) (const NMPObject *obj, NMHashState *h);
-	int (*cmd_obj_cmp) (const NMPObject *obj1, const NMPObject *obj2);
-	void (*cmd_obj_copy) (NMPObject *dst, const NMPObject *src);
-	void (*cmd_obj_dispose) (NMPObject *obj);
-	gboolean (*cmd_obj_is_alive) (const NMPObject *obj);
-	gboolean (*cmd_obj_is_visible) (const NMPObject *obj);
-	const char *(*cmd_obj_to_string) (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size);
-
-	/* functions that operate on NMPlatformObject */
-	void (*cmd_plobj_id_copy) (NMPlatformObject *dst, const NMPlatformObject *src);
-	int (*cmd_plobj_id_cmp) (const NMPlatformObject *obj1, const NMPlatformObject *obj2);
-	void (*cmd_plobj_id_hash_update) (const NMPlatformObject *obj, NMHashState *h);
-	const char *(*cmd_plobj_to_string_id) (const NMPlatformObject *obj, char *buf, gsize buf_size);
-	const char *(*cmd_plobj_to_string) (const NMPlatformObject *obj, char *buf, gsize len);
-	void (*cmd_plobj_hash_update) (const NMPlatformObject *obj, NMHashState *h);
-	int (*cmd_plobj_cmp) (const NMPlatformObject *obj1, const NMPlatformObject *obj2);
+    NMDedupMultiObjClass   parent;
+    const char *           obj_type_name;
+    const char *           signal_type;
+    const guint8 *         supported_cache_ids;
+    int                    sizeof_data;
+    int                    sizeof_public;
+    int                    addr_family;
+    int                    rtm_gettype;
+    NMPObjectType          obj_type;
+    NMPlatformSignalIdType signal_type_id;
+
+    /* Only for NMPObjectLnk* types. */
+    NMLinkType lnk_link_type;
+
+    void (*cmd_obj_hash_update)(const NMPObject *obj, NMHashState *h);
+    int (*cmd_obj_cmp)(const NMPObject *obj1, const NMPObject *obj2);
+    void (*cmd_obj_copy)(NMPObject *dst, const NMPObject *src);
+    void (*cmd_obj_dispose)(NMPObject *obj);
+    gboolean (*cmd_obj_is_alive)(const NMPObject *obj);
+    gboolean (*cmd_obj_is_visible)(const NMPObject *obj);
+    const char *(*cmd_obj_to_string)(const NMPObject *     obj,
+                                     NMPObjectToStringMode to_string_mode,
+                                     char *                buf,
+                                     gsize                 buf_size);
+
+    /* functions that operate on NMPlatformObject */
+    void (*cmd_plobj_id_copy)(NMPlatformObject *dst, const NMPlatformObject *src);
+    int (*cmd_plobj_id_cmp)(const NMPlatformObject *obj1, const NMPlatformObject *obj2);
+    void (*cmd_plobj_id_hash_update)(const NMPlatformObject *obj, NMHashState *h);
+    const char *(*cmd_plobj_to_string_id)(const NMPlatformObject *obj, char *buf, gsize buf_size);
+    const char *(*cmd_plobj_to_string)(const NMPlatformObject *obj, char *buf, gsize len);
+    void (*cmd_plobj_hash_update)(const NMPlatformObject *obj, NMHashState *h);
+    int (*cmd_plobj_cmp)(const NMPlatformObject *obj1, const NMPlatformObject *obj2);
 } NMPClass;
 
 extern const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX];
 
 typedef struct {
-	NMPlatformLink _public;
-
-	struct {
-		bool is_in_netlink;
-
-		/* Additional data that depends on the link-type (IFLA_INFO_DATA) */
-		const NMPObject *lnk;
-	} netlink;
-
-	struct {
-		/* note that "struct udev_device" references the library context
-		 * "struct udev", but doesn't own it.
-		 *
-		 * Hence, the udev.device shall not be used after the library
-		 * context is is destroyed.
-		 *
-		 * In case of NMPObjectLink instances that you obtained from the
-		 * platform cache, that means that you shall no keep references
-		 * to those instances that outlife the NMPlatform instance.
-		 *
-		 * In practice, the requirement is less strict and you'll be even
-		 * fine if the platform instance (and the "struct udev" instance)
-		 * are already destroyed while you still hold onto a reference to
-		 * the NMPObjectLink instance. Just don't make use of udev functions
-		 * that cause access to the udev library context.
-		 */
-		struct udev_device *device;
-	} udev;
-
-	/* Auxiliary data object for Wi-Fi and WPAN */
-	GObject *ext_data;
-
-	/* FIXME: not every NMPObjectLink should pay the price for tracking
-	 * the wireguard family id. This should be tracked via ext_data, which
-	 * would be exactly the right place. */
-	int wireguard_family_id;
+    NMPlatformLink _public;
+
+    struct {
+        bool is_in_netlink;
+
+        /* Additional data that depends on the link-type (IFLA_INFO_DATA) */
+        const NMPObject *lnk;
+    } netlink;
+
+    struct {
+        /* note that "struct udev_device" references the library context
+         * "struct udev", but doesn't own it.
+         *
+         * Hence, the udev.device shall not be used after the library
+         * context is destroyed.
+         *
+         * In case of NMPObjectLink instances that you obtained from the
+         * platform cache, that means that you shall no keep references
+         * to those instances that outlife the NMPlatform instance.
+         *
+         * In practice, the requirement is less strict and you'll be even
+         * fine if the platform instance (and the "struct udev" instance)
+         * are already destroyed while you still hold onto a reference to
+         * the NMPObjectLink instance. Just don't make use of udev functions
+         * that cause access to the udev library context.
+         */
+        struct udev_device *device;
+    } udev;
+
+    /* Auxiliary data object for Wi-Fi and WPAN */
+    GObject *ext_data;
+
+    /* FIXME: not every NMPObjectLink should pay the price for tracking
+     * the wireguard family id. This should be tracked via ext_data, which
+     * would be exactly the right place. */
+    int wireguard_family_id;
 } NMPObjectLink;
 
 typedef struct {
-	NMPlatformLnkGre _public;
+    NMPlatformLnkBridge _public;
+} NMPObjectLnkBridge;
+
+typedef struct {
+    NMPlatformLnkGre _public;
 } NMPObjectLnkGre;
 
 typedef struct {
-	NMPlatformLnkInfiniband _public;
+    NMPlatformLnkInfiniband _public;
 } NMPObjectLnkInfiniband;
 
 typedef struct {
-	NMPlatformLnkIp6Tnl _public;
+    NMPlatformLnkIp6Tnl _public;
 } NMPObjectLnkIp6Tnl;
 
 typedef struct {
-	NMPlatformLnkIpIp _public;
+    NMPlatformLnkIpIp _public;
 } NMPObjectLnkIpIp;
 
 typedef struct {
-	NMPlatformLnkMacsec _public;
+    NMPlatformLnkMacsec _public;
 } NMPObjectLnkMacsec;
 
 typedef struct {
-	NMPlatformLnkMacvlan _public;
+    NMPlatformLnkMacvlan _public;
 } NMPObjectLnkMacvlan;
 
 typedef NMPObjectLnkMacvlan NMPObjectLnkMacvtap;
 
 typedef struct {
-	NMPlatformLnkSit _public;
+    NMPlatformLnkSit _public;
 } NMPObjectLnkSit;
 
 typedef struct {
-	NMPlatformLnkTun _public;
+    NMPlatformLnkTun _public;
 } NMPObjectLnkTun;
 
 typedef struct {
-	NMPlatformLnkVlan _public;
+    NMPlatformLnkVlan _public;
 
-	guint n_ingress_qos_map;
-	guint n_egress_qos_map;
-	const NMVlanQosMapping *ingress_qos_map;
-	const NMVlanQosMapping *egress_qos_map;
+    guint                   n_ingress_qos_map;
+    guint                   n_egress_qos_map;
+    const NMVlanQosMapping *ingress_qos_map;
+    const NMVlanQosMapping *egress_qos_map;
 } NMPObjectLnkVlan;
 
 typedef struct {
-	NMPlatformLnkVrf _public;
+    NMPlatformLnkVrf _public;
 } NMPObjectLnkVrf;
 
 typedef struct {
-	NMPlatformLnkVxlan _public;
+    NMPlatformLnkVxlan _public;
 } NMPObjectLnkVxlan;
 
 typedef struct {
-	NMPlatformLnkWireGuard _public;
-	const NMPWireGuardPeer *peers;
-	const NMPWireGuardAllowedIP *_allowed_ips_buf;
-	guint peers_len;
-	guint _allowed_ips_buf_len;
+    NMPlatformLnkWireGuard       _public;
+    const NMPWireGuardPeer *     peers;
+    const NMPWireGuardAllowedIP *_allowed_ips_buf;
+    guint                        peers_len;
+    guint                        _allowed_ips_buf_len;
 } NMPObjectLnkWireGuard;
 
 typedef struct {
-	NMPlatformIP4Address _public;
+    NMPlatformIP4Address _public;
 } NMPObjectIP4Address;
 
 typedef struct {
-	NMPlatformIP4Route _public;
+    NMPlatformIP4Route _public;
 } NMPObjectIP4Route;
 
 typedef struct {
-	NMPlatformIP6Address _public;
+    NMPlatformIP6Address _public;
 } NMPObjectIP6Address;
 
 typedef struct {
-	NMPlatformIP6Route _public;
+    NMPlatformIP6Route _public;
 } NMPObjectIP6Route;
 
 typedef struct {
-	NMPlatformRoutingRule _public;
+    NMPlatformRoutingRule _public;
 } NMPObjectRoutingRule;
 
 typedef struct {
-	NMPlatformQdisc _public;
+    NMPlatformQdisc _public;
 } NMPObjectQdisc;
 
 typedef struct {
-	NMPlatformTfilter _public;
+    NMPlatformTfilter _public;
 } NMPObjectTfilter;
 
 struct _NMPObject {
-	union {
-		NMDedupMultiObj parent;
-		const NMPClass *_class;
-	};
-	union {
-		NMPlatformObject        object;
+    union {
+        NMDedupMultiObj parent;
+        const NMPClass *_class;
+    };
+    union {
+        NMPlatformObject object;
 
-		NMPlatformObjWithIfindex obj_with_ifindex;
+        NMPlatformObjWithIfindex obj_with_ifindex;
 
-		NMPlatformLink          link;
-		NMPObjectLink           _link;
+        NMPlatformLink link;
+        NMPObjectLink  _link;
 
-		NMPlatformLnkGre        lnk_gre;
-		NMPObjectLnkGre         _lnk_gre;
+        NMPlatformLnkBridge lnk_bridge;
+        NMPObjectLnkBridge  _lnk_bridge;
 
-		NMPlatformLnkInfiniband lnk_infiniband;
-		NMPObjectLnkInfiniband  _lnk_infiniband;
+        NMPlatformLnkGre lnk_gre;
+        NMPObjectLnkGre  _lnk_gre;
 
-		NMPlatformLnkIpIp       lnk_ipip;
-		NMPObjectLnkIpIp        _lnk_ipip;
+        NMPlatformLnkInfiniband lnk_infiniband;
+        NMPObjectLnkInfiniband  _lnk_infiniband;
 
-		NMPlatformLnkIp6Tnl     lnk_ip6tnl;
-		NMPObjectLnkIp6Tnl      _lnk_ip6tnl;
+        NMPlatformLnkIpIp lnk_ipip;
+        NMPObjectLnkIpIp  _lnk_ipip;
 
-		NMPlatformLnkMacsec     lnk_macsec;
-		NMPObjectLnkMacsec      _lnk_macsec;
+        NMPlatformLnkIp6Tnl lnk_ip6tnl;
+        NMPObjectLnkIp6Tnl  _lnk_ip6tnl;
 
-		NMPlatformLnkMacvlan    lnk_macvlan;
-		NMPObjectLnkMacvlan     _lnk_macvlan;
+        NMPlatformLnkMacsec lnk_macsec;
+        NMPObjectLnkMacsec  _lnk_macsec;
 
-		NMPlatformLnkSit        lnk_sit;
-		NMPObjectLnkSit         _lnk_sit;
+        NMPlatformLnkMacvlan lnk_macvlan;
+        NMPObjectLnkMacvlan  _lnk_macvlan;
 
-		NMPlatformLnkTun        lnk_tun;
-		NMPObjectLnkTun         _lnk_tun;
+        NMPlatformLnkSit lnk_sit;
+        NMPObjectLnkSit  _lnk_sit;
 
-		NMPlatformLnkVlan       lnk_vlan;
-		NMPObjectLnkVlan        _lnk_vlan;
+        NMPlatformLnkTun lnk_tun;
+        NMPObjectLnkTun  _lnk_tun;
 
-		NMPlatformLnkVrf        lnk_vrf;
-		NMPObjectLnkVrf         _lnk_vrf;
+        NMPlatformLnkVlan lnk_vlan;
+        NMPObjectLnkVlan  _lnk_vlan;
 
-		NMPlatformLnkVxlan      lnk_vxlan;
-		NMPObjectLnkVxlan       _lnk_vxlan;
+        NMPlatformLnkVrf lnk_vrf;
+        NMPObjectLnkVrf  _lnk_vrf;
 
-		NMPlatformLnkWireGuard  lnk_wireguard;
-		NMPObjectLnkWireGuard   _lnk_wireguard;
+        NMPlatformLnkVxlan lnk_vxlan;
+        NMPObjectLnkVxlan  _lnk_vxlan;
 
-		NMPlatformIPAddress     ip_address;
-		NMPlatformIPXAddress    ipx_address;
-		NMPlatformIP4Address    ip4_address;
-		NMPlatformIP6Address    ip6_address;
-		NMPObjectIP4Address     _ip4_address;
-		NMPObjectIP6Address     _ip6_address;
+        NMPlatformLnkWireGuard lnk_wireguard;
+        NMPObjectLnkWireGuard  _lnk_wireguard;
 
-		NMPlatformIPRoute       ip_route;
-		NMPlatformIPXRoute      ipx_route;
-		NMPlatformIP4Route      ip4_route;
-		NMPlatformIP6Route      ip6_route;
-		NMPObjectIP4Route       _ip4_route;
-		NMPObjectIP6Route       _ip6_route;
+        NMPlatformIPAddress  ip_address;
+        NMPlatformIPXAddress ipx_address;
+        NMPlatformIP4Address ip4_address;
+        NMPlatformIP6Address ip6_address;
+        NMPObjectIP4Address  _ip4_address;
+        NMPObjectIP6Address  _ip6_address;
 
-		NMPlatformRoutingRule   routing_rule;
-		NMPObjectRoutingRule    _routing_rule;
+        NMPlatformIPRoute  ip_route;
+        NMPlatformIPXRoute ipx_route;
+        NMPlatformIP4Route ip4_route;
+        NMPlatformIP6Route ip6_route;
+        NMPObjectIP4Route  _ip4_route;
+        NMPObjectIP6Route  _ip6_route;
 
-		NMPlatformQdisc         qdisc;
-		NMPObjectQdisc          _qdisc;
-		NMPlatformTfilter       tfilter;
-		NMPObjectTfilter        _tfilter;
-	};
+        NMPlatformRoutingRule routing_rule;
+        NMPObjectRoutingRule  _routing_rule;
+
+        NMPlatformQdisc   qdisc;
+        NMPObjectQdisc    _qdisc;
+        NMPlatformTfilter tfilter;
+        NMPObjectTfilter  _tfilter;
+    };
 };
 
 /*****************************************************************************/
 
 static inline gboolean
-NMP_CLASS_IS_VALID (const NMPClass *klass)
+NMP_CLASS_IS_VALID(const NMPClass *klass)
 {
-	return klass >= &_nmp_classes[0]
-	    && klass <= &_nmp_classes[G_N_ELEMENTS (_nmp_classes)]
-	    && ((((char *) klass) - ((char *) _nmp_classes)) % (sizeof (_nmp_classes[0]))) == 0;
+    return klass >= &_nmp_classes[0] && klass <= &_nmp_classes[G_N_ELEMENTS(_nmp_classes)]
+           && ((((char *) klass) - ((char *) _nmp_classes)) % (sizeof(_nmp_classes[0]))) == 0;
 }
 
 static inline const NMPClass *
-nmp_class_from_type (NMPObjectType obj_type)
+nmp_class_from_type(NMPObjectType obj_type)
 {
-	nm_assert (obj_type > 0);
-	nm_assert (obj_type <= G_N_ELEMENTS (_nmp_classes));
-	nm_assert (_nmp_classes[obj_type - 1].obj_type == obj_type);
-	nm_assert (NMP_CLASS_IS_VALID (&_nmp_classes[obj_type - 1]));
+    nm_assert(obj_type > 0);
+    nm_assert(obj_type <= G_N_ELEMENTS(_nmp_classes));
+    nm_assert(_nmp_classes[obj_type - 1].obj_type == obj_type);
+    nm_assert(NMP_CLASS_IS_VALID(&_nmp_classes[obj_type - 1]));
 
-	return &_nmp_classes[obj_type - 1];
+    return &_nmp_classes[obj_type - 1];
 }
 
 static inline NMPObject *
 NMP_OBJECT_UP_CAST(const NMPlatformObject *plobj)
 {
-	NMPObject *obj;
+    NMPObject *obj;
 
-	obj = plobj
-	      ? (NMPObject *) ( &(((char *) plobj)[-((int) G_STRUCT_OFFSET (NMPObject, object))]) )
-	      : NULL;
-	nm_assert (!obj || (obj->parent._ref_count > 0 && NMP_CLASS_IS_VALID (obj->_class)));
-	return obj;
+    obj = plobj ? (NMPObject *) (&(((char *) plobj)[-((int) G_STRUCT_OFFSET(NMPObject, object))]))
+                : NULL;
+    nm_assert(!obj || (obj->parent._ref_count > 0 && NMP_CLASS_IS_VALID(obj->_class)));
+    return obj;
 }
-#define NMP_OBJECT_UP_CAST(plobj) (NMP_OBJECT_UP_CAST ((const NMPlatformObject *) (plobj)))
+#define NMP_OBJECT_UP_CAST(plobj) (NMP_OBJECT_UP_CAST((const NMPlatformObject *) (plobj)))
 
 static inline gboolean
-NMP_OBJECT_IS_VALID (const NMPObject *obj)
+NMP_OBJECT_IS_VALID(const NMPObject *obj)
 {
-	nm_assert (!obj || (   obj
-	                    && obj->parent._ref_count > 0
-	                    && NMP_CLASS_IS_VALID (obj->_class)));
+    nm_assert(!obj || (obj && obj->parent._ref_count > 0 && NMP_CLASS_IS_VALID(obj->_class)));
 
-	/* There isn't really much to check. Either @obj is NULL, or we must
-	 * assume that it points to valid memory. */
-	return obj != NULL;
+    /* There isn't really much to check. Either @obj is NULL, or we must
+     * assume that it points to valid memory. */
+    return obj != NULL;
 }
 
 static inline gboolean
-NMP_OBJECT_IS_STACKINIT (const NMPObject *obj)
+NMP_OBJECT_IS_STACKINIT(const NMPObject *obj)
 {
-	nm_assert (!obj || NMP_OBJECT_IS_VALID (obj));
+    nm_assert(!obj || NMP_OBJECT_IS_VALID(obj));
 
-	return obj && obj->parent._ref_count == NM_OBJ_REF_COUNT_STACKINIT;
+    return obj && obj->parent._ref_count == NM_OBJ_REF_COUNT_STACKINIT;
 }
 
 static inline const NMPClass *
-NMP_OBJECT_GET_CLASS (const NMPObject *obj)
+NMP_OBJECT_GET_CLASS(const NMPObject *obj)
 {
-	nm_assert (NMP_OBJECT_IS_VALID (obj));
+    nm_assert(NMP_OBJECT_IS_VALID(obj));
 
-	return obj->_class;
+    return obj->_class;
 }
 
 static inline NMPObjectType
-NMP_OBJECT_GET_TYPE (const NMPObject *obj)
+NMP_OBJECT_GET_TYPE(const NMPObject *obj)
 {
-	nm_assert (!obj || NMP_OBJECT_IS_VALID (obj));
+    nm_assert(!obj || NMP_OBJECT_IS_VALID(obj));
 
-	return obj ? obj->_class->obj_type : NMP_OBJECT_TYPE_UNKNOWN;
+    return obj ? obj->_class->obj_type : NMP_OBJECT_TYPE_UNKNOWN;
 }
 
 static inline gboolean
-_NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX (NMPObjectType obj_type)
-{
-	switch (obj_type) {
-	case NMP_OBJECT_TYPE_LINK:
-	case NMP_OBJECT_TYPE_IP4_ADDRESS:
-	case NMP_OBJECT_TYPE_IP6_ADDRESS:
-	case NMP_OBJECT_TYPE_IP4_ROUTE:
-	case NMP_OBJECT_TYPE_IP6_ROUTE:
-
-	case NMP_OBJECT_TYPE_QDISC:
-
-	case NMP_OBJECT_TYPE_TFILTER:
-
-	case NMP_OBJECT_TYPE_LNK_GRE:
-	case NMP_OBJECT_TYPE_LNK_GRETAP:
-	case NMP_OBJECT_TYPE_LNK_INFINIBAND:
-	case NMP_OBJECT_TYPE_LNK_IP6TNL:
-	case NMP_OBJECT_TYPE_LNK_IP6GRE:
-	case NMP_OBJECT_TYPE_LNK_IP6GRETAP:
-	case NMP_OBJECT_TYPE_LNK_IPIP:
-	case NMP_OBJECT_TYPE_LNK_MACSEC:
-	case NMP_OBJECT_TYPE_LNK_MACVLAN:
-	case NMP_OBJECT_TYPE_LNK_MACVTAP:
-	case NMP_OBJECT_TYPE_LNK_SIT:
-	case NMP_OBJECT_TYPE_LNK_TUN:
-	case NMP_OBJECT_TYPE_LNK_VLAN:
-	case NMP_OBJECT_TYPE_LNK_VRF:
-	case NMP_OBJECT_TYPE_LNK_VXLAN:
-	case NMP_OBJECT_TYPE_LNK_WIREGUARD:
-		return TRUE;
-
-	case NMP_OBJECT_TYPE_ROUTING_RULE:
-		return FALSE;
-
-	case NMP_OBJECT_TYPE_UNKNOWN:
-	case __NMP_OBJECT_TYPE_LAST:
-		break;
-	}
-	nm_assert_not_reached ();
-	return FALSE;
-}
-
-#define NMP_OBJECT_CAST_OBJECT(obj) \
-	({ \
-		typeof (obj) _obj = (obj); \
-		\
-		nm_assert (   !_obj \
-		           || nmp_class_from_type (NMP_OBJECT_GET_TYPE (_obj)))); \
-		_obj ? &NM_CONSTCAST (NMPObject, _obj)->object : NULL; \
-	})
-
-#define NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj) \
-	({ \
-		typeof (obj) _obj = (obj); \
-		\
-		nm_assert (   !_obj \
-		           || _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX (NMP_OBJECT_GET_TYPE (_obj))); \
-		_obj ? &NM_CONSTCAST (NMPObject, _obj)->obj_with_ifindex : NULL; \
-	})
-
-#define _NMP_OBJECT_CAST(obj, field, ...) \
-	({ \
-		typeof (obj) _obj = (obj); \
-		\
-		nm_assert (!_obj || NM_IN_SET (NMP_OBJECT_GET_TYPE (_obj), __VA_ARGS__)); \
-		_obj ? &NM_CONSTCAST (NMPObject, _obj)->field : NULL; \
-	})
-
-#define NMP_OBJECT_CAST_LINK(obj)          _NMP_OBJECT_CAST (obj, link,          NMP_OBJECT_TYPE_LINK)
-#define NMP_OBJECT_CAST_IP_ADDRESS(obj)    _NMP_OBJECT_CAST (obj, ip_address,    NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS)
-#define NMP_OBJECT_CAST_IPX_ADDRESS(obj)   _NMP_OBJECT_CAST (obj, ipx_address,   NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS)
-#define NMP_OBJECT_CAST_IP4_ADDRESS(obj)   _NMP_OBJECT_CAST (obj, ip4_address,   NMP_OBJECT_TYPE_IP4_ADDRESS)
-#define NMP_OBJECT_CAST_IP6_ADDRESS(obj)   _NMP_OBJECT_CAST (obj, ip6_address,   NMP_OBJECT_TYPE_IP6_ADDRESS)
-#define NMP_OBJECT_CAST_IP_ROUTE(obj)      _NMP_OBJECT_CAST (obj, ip_route,      NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)
-#define NMP_OBJECT_CAST_IPX_ROUTE(obj)     _NMP_OBJECT_CAST (obj, ipx_route,     NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)
-#define NMP_OBJECT_CAST_IP4_ROUTE(obj)     _NMP_OBJECT_CAST (obj, ip4_route,     NMP_OBJECT_TYPE_IP4_ROUTE)
-#define NMP_OBJECT_CAST_IP6_ROUTE(obj)     _NMP_OBJECT_CAST (obj, ip6_route,     NMP_OBJECT_TYPE_IP6_ROUTE)
-#define NMP_OBJECT_CAST_ROUTING_RULE(obj)  _NMP_OBJECT_CAST (obj, routing_rule,  NMP_OBJECT_TYPE_ROUTING_RULE)
-#define NMP_OBJECT_CAST_QDISC(obj)         _NMP_OBJECT_CAST (obj, qdisc,         NMP_OBJECT_TYPE_QDISC)
-#define NMP_OBJECT_CAST_TFILTER(obj)       _NMP_OBJECT_CAST (obj, tfilter,       NMP_OBJECT_TYPE_TFILTER)
-#define NMP_OBJECT_CAST_LNK_WIREGUARD(obj) _NMP_OBJECT_CAST (obj, lnk_wireguard, NMP_OBJECT_TYPE_LNK_WIREGUARD)
+_NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX(NMPObjectType obj_type)
+{
+    switch (obj_type) {
+    case NMP_OBJECT_TYPE_LINK:
+    case NMP_OBJECT_TYPE_IP4_ADDRESS:
+    case NMP_OBJECT_TYPE_IP6_ADDRESS:
+    case NMP_OBJECT_TYPE_IP4_ROUTE:
+    case NMP_OBJECT_TYPE_IP6_ROUTE:
+
+    case NMP_OBJECT_TYPE_QDISC:
+
+    case NMP_OBJECT_TYPE_TFILTER:
+
+    case NMP_OBJECT_TYPE_LNK_BRIDGE:
+    case NMP_OBJECT_TYPE_LNK_GRE:
+    case NMP_OBJECT_TYPE_LNK_GRETAP:
+    case NMP_OBJECT_TYPE_LNK_INFINIBAND:
+    case NMP_OBJECT_TYPE_LNK_IP6TNL:
+    case NMP_OBJECT_TYPE_LNK_IP6GRE:
+    case NMP_OBJECT_TYPE_LNK_IP6GRETAP:
+    case NMP_OBJECT_TYPE_LNK_IPIP:
+    case NMP_OBJECT_TYPE_LNK_MACSEC:
+    case NMP_OBJECT_TYPE_LNK_MACVLAN:
+    case NMP_OBJECT_TYPE_LNK_MACVTAP:
+    case NMP_OBJECT_TYPE_LNK_SIT:
+    case NMP_OBJECT_TYPE_LNK_TUN:
+    case NMP_OBJECT_TYPE_LNK_VLAN:
+    case NMP_OBJECT_TYPE_LNK_VRF:
+    case NMP_OBJECT_TYPE_LNK_VXLAN:
+    case NMP_OBJECT_TYPE_LNK_WIREGUARD:
+        return TRUE;
+
+    case NMP_OBJECT_TYPE_ROUTING_RULE:
+        return FALSE;
+
+    case NMP_OBJECT_TYPE_UNKNOWN:
+    case __NMP_OBJECT_TYPE_LAST:
+        break;
+    }
+    nm_assert_not_reached();
+    return FALSE;
+}
 
-static inline const NMPObject *
-nmp_object_ref (const NMPObject *obj)
+#define NMP_OBJECT_CAST_OBJECT(obj)                                       \
+    ({                                                                    \
+        typeof(obj) _obj = (obj);                                         \
+                                                                          \
+        nm_assert (   !_obj \
+                   || nmp_class_from_type (NMP_OBJECT_GET_TYPE (_obj)))); \
+        _obj ? &NM_CONSTCAST(NMPObject, _obj)->object : NULL;             \
+    })
+
+#define NMP_OBJECT_CAST_OBJ_WITH_IFINDEX(obj)                                                \
+    ({                                                                                       \
+        typeof(obj) _obj = (obj);                                                            \
+                                                                                             \
+        nm_assert(!_obj || _NMP_OBJECT_TYPE_IS_OBJ_WITH_IFINDEX(NMP_OBJECT_GET_TYPE(_obj))); \
+        _obj ? &NM_CONSTCAST(NMPObject, _obj)->obj_with_ifindex : NULL;                      \
+    })
+
+#define _NMP_OBJECT_CAST(obj, field, ...)                                      \
+    ({                                                                         \
+        typeof(obj) _obj = (obj);                                              \
+                                                                               \
+        nm_assert(!_obj || NM_IN_SET(NMP_OBJECT_GET_TYPE(_obj), __VA_ARGS__)); \
+        _obj ? &NM_CONSTCAST(NMPObject, _obj)->field : NULL;                   \
+    })
+
+#define NMP_OBJECT_CAST_LINK(obj) _NMP_OBJECT_CAST(obj, link, NMP_OBJECT_TYPE_LINK)
+#define NMP_OBJECT_CAST_IP_ADDRESS(obj) \
+    _NMP_OBJECT_CAST(obj, ip_address, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS)
+#define NMP_OBJECT_CAST_IPX_ADDRESS(obj) \
+    _NMP_OBJECT_CAST(obj, ipx_address, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS)
+#define NMP_OBJECT_CAST_IP4_ADDRESS(obj) \
+    _NMP_OBJECT_CAST(obj, ip4_address, NMP_OBJECT_TYPE_IP4_ADDRESS)
+#define NMP_OBJECT_CAST_IP6_ADDRESS(obj) \
+    _NMP_OBJECT_CAST(obj, ip6_address, NMP_OBJECT_TYPE_IP6_ADDRESS)
+#define NMP_OBJECT_CAST_IP_ROUTE(obj) \
+    _NMP_OBJECT_CAST(obj, ip_route, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)
+#define NMP_OBJECT_CAST_IPX_ROUTE(obj) \
+    _NMP_OBJECT_CAST(obj, ipx_route, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)
+#define NMP_OBJECT_CAST_IP4_ROUTE(obj) _NMP_OBJECT_CAST(obj, ip4_route, NMP_OBJECT_TYPE_IP4_ROUTE)
+#define NMP_OBJECT_CAST_IP6_ROUTE(obj) _NMP_OBJECT_CAST(obj, ip6_route, NMP_OBJECT_TYPE_IP6_ROUTE)
+#define NMP_OBJECT_CAST_ROUTING_RULE(obj) \
+    _NMP_OBJECT_CAST(obj, routing_rule, NMP_OBJECT_TYPE_ROUTING_RULE)
+#define NMP_OBJECT_CAST_QDISC(obj)   _NMP_OBJECT_CAST(obj, qdisc, NMP_OBJECT_TYPE_QDISC)
+#define NMP_OBJECT_CAST_TFILTER(obj) _NMP_OBJECT_CAST(obj, tfilter, NMP_OBJECT_TYPE_TFILTER)
+#define NMP_OBJECT_CAST_LNK_WIREGUARD(obj) \
+    _NMP_OBJECT_CAST(obj, lnk_wireguard, NMP_OBJECT_TYPE_LNK_WIREGUARD)
+#define NMP_OBJECT_CAST_LNK_BRIDGE(obj) \
+    _NMP_OBJECT_CAST(obj, lnk_bridge, NMP_OBJECT_TYPE_LNK_BRIDGE)
+
+static inline int
+NMP_OBJECT_TYPE_TO_ADDR_FAMILY(NMPObjectType obj_type)
 {
-	if (!obj) {
-		/* for convenience, allow NULL. */
-		return NULL;
-	}
+    return nmp_class_from_type(obj_type)->addr_family;
+}
 
-	/* ref and unref accept const pointers. NMPObject is supposed to be shared
-	 * and kept immutable. Disallowing to take/return a reference to a const
-	 * NMPObject is cumbersome, because callers are precisely expected to
-	 * keep a ref on the otherwise immutable object. */
-	g_return_val_if_fail (NMP_OBJECT_IS_VALID (obj), NULL);
-	g_return_val_if_fail (obj->parent._ref_count != NM_OBJ_REF_COUNT_STACKINIT, NULL);
+static inline int
+NMP_OBJECT_GET_ADDR_FAMILY(const NMPObject *obj)
+{
+    return NMP_OBJECT_GET_CLASS(obj)->addr_family;
+}
 
-	return (const NMPObject *) nm_dedup_multi_obj_ref ((const NMDedupMultiObj *) obj);
+static inline const NMPObject *
+nmp_object_ref(const NMPObject *obj)
+{
+    if (!obj) {
+        /* for convenience, allow NULL. */
+        return NULL;
+    }
+
+    /* ref and unref accept const pointers. NMPObject is supposed to be shared
+     * and kept immutable. Disallowing to take/return a reference to a const
+     * NMPObject is cumbersome, because callers are precisely expected to
+     * keep a ref on the otherwise immutable object. */
+    g_return_val_if_fail(NMP_OBJECT_IS_VALID(obj), NULL);
+    g_return_val_if_fail(obj->parent._ref_count != NM_OBJ_REF_COUNT_STACKINIT, NULL);
+
+    return (const NMPObject *) nm_dedup_multi_obj_ref((const NMDedupMultiObj *) obj);
 }
 
 static inline void
-nmp_object_unref (const NMPObject *obj)
+nmp_object_unref(const NMPObject *obj)
 {
-	if (obj) {
-		nm_assert (NMP_OBJECT_IS_VALID (obj));
+    if (obj) {
+        nm_assert(NMP_OBJECT_IS_VALID(obj));
 
-		nm_dedup_multi_obj_unref ((const NMDedupMultiObj *) obj);
-	}
+        nm_dedup_multi_obj_unref((const NMDedupMultiObj *) obj);
+    }
 }
 
-#define nm_clear_nmp_object(ptr) \
-	({ \
-		typeof (ptr) _ptr = (ptr); \
-		typeof (*_ptr) _pptr; \
-		gboolean _changed = FALSE; \
-		\
-		if (   _ptr \
-		    && (_pptr = *_ptr)) { \
-			*_ptr = NULL; \
-			nmp_object_unref (_pptr); \
-			_changed = TRUE; \
-		} \
-		_changed; \
-	})
+#define nm_clear_nmp_object(ptr)       \
+    ({                                 \
+        typeof(ptr) _ptr = (ptr);      \
+        typeof(*_ptr) _pptr;           \
+        gboolean _changed = FALSE;     \
+                                       \
+        if (_ptr && (_pptr = *_ptr)) { \
+            *_ptr = NULL;              \
+            nmp_object_unref(_pptr);   \
+            _changed = TRUE;           \
+        }                              \
+        _changed;                      \
+    })
+
+static inline gboolean
+nmp_object_ref_set(const NMPObject **pp, const NMPObject *obj)
+{
+    gboolean         _changed = FALSE;
+    const NMPObject *p;
+
+    nm_assert(!pp || !*pp || NMP_OBJECT_IS_VALID(*pp));
+    nm_assert(!obj || NMP_OBJECT_IS_VALID(obj));
+
+    if (pp && ((p = *pp) != obj)) {
+        nmp_object_ref(obj);
+        *pp = obj;
+        nmp_object_unref(p);
+        _changed = TRUE;
+    }
+    return _changed;
+}
 
-NMPObject *nmp_object_new (NMPObjectType obj_type, gconstpointer plobj);
-NMPObject *nmp_object_new_link (int ifindex);
+NMPObject *nmp_object_new(NMPObjectType obj_type, gconstpointer plobj);
+NMPObject *nmp_object_new_link(int ifindex);
 
-const NMPObject *nmp_object_stackinit (NMPObject *obj, NMPObjectType obj_type, gconstpointer plobj);
+const NMPObject *nmp_object_stackinit(NMPObject *obj, NMPObjectType obj_type, gconstpointer plobj);
 
 static inline NMPObject *
-nmp_object_stackinit_obj (NMPObject *obj, const NMPObject *src)
+nmp_object_stackinit_obj(NMPObject *obj, const NMPObject *src)
 {
-	return obj == src
-	         ? obj
-	         : (NMPObject *) nmp_object_stackinit (obj, NMP_OBJECT_GET_TYPE (src), &src->object);
+    return obj == src
+               ? obj
+               : (NMPObject *) nmp_object_stackinit(obj, NMP_OBJECT_GET_TYPE(src), &src->object);
 }
 
-const NMPObject *nmp_object_stackinit_id  (NMPObject *obj, const NMPObject *src);
-const NMPObject *nmp_object_stackinit_id_link (NMPObject *obj, int ifindex);
-const NMPObject *nmp_object_stackinit_id_ip4_address (NMPObject *obj, int ifindex, guint32 address, guint8 plen, guint32 peer_address);
-const NMPObject *nmp_object_stackinit_id_ip6_address (NMPObject *obj, int ifindex, const struct in6_addr *address);
-
-const char *nmp_object_to_string (const NMPObject *obj, NMPObjectToStringMode to_string_mode, char *buf, gsize buf_size);
-void nmp_object_hash_update (const NMPObject *obj, NMHashState *h);
-int nmp_object_cmp (const NMPObject *obj1, const NMPObject *obj2);
+const NMPObject *nmp_object_stackinit_id(NMPObject *obj, const NMPObject *src);
+const NMPObject *nmp_object_stackinit_id_link(NMPObject *obj, int ifindex);
+const NMPObject *nmp_object_stackinit_id_ip4_address(NMPObject *obj,
+                                                     int        ifindex,
+                                                     guint32    address,
+                                                     guint8     plen,
+                                                     guint32    peer_address);
+const NMPObject *
+nmp_object_stackinit_id_ip6_address(NMPObject *obj, int ifindex, const struct in6_addr *address);
+
+const char *nmp_object_to_string(const NMPObject *     obj,
+                                 NMPObjectToStringMode to_string_mode,
+                                 char *                buf,
+                                 gsize                 buf_size);
+void        nmp_object_hash_update(const NMPObject *obj, NMHashState *h);
+int         nmp_object_cmp(const NMPObject *obj1, const NMPObject *obj2);
 
 static inline gboolean
-nmp_object_equal (const NMPObject *obj1, const NMPObject *obj2)
+nmp_object_equal(const NMPObject *obj1, const NMPObject *obj2)
 {
-	return nmp_object_cmp (obj1, obj2) == 0;
+    return nmp_object_cmp(obj1, obj2) == 0;
 }
 
-void nmp_object_copy (NMPObject *dst, const NMPObject *src, gboolean id_only);
-NMPObject *nmp_object_clone (const NMPObject *obj, gboolean id_only);
+void       nmp_object_copy(NMPObject *dst, const NMPObject *src, gboolean id_only);
+NMPObject *nmp_object_clone(const NMPObject *obj, gboolean id_only);
 
-int nmp_object_id_cmp (const NMPObject *obj1, const NMPObject *obj2);
-void nmp_object_id_hash_update (const NMPObject *obj, NMHashState *h);
-guint nmp_object_id_hash (const NMPObject *obj);
+int   nmp_object_id_cmp(const NMPObject *obj1, const NMPObject *obj2);
+void  nmp_object_id_hash_update(const NMPObject *obj, NMHashState *h);
+guint nmp_object_id_hash(const NMPObject *obj);
 
 static inline gboolean
-nmp_object_id_equal (const NMPObject *obj1, const NMPObject *obj2)
+nmp_object_id_equal(const NMPObject *obj1, const NMPObject *obj2)
 {
-	return nmp_object_id_cmp (obj1, obj2) == 0;
+    return nmp_object_id_cmp(obj1, obj2) == 0;
 }
 
-gboolean nmp_object_is_alive (const NMPObject *obj);
-gboolean nmp_object_is_visible (const NMPObject *obj);
+guint    nmp_object_indirect_id_hash(gconstpointer a);
+gboolean nmp_object_indirect_id_equal(gconstpointer a, gconstpointer b);
+
+gboolean nmp_object_is_alive(const NMPObject *obj);
+gboolean nmp_object_is_visible(const NMPObject *obj);
 
-void _nmp_object_fixup_link_udev_fields (NMPObject **obj_new, NMPObject *obj_orig, gboolean use_udev);
+void
+_nmp_object_fixup_link_udev_fields(NMPObject **obj_new, NMPObject *obj_orig, gboolean use_udev);
 
 static inline void
-_nm_auto_nmpobj_cleanup (gpointer p)
+_nm_auto_nmpobj_cleanup(gpointer p)
 {
-	nmp_object_unref (*((const NMPObject **) p));
+    nmp_object_unref(*((const NMPObject **) p));
 }
 #define nm_auto_nmpobj nm_auto(_nm_auto_nmpobj_cleanup)
 
 typedef struct _NMPCache NMPCache;
 
-typedef void (*NMPCachePreHook) (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMPCacheOpsType ops_type, gpointer user_data);
-typedef gboolean (*NMPObjectMatchFn) (const NMPObject *obj, gpointer user_data);
-
-const NMDedupMultiEntry *nmp_cache_lookup_entry (const NMPCache *cache,
-                                                 const NMPObject *obj);
-const NMDedupMultiEntry *nmp_cache_lookup_entry_with_idx_type (const NMPCache *cache,
-                                                               NMPCacheIdType cache_id_type,
-                                                               const NMPObject *obj);
-const NMDedupMultiEntry *nmp_cache_lookup_entry_link (const NMPCache *cache,
-                                                      int ifindex);
-const NMPObject *nmp_cache_lookup_obj (const NMPCache *cache,
-                                       const NMPObject *obj);
-const NMPObject *nmp_cache_lookup_link (const NMPCache *cache,
-                                        int ifindex);
+typedef void (*NMPCachePreHook)(NMPCache *       cache,
+                                const NMPObject *old,
+                                const NMPObject *new,
+                                NMPCacheOpsType ops_type,
+                                gpointer        user_data);
+typedef gboolean (*NMPObjectMatchFn)(const NMPObject *obj, gpointer user_data);
+
+const NMDedupMultiEntry *nmp_cache_lookup_entry(const NMPCache *cache, const NMPObject *obj);
+const NMDedupMultiEntry *nmp_cache_lookup_entry_with_idx_type(const NMPCache * cache,
+                                                              NMPCacheIdType   cache_id_type,
+                                                              const NMPObject *obj);
+const NMDedupMultiEntry *nmp_cache_lookup_entry_link(const NMPCache *cache, int ifindex);
+const NMPObject *        nmp_cache_lookup_obj(const NMPCache *cache, const NMPObject *obj);
+const NMPObject *        nmp_cache_lookup_link(const NMPCache *cache, int ifindex);
 
 typedef struct _NMPLookup NMPLookup;
 
 struct _NMPLookup {
-	NMPCacheIdType cache_id_type;
-	NMPObject selector_obj;
+    NMPCacheIdType cache_id_type;
+    NMPObject      selector_obj;
 };
 
-const NMDedupMultiHeadEntry *nmp_cache_lookup_all (const NMPCache *cache,
-                                                   NMPCacheIdType cache_id_type,
-                                                   const NMPObject *select_obj);
+const NMDedupMultiHeadEntry *nmp_cache_lookup_all(const NMPCache * cache,
+                                                  NMPCacheIdType   cache_id_type,
+                                                  const NMPObject *select_obj);
 
 static inline const NMDedupMultiHeadEntry *
-nmp_cache_lookup (const NMPCache *cache,
-                  const NMPLookup *lookup)
+nmp_cache_lookup(const NMPCache *cache, const NMPLookup *lookup)
 {
-	return nmp_cache_lookup_all (cache, lookup->cache_id_type, &lookup->selector_obj);
+    return nmp_cache_lookup_all(cache, lookup->cache_id_type, &lookup->selector_obj);
 }
 
-const NMPLookup *nmp_lookup_init_obj_type (NMPLookup *lookup,
-                                           NMPObjectType obj_type);
-const NMPLookup *nmp_lookup_init_link_by_ifname (NMPLookup *lookup,
-                                                 const char *ifname);
-const NMPLookup *nmp_lookup_init_object (NMPLookup *lookup,
-                                         NMPObjectType obj_type,
-                                         int ifindex);
-const NMPLookup *nmp_lookup_init_route_default (NMPLookup *lookup,
-                                                NMPObjectType obj_type);
-const NMPLookup *nmp_lookup_init_route_by_weak_id (NMPLookup *lookup,
-                                                   const NMPObject *obj);
-const NMPLookup *nmp_lookup_init_ip4_route_by_weak_id (NMPLookup *lookup,
-                                                       in_addr_t network,
-                                                       guint plen,
-                                                       guint32 metric,
-                                                       guint8 tos);
-const NMPLookup *nmp_lookup_init_ip6_route_by_weak_id (NMPLookup *lookup,
-                                                       const struct in6_addr *network,
-                                                       guint plen,
-                                                       guint32 metric,
-                                                       const struct in6_addr *src,
-                                                       guint8 src_plen);
-const NMPLookup *nmp_lookup_init_object_by_addr_family (NMPLookup *lookup,
-                                                        NMPObjectType obj_type,
-                                                        int addr_family);
-
-GArray *nmp_cache_lookup_to_array (const NMDedupMultiHeadEntry *head_entry,
-                                   NMPObjectType obj_type,
-                                   gboolean visible_only);
+const NMPLookup *nmp_lookup_init_obj_type(NMPLookup *lookup, NMPObjectType obj_type);
+const NMPLookup *nmp_lookup_init_link_by_ifname(NMPLookup *lookup, const char *ifname);
+const NMPLookup *nmp_lookup_init_object(NMPLookup *lookup, NMPObjectType obj_type, int ifindex);
+const NMPLookup *nmp_lookup_init_route_default(NMPLookup *lookup, NMPObjectType obj_type);
+const NMPLookup *nmp_lookup_init_route_by_weak_id(NMPLookup *lookup, const NMPObject *obj);
+const NMPLookup *nmp_lookup_init_ip4_route_by_weak_id(NMPLookup *lookup,
+                                                      in_addr_t  network,
+                                                      guint      plen,
+                                                      guint32    metric,
+                                                      guint8     tos);
+const NMPLookup *nmp_lookup_init_ip6_route_by_weak_id(NMPLookup *            lookup,
+                                                      const struct in6_addr *network,
+                                                      guint                  plen,
+                                                      guint32                metric,
+                                                      const struct in6_addr *src,
+                                                      guint8                 src_plen);
+const NMPLookup *
+nmp_lookup_init_object_by_addr_family(NMPLookup *lookup, NMPObjectType obj_type, int addr_family);
+
+GArray *nmp_cache_lookup_to_array(const NMDedupMultiHeadEntry *head_entry,
+                                  NMPObjectType                obj_type,
+                                  gboolean                     visible_only);
 
 static inline gboolean
-nmp_cache_iter_next (NMDedupMultiIter *iter, const NMPObject **out_obj)
+nmp_cache_iter_next(NMDedupMultiIter *iter, const NMPObject **out_obj)
 {
-	gboolean has_next;
+    gboolean has_next;
 
-	has_next = nm_dedup_multi_iter_next (iter);
-	nm_assert (!has_next || NMP_OBJECT_IS_VALID (iter->current->obj));
-	if (out_obj)
-		*out_obj = has_next ? iter->current->obj : NULL;
-	return has_next;
+    has_next = nm_dedup_multi_iter_next(iter);
+    nm_assert(!has_next || NMP_OBJECT_IS_VALID(iter->current->obj));
+    if (out_obj)
+        *out_obj = has_next ? iter->current->obj : NULL;
+    return has_next;
 }
 
 static inline gboolean
-nmp_cache_iter_next_link (NMDedupMultiIter *iter, const NMPlatformLink **out_obj)
+nmp_cache_iter_next_link(NMDedupMultiIter *iter, const NMPlatformLink **out_obj)
 {
-	gboolean has_next;
+    gboolean has_next;
 
-	has_next = nm_dedup_multi_iter_next (iter);
-	nm_assert (!has_next || NMP_OBJECT_GET_TYPE (iter->current->obj) == NMP_OBJECT_TYPE_LINK);
-	if (out_obj)
-		*out_obj = has_next ? &(((const NMPObject *) iter->current->obj)->link) : NULL;
-	return has_next;
+    has_next = nm_dedup_multi_iter_next(iter);
+    nm_assert(!has_next || NMP_OBJECT_GET_TYPE(iter->current->obj) == NMP_OBJECT_TYPE_LINK);
+    if (out_obj)
+        *out_obj = has_next ? &(((const NMPObject *) iter->current->obj)->link) : NULL;
+    return has_next;
 }
 
 #define nmp_cache_iter_for_each(iter, head, obj) \
-	for (nm_dedup_multi_iter_init ((iter), \
-	                               (head)); \
-	     nmp_cache_iter_next ((iter), (obj)); \
-	     )
+    for (nm_dedup_multi_iter_init((iter), (head)); nmp_cache_iter_next((iter), (obj));)
 
 #define nmp_cache_iter_for_each_link(iter, head, obj) \
-	for (nm_dedup_multi_iter_init ((iter), \
-	                               (head)); \
-	     nmp_cache_iter_next_link ((iter), (obj)); \
-	     )
-
-const NMPObject *nmp_cache_lookup_link_full (const NMPCache *cache,
-                                             int ifindex,
-                                             const char *ifname,
-                                             gboolean visible_only,
-                                             NMLinkType link_type,
-                                             NMPObjectMatchFn match_fn,
-                                             gpointer user_data);
-
-gboolean nmp_cache_link_connected_for_slave (int ifindex_master, const NMPObject *slave);
-gboolean nmp_cache_link_connected_needs_toggle (const NMPCache *cache, const NMPObject *master, const NMPObject *potential_slave, const NMPObject *ignore_slave);
-const NMPObject *nmp_cache_link_connected_needs_toggle_by_ifindex (const NMPCache *cache, int master_ifindex, const NMPObject *potential_slave, const NMPObject *ignore_slave);
-
-gboolean nmp_cache_use_udev_get (const NMPCache *cache);
-
-void ASSERT_nmp_cache_is_consistent (const NMPCache *cache);
-
-NMPCacheOpsType nmp_cache_remove (NMPCache *cache,
-                                  const NMPObject *obj_needle,
-                                  gboolean equals_by_ptr,
-                                  gboolean only_dirty,
-                                  const NMPObject **out_obj_old);
-NMPCacheOpsType nmp_cache_remove_netlink (NMPCache *cache,
-                                          const NMPObject *obj_needle,
-                                          const NMPObject **out_obj_old,
-                                          const NMPObject **out_obj_new);
-NMPCacheOpsType nmp_cache_update_netlink (NMPCache *cache,
-                                          NMPObject *obj_hand_over,
-                                          gboolean is_dump,
-                                          const NMPObject **out_obj_old,
-                                          const NMPObject **out_obj_new);
-NMPCacheOpsType nmp_cache_update_netlink_route (NMPCache *cache,
-                                                NMPObject *obj_hand_over,
-                                                gboolean is_dump,
-                                                guint16 nlmsgflags,
-                                                const NMPObject **out_obj_old,
-                                                const NMPObject **out_obj_new,
-                                                const NMPObject **out_obj_replace,
-                                                gboolean *out_resync_required);
-NMPCacheOpsType nmp_cache_update_link_udev (NMPCache *cache,
-                                            int ifindex,
-                                            struct udev_device *udevice,
-                                            const NMPObject **out_obj_old,
-                                            const NMPObject **out_obj_new);
-NMPCacheOpsType nmp_cache_update_link_master_connected (NMPCache *cache,
-                                                        int ifindex,
-                                                        const NMPObject **out_obj_old,
-                                                        const NMPObject **out_obj_new);
+    for (nm_dedup_multi_iter_init((iter), (head)); nmp_cache_iter_next_link((iter), (obj));)
+
+const NMPObject *nmp_cache_lookup_link_full(const NMPCache * cache,
+                                            int              ifindex,
+                                            const char *     ifname,
+                                            gboolean         visible_only,
+                                            NMLinkType       link_type,
+                                            NMPObjectMatchFn match_fn,
+                                            gpointer         user_data);
+
+gboolean         nmp_cache_link_connected_for_slave(int ifindex_master, const NMPObject *slave);
+gboolean         nmp_cache_link_connected_needs_toggle(const NMPCache * cache,
+                                                       const NMPObject *master,
+                                                       const NMPObject *potential_slave,
+                                                       const NMPObject *ignore_slave);
+const NMPObject *nmp_cache_link_connected_needs_toggle_by_ifindex(const NMPCache * cache,
+                                                                  int              master_ifindex,
+                                                                  const NMPObject *potential_slave,
+                                                                  const NMPObject *ignore_slave);
+
+gboolean nmp_cache_use_udev_get(const NMPCache *cache);
+
+void nmtst_assert_nmp_cache_is_consistent(const NMPCache *cache);
+
+NMPCacheOpsType nmp_cache_remove(NMPCache *        cache,
+                                 const NMPObject * obj_needle,
+                                 gboolean          equals_by_ptr,
+                                 gboolean          only_dirty,
+                                 const NMPObject **out_obj_old);
+NMPCacheOpsType nmp_cache_remove_netlink(NMPCache *        cache,
+                                         const NMPObject * obj_needle,
+                                         const NMPObject **out_obj_old,
+                                         const NMPObject **out_obj_new);
+NMPCacheOpsType nmp_cache_update_netlink(NMPCache *        cache,
+                                         NMPObject *       obj_hand_over,
+                                         gboolean          is_dump,
+                                         const NMPObject **out_obj_old,
+                                         const NMPObject **out_obj_new);
+NMPCacheOpsType nmp_cache_update_netlink_route(NMPCache *        cache,
+                                               NMPObject *       obj_hand_over,
+                                               gboolean          is_dump,
+                                               guint16           nlmsgflags,
+                                               const NMPObject **out_obj_old,
+                                               const NMPObject **out_obj_new,
+                                               const NMPObject **out_obj_replace,
+                                               gboolean *        out_resync_required);
+NMPCacheOpsType nmp_cache_update_link_udev(NMPCache *          cache,
+                                           int                 ifindex,
+                                           struct udev_device *udevice,
+                                           const NMPObject **  out_obj_old,
+                                           const NMPObject **  out_obj_new);
+NMPCacheOpsType nmp_cache_update_link_master_connected(NMPCache *        cache,
+                                                       int               ifindex,
+                                                       const NMPObject **out_obj_old,
+                                                       const NMPObject **out_obj_new);
 
 static inline const NMDedupMultiEntry *
-nmp_cache_reresolve_main_entry (NMPCache *cache,
-                                const NMDedupMultiEntry *entry,
-                                const NMPLookup *lookup)
+nmp_cache_reresolve_main_entry(NMPCache *               cache,
+                               const NMDedupMultiEntry *entry,
+                               const NMPLookup *        lookup)
 {
-	const NMDedupMultiEntry *main_entry;
+    const NMDedupMultiEntry *main_entry;
 
-	nm_assert (cache);
-	nm_assert (entry);
-	nm_assert (lookup);
+    nm_assert(cache);
+    nm_assert(entry);
+    nm_assert(lookup);
 
-	if (lookup->cache_id_type == NMP_CACHE_ID_TYPE_OBJECT_TYPE) {
-		nm_assert (entry == nmp_cache_lookup_entry (cache, entry->obj));
-		return entry;
-	}
+    if (lookup->cache_id_type == NMP_CACHE_ID_TYPE_OBJECT_TYPE) {
+        nm_assert(entry == nmp_cache_lookup_entry(cache, entry->obj));
+        return entry;
+    }
 
-	/* we only track the dirty flag for the OBJECT-TYPE index. That means,
-	 * for other lookup types we need to check the dirty flag of the main-entry. */
-	main_entry = nmp_cache_lookup_entry (cache, entry->obj);
+    /* we only track the dirty flag for the OBJECT-TYPE index. That means,
+     * for other lookup types we need to check the dirty flag of the main-entry. */
+    main_entry = nmp_cache_lookup_entry(cache, entry->obj);
 
-	nm_assert (main_entry);
-	nm_assert (main_entry->obj == entry->obj);
+    nm_assert(main_entry);
+    nm_assert(main_entry->obj == entry->obj);
 
-	return main_entry;
+    return main_entry;
 }
 
-void nmp_cache_dirty_set_all_main (NMPCache *cache,
-                                   const NMPLookup *lookup);
+void nmp_cache_dirty_set_all_main(NMPCache *cache, const NMPLookup *lookup);
 
-NMPCache *nmp_cache_new (NMDedupMultiIndex *multi_idx, gboolean use_udev);
-void nmp_cache_free (NMPCache *cache);
+NMPCache *nmp_cache_new(NMDedupMultiIndex *multi_idx, gboolean use_udev);
+void      nmp_cache_free(NMPCache *cache);
 
 static inline void
-ASSERT_nmp_cache_ops (const NMPCache *cache,
-                      NMPCacheOpsType ops_type,
-                      const NMPObject *obj_old,
-                      const NMPObject *obj_new)
+ASSERT_nmp_cache_ops(const NMPCache * cache,
+                     NMPCacheOpsType  ops_type,
+                     const NMPObject *obj_old,
+                     const NMPObject *obj_new)
 {
 #if NM_MORE_ASSERTS
-	nm_assert (cache);
-	nm_assert (obj_old || obj_new);
-	nm_assert (!obj_old || (   NMP_OBJECT_IS_VALID (obj_old)
-	                        && !NMP_OBJECT_IS_STACKINIT (obj_old)
-	                        && nmp_object_is_alive (obj_old)));
-	nm_assert (!obj_new || (   NMP_OBJECT_IS_VALID (obj_new)
-	                        && !NMP_OBJECT_IS_STACKINIT (obj_new)
-	                        && nmp_object_is_alive (obj_new)));
-
-	switch (ops_type) {
-	case NMP_CACHE_OPS_UNCHANGED:
-		nm_assert (obj_old == obj_new);
-		break;
-	case NMP_CACHE_OPS_ADDED:
-		nm_assert (!obj_old && obj_new);
-		break;
-	case NMP_CACHE_OPS_UPDATED:
-		nm_assert (obj_old &&  obj_new && obj_old != obj_new);
-		break;
-	case NMP_CACHE_OPS_REMOVED:
-		nm_assert (obj_old && !obj_new);
-		break;
-	default:
-		nm_assert_not_reached ();
-	}
-
-	nm_assert (obj_new == NULL || obj_old == NULL || nmp_object_id_equal (obj_new, obj_old));
-	nm_assert (!obj_old || !obj_new || NMP_OBJECT_GET_CLASS (obj_old) == NMP_OBJECT_GET_CLASS (obj_new));
-
-	nm_assert (obj_new == nmp_cache_lookup_obj (cache, obj_new ?: obj_old));
+    nm_assert(cache);
+    nm_assert(obj_old || obj_new);
+    nm_assert(!obj_old
+              || (NMP_OBJECT_IS_VALID(obj_old) && !NMP_OBJECT_IS_STACKINIT(obj_old)
+                  && nmp_object_is_alive(obj_old)));
+    nm_assert(!obj_new
+              || (NMP_OBJECT_IS_VALID(obj_new) && !NMP_OBJECT_IS_STACKINIT(obj_new)
+                  && nmp_object_is_alive(obj_new)));
+
+    switch (ops_type) {
+    case NMP_CACHE_OPS_UNCHANGED:
+        nm_assert(obj_old == obj_new);
+        break;
+    case NMP_CACHE_OPS_ADDED:
+        nm_assert(!obj_old && obj_new);
+        break;
+    case NMP_CACHE_OPS_UPDATED:
+        nm_assert(obj_old && obj_new && obj_old != obj_new);
+        break;
+    case NMP_CACHE_OPS_REMOVED:
+        nm_assert(obj_old && !obj_new);
+        break;
+    default:
+        nm_assert_not_reached();
+    }
+
+    nm_assert(obj_new == NULL || obj_old == NULL || nmp_object_id_equal(obj_new, obj_old));
+    nm_assert(!obj_old || !obj_new
+              || NMP_OBJECT_GET_CLASS(obj_old) == NMP_OBJECT_GET_CLASS(obj_new));
+
+    nm_assert(obj_new == nmp_cache_lookup_obj(cache, obj_new ?: obj_old));
 #endif
 }
 
-const NMDedupMultiHeadEntry *nm_platform_lookup_all (NMPlatform *platform,
-                                                     NMPCacheIdType cache_id_type,
-                                                     const NMPObject *obj);
+const NMDedupMultiHeadEntry *
+nm_platform_lookup_all(NMPlatform *platform, NMPCacheIdType cache_id_type, const NMPObject *obj);
 
-const NMDedupMultiEntry *nm_platform_lookup_entry (NMPlatform *platform,
-                                                   NMPCacheIdType cache_id_type,
-                                                   const NMPObject *obj);
+const NMDedupMultiEntry *
+nm_platform_lookup_entry(NMPlatform *platform, NMPCacheIdType cache_id_type, const NMPObject *obj);
 
 static inline const NMPObject *
-nm_platform_lookup_obj (NMPlatform *platform,
-                        NMPCacheIdType cache_id_type,
-                        const NMPObject *obj)
+nm_platform_lookup_obj(NMPlatform *platform, NMPCacheIdType cache_id_type, const NMPObject *obj)
 {
-	return nm_dedup_multi_entry_get_obj (nm_platform_lookup_entry (platform,
-	                                                               cache_id_type,
-	                                                               obj));
+    return nm_dedup_multi_entry_get_obj(nm_platform_lookup_entry(platform, cache_id_type, obj));
 }
 
 static inline const NMDedupMultiHeadEntry *
-nm_platform_lookup_obj_type (NMPlatform *platform,
-                             NMPObjectType obj_type)
+nm_platform_lookup_obj_type(NMPlatform *platform, NMPObjectType obj_type)
 {
-	NMPLookup lookup;
+    NMPLookup lookup;
 
-	nmp_lookup_init_obj_type (&lookup, obj_type);
-	return nm_platform_lookup (platform, &lookup);
+    nmp_lookup_init_obj_type(&lookup, obj_type);
+    return nm_platform_lookup(platform, &lookup);
 }
 
 static inline const NMDedupMultiHeadEntry *
-nm_platform_lookup_link_by_ifname (NMPlatform *platform,
-                                   const char *ifname)
+nm_platform_lookup_link_by_ifname(NMPlatform *platform, const char *ifname)
 {
-	NMPLookup lookup;
+    NMPLookup lookup;
 
-	nmp_lookup_init_link_by_ifname (&lookup, ifname);
-	return nm_platform_lookup (platform, &lookup);
+    nmp_lookup_init_link_by_ifname(&lookup, ifname);
+    return nm_platform_lookup(platform, &lookup);
 }
 
 static inline const NMDedupMultiHeadEntry *
-nm_platform_lookup_object (NMPlatform *platform,
-                           NMPObjectType obj_type,
-                           int ifindex)
+nm_platform_lookup_object(NMPlatform *platform, NMPObjectType obj_type, int ifindex)
 {
-	NMPLookup lookup;
+    NMPLookup lookup;
 
-	nmp_lookup_init_object (&lookup, obj_type, ifindex);
-	return nm_platform_lookup (platform, &lookup);
+    nmp_lookup_init_object(&lookup, obj_type, ifindex);
+    return nm_platform_lookup(platform, &lookup);
 }
 
 static inline GPtrArray *
-nm_platform_lookup_object_clone (NMPlatform *platform,
-                                 NMPObjectType obj_type,
-                                 int ifindex,
-                                 NMPObjectPredicateFunc predicate,
-                                 gpointer user_data)
+nm_platform_lookup_object_clone(NMPlatform *           platform,
+                                NMPObjectType          obj_type,
+                                int                    ifindex,
+                                NMPObjectPredicateFunc predicate,
+                                gpointer               user_data)
 {
-	NMPLookup lookup;
+    NMPLookup lookup;
 
-	nmp_lookup_init_object (&lookup, obj_type, ifindex);
-	return nm_platform_lookup_clone (platform, &lookup, predicate, user_data);
+    nmp_lookup_init_object(&lookup, obj_type, ifindex);
+    return nm_platform_lookup_clone(platform, &lookup, predicate, user_data);
 }
 
 static inline const NMDedupMultiHeadEntry *
-nm_platform_lookup_route_default (NMPlatform *platform,
-                                  NMPObjectType obj_type)
+nm_platform_lookup_route_default(NMPlatform *platform, NMPObjectType obj_type)
 {
-	NMPLookup lookup;
+    NMPLookup lookup;
 
-	nmp_lookup_init_route_default (&lookup, obj_type);
-	return nm_platform_lookup (platform, &lookup);
+    nmp_lookup_init_route_default(&lookup, obj_type);
+    return nm_platform_lookup(platform, &lookup);
 }
 
 static inline GPtrArray *
-nm_platform_lookup_route_default_clone (NMPlatform *platform,
-                                        NMPObjectType obj_type,
-                                        NMPObjectPredicateFunc predicate,
-                                        gpointer user_data)
+nm_platform_lookup_route_default_clone(NMPlatform *           platform,
+                                       NMPObjectType          obj_type,
+                                       NMPObjectPredicateFunc predicate,
+                                       gpointer               user_data)
 {
-	NMPLookup lookup;
+    NMPLookup lookup;
 
-	nmp_lookup_init_route_default (&lookup, obj_type);
-	return nm_platform_lookup_clone (platform, &lookup, predicate, user_data);
+    nmp_lookup_init_route_default(&lookup, obj_type);
+    return nm_platform_lookup_clone(platform, &lookup, predicate, user_data);
 }
 
 static inline const NMDedupMultiHeadEntry *
-nm_platform_lookup_ip4_route_by_weak_id (NMPlatform *platform,
-                                         in_addr_t network,
-                                         guint plen,
-                                         guint32 metric,
-                                         guint8 tos)
+nm_platform_lookup_ip4_route_by_weak_id(NMPlatform *platform,
+                                        in_addr_t   network,
+                                        guint       plen,
+                                        guint32     metric,
+                                        guint8      tos)
 {
-	NMPLookup lookup;
+    NMPLookup lookup;
 
-	nmp_lookup_init_ip4_route_by_weak_id (&lookup, network, plen, metric, tos);
-	return nm_platform_lookup (platform, &lookup);
+    nmp_lookup_init_ip4_route_by_weak_id(&lookup, network, plen, metric, tos);
+    return nm_platform_lookup(platform, &lookup);
 }
 
 static inline const NMDedupMultiHeadEntry *
-nm_platform_lookup_ip6_route_by_weak_id (NMPlatform *platform,
-                                         const struct in6_addr *network,
-                                         guint plen,
-                                         guint32 metric,
-                                         const struct in6_addr *src,
-                                         guint8 src_plen)
+nm_platform_lookup_ip6_route_by_weak_id(NMPlatform *           platform,
+                                        const struct in6_addr *network,
+                                        guint                  plen,
+                                        guint32                metric,
+                                        const struct in6_addr *src,
+                                        guint8                 src_plen)
 {
-	NMPLookup lookup;
+    NMPLookup lookup;
 
-	nmp_lookup_init_ip6_route_by_weak_id (&lookup, network, plen, metric, src, src_plen);
-	return nm_platform_lookup (platform, &lookup);
+    nmp_lookup_init_ip6_route_by_weak_id(&lookup, network, plen, metric, src, src_plen);
+    return nm_platform_lookup(platform, &lookup);
 }
 
 static inline const NMDedupMultiHeadEntry *
-nm_platform_lookup_object_by_addr_family (NMPlatform *platform,
-                                          NMPObjectType obj_type,
-                                          int addr_family)
+nm_platform_lookup_object_by_addr_family(NMPlatform *  platform,
+                                         NMPObjectType obj_type,
+                                         int           addr_family)
+{
+    NMPLookup lookup;
+
+    nmp_lookup_init_object_by_addr_family(&lookup, obj_type, addr_family);
+    return nm_platform_lookup(platform, &lookup);
+}
+
+/*****************************************************************************/
+
+static inline const char *
+nmp_object_link_get_ifname(const NMPObject *obj)
+{
+    if (!obj)
+        return NULL;
+    return NMP_OBJECT_CAST_LINK(obj)->name;
+}
+
+static inline gboolean
+nmp_object_ip_route_is_best_defaut_route(const NMPObject *obj)
+{
+    const NMPlatformIPRoute *r = NMP_OBJECT_CAST_IP_ROUTE(obj);
+
+    /* return whether @obj is considered a default-route.
+     *
+     * NMIP4Config/NMIP6Config tracks the (best) default-route explicitly, because
+     * at various places we act differently depending on whether there is a default-route
+     * configured.
+     *
+     * Note that this only considers the main routing table. */
+    return r && NM_PLATFORM_IP_ROUTE_IS_DEFAULT(r)
+           && nm_platform_route_table_is_main(r->table_coerced)
+           && r->type_coerced == nm_platform_route_type_coerce(1 /* RTN_UNICAST */);
+}
+
+static inline gboolean
+nmp_object_ip6_address_is_not_link_local(const NMPObject *obj)
+{
+    return !IN6_IS_ADDR_LINKLOCAL(&NMP_OBJECT_CAST_IP6_ADDRESS(obj)->address);
+}
+
+/*****************************************************************************/
+
+static inline gboolean
+nm_platform_dedup_multi_iter_next_obj(NMDedupMultiIter *ipconf_iter,
+                                      const NMPObject **out_obj,
+                                      NMPObjectType     assert_obj_type)
+{
+    gboolean has_next;
+
+    has_next = nm_dedup_multi_iter_next(ipconf_iter);
+    nm_assert(assert_obj_type == NMP_OBJECT_TYPE_UNKNOWN || !has_next
+              || NMP_OBJECT_GET_TYPE(ipconf_iter->current->obj) == assert_obj_type);
+    NM_SET_OUT(out_obj, has_next ? ipconf_iter->current->obj : NULL);
+    return has_next;
+}
+
+static inline gboolean
+nm_platform_dedup_multi_iter_next_ip4_address(NMDedupMultiIter *           ipconf_iter,
+                                              const NMPlatformIP4Address **out_address)
+{
+    gboolean has_next;
+
+    has_next = nm_dedup_multi_iter_next(ipconf_iter);
+    if (out_address)
+        *out_address = has_next ? NMP_OBJECT_CAST_IP4_ADDRESS(ipconf_iter->current->obj) : NULL;
+    return has_next;
+}
+
+static inline gboolean
+nm_platform_dedup_multi_iter_next_ip4_route(NMDedupMultiIter *         ipconf_iter,
+                                            const NMPlatformIP4Route **out_route)
+{
+    gboolean has_next;
+
+    has_next = nm_dedup_multi_iter_next(ipconf_iter);
+    if (out_route)
+        *out_route = has_next ? NMP_OBJECT_CAST_IP4_ROUTE(ipconf_iter->current->obj) : NULL;
+    return has_next;
+}
+
+static inline gboolean
+nm_platform_dedup_multi_iter_next_ip6_address(NMDedupMultiIter *           ipconf_iter,
+                                              const NMPlatformIP6Address **out_address)
+{
+    gboolean has_next;
+
+    has_next = nm_dedup_multi_iter_next(ipconf_iter);
+    if (out_address)
+        *out_address = has_next ? NMP_OBJECT_CAST_IP6_ADDRESS(ipconf_iter->current->obj) : NULL;
+    return has_next;
+}
+
+static inline gboolean
+nm_platform_dedup_multi_iter_next_ip6_route(NMDedupMultiIter *         ipconf_iter,
+                                            const NMPlatformIP6Route **out_route)
 {
-	NMPLookup lookup;
+    gboolean has_next;
 
-	nmp_lookup_init_object_by_addr_family (&lookup, obj_type, addr_family);
-	return nm_platform_lookup (platform, &lookup);
+    has_next = nm_dedup_multi_iter_next(ipconf_iter);
+    if (out_route)
+        *out_route = has_next ? NMP_OBJECT_CAST_IP6_ROUTE(ipconf_iter->current->obj) : NULL;
+    return has_next;
 }
 
 #endif /* __NMP_OBJECT_H__ */