diff options
Diffstat (limited to 'src/platform/nmp-object.h')
| -rw-r--r-- | src/platform/nmp-object.h | 559 |
1 files changed, 442 insertions, 117 deletions
diff --git a/src/platform/nmp-object.h b/src/platform/nmp-object.h index b69680f6..41fd08cb 100644 --- a/src/platform/nmp-object.h +++ b/src/platform/nmp-object.h @@ -21,8 +21,9 @@ #ifndef __NMP_OBJECT_H__ #define __NMP_OBJECT_H__ +#include "nm-utils/nm-obj.h" +#include "nm-utils/nm-dedup-multi.h" #include "nm-platform.h" -#include "nm-multi-index.h" struct udev_device; @@ -47,36 +48,42 @@ typedef enum { /*< skip >*/ * but only route objects can be indexed by NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_NO_DEFAULT. * * Of one index type, there can be multiple indexes or not. - * For example, of the index type NMP_CACHE_ID_TYPE_ADDRROUTE_VISIBLE_BY_IFINDEX there + * For example, of the index type NMP_CACHE_ID_TYPE_ADDRROUTE_BY_IFINDEX there * are multiple instances (for different route/addresses, v4/v6, per-ifindex). * * But one object, can only be indexed by one particular index of a * type. For example, a certain address instance is only indexed by - * the index NMP_CACHE_ID_TYPE_ADDRROUTE_VISIBLE_BY_IFINDEX with + * the index NMP_CACHE_ID_TYPE_ADDRROUTE_BY_IFINDEX with * 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 */ + /* 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 + * distiction 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, - /* all the visible objects of a certain type */ - NMP_CACHE_ID_TYPE_OBJECT_TYPE_VISIBLE_ONLY, + /* indeces 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, - /* indeces for the visible routes, ignoring ifindex. */ - NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_NO_DEFAULT, - NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_ONLY_DEFAULT, - - /* all the visible addresses/routes (by object-type) for an ifindex. */ - NMP_CACHE_ID_TYPE_ADDRROUTE_VISIBLE_BY_IFINDEX, - - /* three indeces for the visible routes, per ifindex. */ - NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_NO_DEFAULT, - NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_ONLY_DEFAULT, + /* all the addresses/routes (by object-type) for an ifindex. */ + NMP_CACHE_ID_TYPE_ADDRROUTE_BY_IFINDEX, /* Consider all the destination fields of a route, that is, the ID without the ifindex * and gateway (meaning: network/plen,metric). @@ -86,65 +93,21 @@ typedef enum { /*< skip >*/ * 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_DESTINATION_IP4, - NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP6, + NMP_CACHE_ID_TYPE_ROUTES_BY_WEAK_ID, __NMP_CACHE_ID_TYPE_MAX, NMP_CACHE_ID_TYPE_MAX = __NMP_CACHE_ID_TYPE_MAX - 1, } NMPCacheIdType; -typedef struct _NMPCacheId NMPCacheId; - -struct _NMPCacheId { - union { - NMMultiIndexId base; - guint8 _id_type; /* NMPCacheIdType as guint8 */ - struct _nm_packed { - /* NMP_CACHE_ID_TYPE_OBJECT_TYPE */ - /* NMP_CACHE_ID_TYPE_OBJECT_TYPE_VISIBLE_ONLY */ - /* NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_NO_DEFAULT */ - /* NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_ONLY_DEFAULT */ - guint8 _id_type; - guint8 obj_type; /* NMPObjectType as guint8 */ - } object_type; - struct _nm_packed { - /* NMP_CACHE_ID_TYPE_ADDRROUTE_VISIBLE_BY_IFINDEX */ - /* NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_NO_DEFAULT */ - /* NMP_CACHE_ID_TYPE_ROUTES_VISIBLE_BY_IFINDEX_ONLY_DEFAULT */ - guint8 _id_type; - guint8 obj_type; /* NMPObjectType as guint8 */ - int _misaligned_ifindex; - } object_type_by_ifindex; - struct _nm_packed { - /* NMP_CACHE_ID_TYPE_LINK_BY_IFNAME */ - guint8 _id_type; - char ifname_short[IFNAMSIZ - 1]; /* don't include the trailing NUL so the struct fits in 4 bytes. */ - } link_by_ifname; - struct _nm_packed { - /* NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP4 */ - guint8 _id_type; - guint8 plen; - guint32 _misaligned_metric; - guint32 _misaligned_network; - } routes_by_destination_ip4; - struct _nm_packed { - /* NMP_CACHE_ID_TYPE_ROUTES_BY_DESTINATION_IP6 */ - guint8 _id_type; - guint8 plen; - guint32 _misaligned_metric; - struct in6_addr _misaligned_network; - } routes_by_destination_ip6; - }; -}; - typedef struct { + NMDedupMultiObjClass parent; + const char *obj_type_name; + int sizeof_data; + int sizeof_public; NMPObjectType obj_type; int addr_family; int rtm_gettype; - int sizeof_data; - int sizeof_public; NMPlatformSignalIdType signal_type_id; - const char *obj_type_name; const char *signal_type; const guint8 *supported_cache_ids; @@ -152,13 +115,9 @@ typedef struct { /* Only for NMPObjectLnk* types. */ NMLinkType lnk_link_type; - /* returns %FALSE, if the obj type would never have an entry for index type @id_type. If @obj has an index, - * initialize @id and set @out_id to it. Otherwise, @out_id is NULL. */ - gboolean (*cmd_obj_init_cache_id) (const NMPObject *obj, NMPCacheIdType id_type, NMPCacheId *id, const NMPCacheId **out_id); - + 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_stackinit_id) (NMPObject *obj, 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); @@ -166,10 +125,11 @@ typedef struct { /* functions that operate on NMPlatformObject */ void (*cmd_plobj_id_copy) (NMPlatformObject *dst, const NMPlatformObject *src); - gboolean (*cmd_plobj_id_equal) (const NMPlatformObject *obj1, const NMPlatformObject *obj2); - guint (*cmd_plobj_id_hash) (const NMPlatformObject *obj); + 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; @@ -182,7 +142,7 @@ typedef struct { bool is_in_netlink; /* Additional data that depends on the link-type (IFLA_INFO_DATA) */ - NMPObject *lnk; + const NMPObject *lnk; } netlink; struct { @@ -266,9 +226,10 @@ typedef struct { } NMPObjectIP6Route; struct _NMPObject { - const NMPClass *_class; - int _ref_count; - bool is_cached; + union { + NMDedupMultiObj parent; + const NMPClass *_class; + }; union { NMPlatformObject object; @@ -326,8 +287,6 @@ NMP_CLASS_IS_VALID (const NMPClass *klass) && ((((char *) klass) - ((char *) _nmp_classes)) % (sizeof (_nmp_classes[0]))) == 0; } -#define NMP_REF_COUNT_STACKINIT (G_MAXINT) - static inline NMPObject * NMP_OBJECT_UP_CAST(const NMPlatformObject *plobj) { @@ -336,7 +295,7 @@ NMP_OBJECT_UP_CAST(const NMPlatformObject *plobj) obj = plobj ? (NMPObject *) ( &(((char *) plobj)[-((int) G_STRUCT_OFFSET (NMPObject, object))]) ) : NULL; - nm_assert (!obj || (obj->_ref_count > 0 && NMP_CLASS_IS_VALID (obj->_class))); + 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))) @@ -345,7 +304,7 @@ static inline gboolean NMP_OBJECT_IS_VALID (const NMPObject *obj) { nm_assert (!obj || ( obj - && obj->_ref_count > 0 + && 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 @@ -358,7 +317,7 @@ NMP_OBJECT_IS_STACKINIT (const NMPObject *obj) { nm_assert (!obj || NMP_OBJECT_IS_VALID (obj)); - return obj && obj->_ref_count == NMP_REF_COUNT_STACKINIT; + return obj && obj->parent._ref_count == NM_OBJ_REF_COUNT_STACKINIT; } static inline const NMPClass * @@ -377,65 +336,264 @@ NMP_OBJECT_GET_TYPE (const NMPObject *obj) return obj ? obj->_class->obj_type : NMP_OBJECT_TYPE_UNKNOWN; } - +#define NMP_OBJECT_CAST_LINK(obj) \ + ({ \ + typeof (obj) _obj = (obj); \ + \ + nm_assert (!_obj || NMP_OBJECT_GET_TYPE ((const NMPObject *) _obj) == NMP_OBJECT_TYPE_LINK); \ + _obj ? &_NM_CONSTCAST (NMPObject, _obj)->link : NULL; \ + }) + +#define NMP_OBJECT_CAST_IP_ADDRESS(obj) \ + ({ \ + typeof (obj) _obj = (obj); \ + \ + nm_assert (!_obj || NM_IN_SET (NMP_OBJECT_GET_TYPE (_obj), NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS)); \ + _obj ? &_NM_CONSTCAST (NMPObject, _obj)->ip_address : NULL; \ + }) + +#define NMP_OBJECT_CAST_IPX_ADDRESS(obj) \ + ({ \ + typeof (obj) _obj = (obj); \ + \ + nm_assert (!_obj || NM_IN_SET (NMP_OBJECT_GET_TYPE (_obj), NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS)); \ + _obj ? &_NM_CONSTCAST (NMPObject, _obj)->ipx_address : NULL; \ + }) + +#define NMP_OBJECT_CAST_IP4_ADDRESS(obj) \ + ({ \ + typeof (obj) _obj = (obj); \ + \ + nm_assert (!_obj || NMP_OBJECT_GET_TYPE ((const NMPObject *) _obj) == NMP_OBJECT_TYPE_IP4_ADDRESS); \ + _obj ? &_NM_CONSTCAST (NMPObject, _obj)->ip4_address : NULL; \ + }) + +#define NMP_OBJECT_CAST_IP6_ADDRESS(obj) \ + ({ \ + typeof (obj) _obj = (obj); \ + \ + nm_assert (!_obj || NMP_OBJECT_GET_TYPE ((const NMPObject *) _obj) == NMP_OBJECT_TYPE_IP6_ADDRESS); \ + _obj ? &_NM_CONSTCAST (NMPObject, _obj)->ip6_address : NULL; \ + }) + +#define NMP_OBJECT_CAST_IPX_ROUTE(obj) \ + ({ \ + typeof (obj) _obj = (obj); \ + \ + nm_assert (!_obj || NM_IN_SET (NMP_OBJECT_GET_TYPE (_obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); \ + _obj ? &_NM_CONSTCAST (NMPObject, _obj)->ipx_route : NULL; \ + }) + +#define NMP_OBJECT_CAST_IP_ROUTE(obj) \ + ({ \ + typeof (obj) _obj = (obj); \ + \ + nm_assert (!_obj || NM_IN_SET (NMP_OBJECT_GET_TYPE (_obj), NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)); \ + _obj ? &_NM_CONSTCAST (NMPObject, _obj)->ip_route : NULL; \ + }) + +#define NMP_OBJECT_CAST_IP4_ROUTE(obj) \ + ({ \ + typeof (obj) _obj = (obj); \ + \ + nm_assert (!_obj || NMP_OBJECT_GET_TYPE ((const NMPObject *) _obj) == NMP_OBJECT_TYPE_IP4_ROUTE); \ + _obj ? &_NM_CONSTCAST (NMPObject, _obj)->ip4_route : NULL; \ + }) + +#define NMP_OBJECT_CAST_IP6_ROUTE(obj) \ + ({ \ + typeof (obj) _obj = (obj); \ + \ + nm_assert (!_obj || NMP_OBJECT_GET_TYPE ((const NMPObject *) _obj) == NMP_OBJECT_TYPE_IP6_ROUTE); \ + _obj ? &_NM_CONSTCAST (NMPObject, _obj)->ip6_route : NULL; \ + }) const NMPClass *nmp_class_from_type (NMPObjectType obj_type); -NMPObject *nmp_object_ref (NMPObject *object); -void nmp_object_unref (NMPObject *object); +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/retrun 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 const NMPObject * +nmp_object_unref (const NMPObject *obj) +{ + nm_dedup_multi_obj_unref ((const NMDedupMultiObj *) obj); + return NULL; +} + +#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; \ + }) + NMPObject *nmp_object_new (NMPObjectType obj_type, const NMPlatformObject *plob); NMPObject *nmp_object_new_link (int ifindex); const NMPObject *nmp_object_stackinit (NMPObject *obj, NMPObjectType obj_type, const NMPlatformObject *plobj); + +static inline NMPObject * +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); +} + 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, guint8 plen); -const NMPObject *nmp_object_stackinit_id_ip4_route (NMPObject *obj, int ifindex, guint32 network, guint8 plen, guint32 metric); -const NMPObject *nmp_object_stackinit_id_ip6_route (NMPObject *obj, int ifindex, const struct in6_addr *network, guint8 plen, guint32 metric); +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); gboolean nmp_object_equal (const NMPObject *obj1, const NMPObject *obj2); void nmp_object_copy (NMPObject *dst, const NMPObject *src, gboolean id_only); NMPObject *nmp_object_clone (const NMPObject *obj, gboolean id_only); -gboolean nmp_object_id_equal (const NMPObject *obj1, const NMPObject *obj2); + +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) +{ + return nmp_object_id_cmp (obj1, obj2) == 0; +} + 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, gboolean use_udev); +void _nmp_object_fixup_link_udev_fields (NMPObject **obj_new, NMPObject *obj_orig, gboolean use_udev); -#define nm_auto_nmpobj __attribute__((cleanup(_nm_auto_nmpobj_cleanup))) static inline void -_nm_auto_nmpobj_cleanup (NMPObject **pobj) +_nm_auto_nmpobj_cleanup (gpointer p) { - nmp_object_unref (*pobj); + 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); -gboolean nmp_cache_id_equal (const NMPCacheId *a, const NMPCacheId *b); -guint nmp_cache_id_hash (const NMPCacheId *id); -NMPCacheId *nmp_cache_id_clone (const NMPCacheId *id); -void nmp_cache_id_destroy (NMPCacheId *id); +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; +}; + +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) +{ + 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_addrroute (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); + +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) +{ + 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; +} + +static inline gboolean +nmp_cache_iter_next_link (NMDedupMultiIter *iter, const NMPlatformLink **out_obj) +{ + gboolean has_next; -NMPCacheId *nmp_cache_id_init_object_type (NMPCacheId *id, NMPObjectType obj_type, gboolean visible_only); -NMPCacheId *nmp_cache_id_init_addrroute_visible_by_ifindex (NMPCacheId *id, NMPObjectType obj_type, int ifindex); -NMPCacheId *nmp_cache_id_init_routes_visible (NMPCacheId *id, NMPObjectType obj_type, gboolean with_default, gboolean with_non_default, int ifindex); -NMPCacheId *nmp_cache_id_init_link_by_ifname (NMPCacheId *id, const char *ifname); -NMPCacheId *nmp_cache_id_init_routes_by_destination_ip4 (NMPCacheId *id, guint32 network, guint8 plen, guint32 metric); -NMPCacheId *nmp_cache_id_init_routes_by_destination_ip6 (NMPCacheId *id, const struct in6_addr *network, guint8 plen, guint32 metric); + 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; +} -const NMPlatformObject *const *nmp_cache_lookup_multi (const NMPCache *cache, const NMPCacheId *cache_id, guint *out_len); -GArray *nmp_cache_lookup_multi_to_array (const NMPCache *cache, NMPObjectType obj_type, const NMPCacheId *cache_id); -const NMPObject *nmp_cache_lookup_obj (const NMPCache *cache, const NMPObject *obj); -const NMPObject *nmp_cache_lookup_link (const NMPCache *cache, int ifindex); +#define nmp_cache_iter_for_each(iter, head, obj) \ + for (nm_dedup_multi_iter_init ((iter), \ + (head)); \ + nmp_cache_iter_next ((iter), (obj)); \ + ) -const NMPObject *nmp_cache_find_other_route_for_same_destination (const NMPCache *cache, const NMPObject *route); +#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, @@ -444,10 +602,8 @@ const NMPObject *nmp_cache_lookup_link_full (const NMPCache *cache, NMLinkType link_type, NMPObjectMatchFn match_fn, gpointer user_data); -GHashTable *nmp_cache_lookup_all_to_hash (const NMPCache *cache, - NMPCacheId *cache_id, - GHashTable *hash); +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); @@ -455,13 +611,182 @@ 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, gboolean equals_by_ptr, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data); -NMPCacheOpsType nmp_cache_remove_netlink (NMPCache *cache, const NMPObject *obj, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data); -NMPCacheOpsType nmp_cache_update_netlink (NMPCache *cache, NMPObject *obj, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data); -NMPCacheOpsType nmp_cache_update_link_udev (NMPCache *cache, int ifindex, struct udev_device *udevice, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data); -NMPCacheOpsType nmp_cache_update_link_master_connected (NMPCache *cache, int ifindex, NMPObject **out_obj, gboolean *out_was_visible, NMPCachePreHook pre_hook, gpointer user_data); - -NMPCache *nmp_cache_new (gboolean use_udev); +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); + +void nmp_cache_dirty_set_all (NMPCache *cache, NMPObjectType obj_type); + +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) +{ +#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)); +#endif +} + +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); + +static inline const NMDedupMultiHeadEntry * +nm_platform_lookup_obj_type (NMPlatform *platform, + NMPObjectType obj_type) +{ + NMPLookup 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) +{ + NMPLookup lookup; + + nmp_lookup_init_link_by_ifname (&lookup, ifname); + return nm_platform_lookup (platform, &lookup); +} + +static inline const NMDedupMultiHeadEntry * +nm_platform_lookup_addrroute (NMPlatform *platform, + NMPObjectType obj_type, + int ifindex) +{ + NMPLookup lookup; + + nmp_lookup_init_addrroute (&lookup, obj_type, ifindex); + return nm_platform_lookup (platform, &lookup); +} + +static inline GPtrArray * +nm_platform_lookup_addrroute_clone (NMPlatform *platform, + NMPObjectType obj_type, + int ifindex, + NMPObjectPredicateFunc predicate, + gpointer user_data) +{ + NMPLookup lookup; + + nmp_lookup_init_addrroute (&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) +{ + NMPLookup 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) +{ + NMPLookup lookup; + + 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) +{ + NMPLookup 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) +{ + NMPLookup lookup; + + nmp_lookup_init_ip6_route_by_weak_id (&lookup, network, plen, metric, src, src_plen); + return nm_platform_lookup (platform, &lookup); +} + #endif /* __NMP_OBJECT_H__ */ |