mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-05 12:20:36 +01:00
platform: use NMDedupMultiIndex for routes in NMPCache
Rework platform object cache to use NMDedupMultiIndex. Already previously, NMPCache used NMMultiIndex and had thus O(1) for most operations. What is new is: - Contrary to NMMultiIndex, NMDedupMultiIndex preserves the order of the cached items. That is crucial to handle routes properly as kernel will replace the first matching route based on network/plen/metric properties. See related bug rh#1337855. Without tracking the order of routes as they are exposed by kernel, we cannot properly maintain the route cache. - All NMPObject instances are now treated immutable, refcounted and get de-duplicated via NMDedupMultiIndex. This allows to have a global NMDedupMultiIndex that can be shared with NMIP4Config and NMRouteManager. It also allows to share the objects themselves. Immutable objects are so much nicer. We can get rid of the update pre-hook callback, which was required previously because we would mutate the object inplace. Now, we can just update the cache, and compare obj_old and obj_new after the fact. - NMMultiIndex was treated as an internal of NMPCache. On the other hand, NMDedupMultiIndex exposes NMDedupMultiHeadEntry, which is basically an object that allows to iterate over all related objects. That means, we can now lookup objects in the cache and give the NMDedupMultiHeadEntry instance to the caller, which then can iterate the list on it's own -- without need for copying anything. Currently, at various places we still create copies of lookup results. That can be improved later. The ability to share NMPObject instances should enable us to significantly improve performance and scale with large number of routes. Of course there is a memory overhead of having an index for each list entry. Each NMPObject may also require an NMDedupMultiEntry, NMDedupMultiHeadEntry, and NMDedupMultiBox item, which are tracked in a GHashTable. Optimally, one NMDedupMultiHeadEntry is the head for multiple objects, and NMDedupMultiBox is able to deduplicate several NMPObjects, so that there is a net saving. Also, each object type has several indexes of type NMPCacheIdType. So, worst case an NMPlatformIP4Route in the platform cache is tracked by 8 NMPCacheIdType indexes, for each we require a NMDedupMultiEntry, plus the shared NMDedupMultiHeadEntry. The NMDedupMultiBox instance is shared between the 8 indexes (and possibly other).
This commit is contained in:
parent
3edf2bff3d
commit
9440eefb6d
8 changed files with 1691 additions and 1297 deletions
|
|
@ -1173,7 +1173,7 @@ nm_route_manager_ip4_route_register_device_route_purge_list (NMRouteManager *sel
|
|||
? "update" : "new",
|
||||
nmp_object_to_string (entry->obj, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
|
||||
g_hash_table_replace (priv->ip4_device_routes.entries,
|
||||
nmp_object_ref (entry->obj),
|
||||
(NMPObject *) nmp_object_ref (entry->obj),
|
||||
entry);
|
||||
}
|
||||
if (priv->ip4_device_routes.gc_id == 0) {
|
||||
|
|
|
|||
|
|
@ -255,8 +255,11 @@ static void delayed_action_schedule (NMPlatform *platform, DelayedActionType act
|
|||
static gboolean delayed_action_handle_all (NMPlatform *platform, gboolean read_netlink);
|
||||
static void do_request_link_no_delayed_actions (NMPlatform *platform, int ifindex, const char *name);
|
||||
static void do_request_all_no_delayed_actions (NMPlatform *platform, DelayedActionType action_type);
|
||||
static void cache_pre_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMPCacheOpsType cache_op, gpointer user_data);
|
||||
static void cache_prune_candidates_prune (NMPlatform *platform);
|
||||
static void cache_on_change (NMPlatform *platform,
|
||||
NMPCacheOpsType cache_op,
|
||||
const NMPObject *obj_old,
|
||||
const NMPObject *obj_new);
|
||||
static void cache_prune_all (NMPlatform *platform);
|
||||
static gboolean event_handler_read_netlink (NMPlatform *platform, gboolean wait_for_acks);
|
||||
static void ASSERT_NETNS_CURRENT (NMPlatform *platform);
|
||||
|
||||
|
|
@ -1680,7 +1683,7 @@ _new_from_nl_link (NMPlatform *platform, const NMPCache *cache, struct nlmsghdr
|
|||
* Also, sometimes the info-data is missing for updates. In this case
|
||||
* we want to keep the previously received lnk_data. */
|
||||
nmp_object_unref (lnk_data);
|
||||
lnk_data = nmp_object_ref (link_cached->_link.netlink.lnk);
|
||||
lnk_data = (NMPObject *) nmp_object_ref (link_cached->_link.netlink.lnk);
|
||||
}
|
||||
if (address_complete_from_cache)
|
||||
obj->link.addr = link_cached->link.addr;
|
||||
|
|
@ -2574,7 +2577,9 @@ typedef struct {
|
|||
GIOChannel *event_channel;
|
||||
guint event_id;
|
||||
|
||||
gboolean sysctl_get_warned;
|
||||
bool pruning[_DELAYED_ACTION_IDX_REFRESH_ALL_NUM];
|
||||
|
||||
bool sysctl_get_warned;
|
||||
GHashTable *sysctl_get_prev_values;
|
||||
|
||||
NMUdevClient *udev_client;
|
||||
|
|
@ -2595,8 +2600,6 @@ typedef struct {
|
|||
gint is_handling;
|
||||
} delayed_action;
|
||||
|
||||
GHashTable *prune_candidates;
|
||||
|
||||
GHashTable *wifi_data;
|
||||
} NMLinuxPlatformPrivate;
|
||||
|
||||
|
|
@ -2913,29 +2916,20 @@ process_events (NMPlatform *platform)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define cache_lookup_all_objects(type, platform, obj_type, visible_only) \
|
||||
({ \
|
||||
NMPCacheId _cache_id; \
|
||||
\
|
||||
((const type *const*) nmp_cache_lookup_multi (NM_LINUX_PLATFORM_GET_PRIVATE ((platform))->cache, \
|
||||
nmp_cache_id_init_object_type (&_cache_id, (obj_type), (visible_only)), \
|
||||
NULL)); \
|
||||
})
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
do_emit_signal (NMPlatform *platform, const NMPObject *obj_new, NMPCacheOpsType cache_op, gboolean was_visible)
|
||||
do_emit_signal (NMPlatform *platform,
|
||||
NMPCacheOpsType cache_op,
|
||||
const NMPObject *obj_old,
|
||||
const NMPObject *obj_new)
|
||||
{
|
||||
gboolean is_visible;
|
||||
NMPObject obj_clone;
|
||||
gboolean visible_new;
|
||||
gboolean visible_old;
|
||||
const NMPObject *o;
|
||||
const NMPClass *klass;
|
||||
|
||||
nm_assert (NM_IN_SET ((NMPlatformSignalChangeType) cache_op, (NMPlatformSignalChangeType) NMP_CACHE_OPS_UNCHANGED, NM_PLATFORM_SIGNAL_ADDED, NM_PLATFORM_SIGNAL_CHANGED, NM_PLATFORM_SIGNAL_REMOVED));
|
||||
|
||||
nm_assert (obj_new || cache_op == NMP_CACHE_OPS_UNCHANGED);
|
||||
nm_assert (!obj_new || cache_op == NMP_CACHE_OPS_REMOVED || obj_new == nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, obj_new));
|
||||
nm_assert (!obj_new || cache_op != NMP_CACHE_OPS_REMOVED || obj_new != nmp_cache_lookup_obj (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, obj_new));
|
||||
ASSERT_nmp_cache_ops (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache, cache_op, obj_old, obj_new);
|
||||
|
||||
ASSERT_NETNS_CURRENT (platform);
|
||||
|
||||
|
|
@ -2943,52 +2937,49 @@ do_emit_signal (NMPlatform *platform, const NMPObject *obj_new, NMPCacheOpsType
|
|||
case NMP_CACHE_OPS_ADDED:
|
||||
if (!nmp_object_is_visible (obj_new))
|
||||
return;
|
||||
o = obj_new;
|
||||
break;
|
||||
case NMP_CACHE_OPS_UPDATED:
|
||||
is_visible = nmp_object_is_visible (obj_new);
|
||||
if (!was_visible && is_visible)
|
||||
visible_old = nmp_object_is_visible (obj_old);
|
||||
visible_new = nmp_object_is_visible (obj_new);
|
||||
if (!visible_old && visible_new) {
|
||||
o = obj_new;
|
||||
cache_op = NMP_CACHE_OPS_ADDED;
|
||||
else if (was_visible && !is_visible) {
|
||||
/* This is a bit ugly. The object was visible and changed in a way that it became invisible.
|
||||
* We raise a removed signal, but contrary to a real 'remove', @obj_new is already changed to be
|
||||
* different from what it was when the user saw it the last time.
|
||||
*
|
||||
* The more correct solution would be to have cache_pre_hook() create a clone of the original
|
||||
* value before it was changed to become invisible.
|
||||
*
|
||||
* But, don't bother. Probably nobody depends on the original values and only cares about the
|
||||
* id properties (which are still correct).
|
||||
*/
|
||||
} else if (visible_old && !visible_new) {
|
||||
o = obj_old;
|
||||
cache_op = NMP_CACHE_OPS_REMOVED;
|
||||
} else if (!is_visible)
|
||||
} else if (!visible_new) {
|
||||
/* it was invisible and stayed invisible. Nothing to do. */
|
||||
return;
|
||||
} else
|
||||
o = obj_new;
|
||||
break;
|
||||
case NMP_CACHE_OPS_REMOVED:
|
||||
if (!was_visible)
|
||||
if (!nmp_object_is_visible (obj_old))
|
||||
return;
|
||||
o = obj_old;
|
||||
break;
|
||||
default:
|
||||
g_assert (cache_op == NMP_CACHE_OPS_UNCHANGED);
|
||||
nm_assert (cache_op == NMP_CACHE_OPS_UNCHANGED);
|
||||
return;
|
||||
}
|
||||
|
||||
klass = NMP_OBJECT_GET_CLASS (obj_new);
|
||||
klass = NMP_OBJECT_GET_CLASS (o);
|
||||
|
||||
_LOGt ("emit signal %s %s: %s",
|
||||
klass->signal_type,
|
||||
nm_platform_signal_change_type_to_string ((NMPlatformSignalChangeType) cache_op),
|
||||
nmp_object_to_string (obj_new, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
|
||||
nmp_object_to_string (o, NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
|
||||
|
||||
/* don't expose @obj_new directly, but clone the public fields. A signal handler might
|
||||
* call back into NMPlatform which could invalidate (or modify) @obj_new. */
|
||||
memcpy (&obj_clone.object, &obj_new->object, klass->sizeof_public);
|
||||
nmp_object_ref (o);
|
||||
g_signal_emit (platform,
|
||||
_nm_platform_signal_id_get (klass->signal_type_id),
|
||||
0,
|
||||
(int) klass->obj_type,
|
||||
obj_clone.object.ifindex,
|
||||
&obj_clone.object,
|
||||
o->object.ifindex,
|
||||
&o->object,
|
||||
(int) cache_op);
|
||||
nmp_object_unref (o);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -3164,12 +3155,15 @@ static void
|
|||
delayed_action_handle_MASTER_CONNECTED (NMPlatform *platform, int master_ifindex)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
nm_auto_nmpobj NMPObject *obj_cache = NULL;
|
||||
gboolean was_visible;
|
||||
nm_auto_nmpobj const NMPObject *obj_old = NULL;
|
||||
nm_auto_nmpobj const NMPObject *obj_new = NULL;
|
||||
NMPCacheOpsType cache_op;
|
||||
|
||||
cache_op = nmp_cache_update_link_master_connected (priv->cache, master_ifindex, &obj_cache, &was_visible, cache_pre_hook, platform);
|
||||
do_emit_signal (platform, obj_cache, cache_op, was_visible);
|
||||
cache_op = nmp_cache_update_link_master_connected (priv->cache, master_ifindex, &obj_old, &obj_new);
|
||||
if (cache_op == NMP_CACHE_OPS_UNCHANGED)
|
||||
return;
|
||||
cache_on_change (platform, cache_op, obj_old, obj_new);
|
||||
do_emit_signal (platform, cache_op, obj_old, obj_new);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -3290,7 +3284,7 @@ delayed_action_handle_all (NMPlatform *platform, gboolean read_netlink)
|
|||
any = TRUE;
|
||||
priv->delayed_action.is_handling--;
|
||||
|
||||
cache_prune_candidates_prune (platform);
|
||||
cache_prune_all (platform);
|
||||
|
||||
return any;
|
||||
}
|
||||
|
|
@ -3353,101 +3347,69 @@ delayed_action_schedule_WAIT_FOR_NL_RESPONSE (NMPlatform *platform,
|
|||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
cache_prune_candidates_record_all (NMPlatform *platform, NMPObjectType obj_type)
|
||||
cache_prune_one_type (NMPlatform *platform, NMPObjectType obj_type)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
NMPCacheId cache_id;
|
||||
|
||||
priv->prune_candidates = nmp_cache_lookup_all_to_hash (priv->cache,
|
||||
nmp_cache_id_init_object_type (&cache_id, obj_type, FALSE),
|
||||
priv->prune_candidates);
|
||||
_LOGt ("cache-prune: record %s (now %u candidates)", nmp_class_from_type (obj_type)->obj_type_name,
|
||||
priv->prune_candidates ? g_hash_table_size (priv->prune_candidates) : 0);
|
||||
}
|
||||
|
||||
static void
|
||||
cache_prune_candidates_record_one (NMPlatform *platform, NMPObject *obj)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv;
|
||||
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
|
||||
if (!priv->prune_candidates)
|
||||
priv->prune_candidates = g_hash_table_new_full (NULL, NULL, (GDestroyNotify) nmp_object_unref, NULL);
|
||||
|
||||
if (_LOGt_ENABLED () && !g_hash_table_contains (priv->prune_candidates, obj))
|
||||
_LOGt ("cache-prune: record-one: %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0));
|
||||
g_hash_table_add (priv->prune_candidates, nmp_object_ref (obj));
|
||||
}
|
||||
|
||||
static void
|
||||
cache_prune_candidates_drop (NMPlatform *platform, const NMPObject *obj)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv;
|
||||
|
||||
if (!obj)
|
||||
return;
|
||||
|
||||
priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
if (priv->prune_candidates) {
|
||||
if (_LOGt_ENABLED () && g_hash_table_contains (priv->prune_candidates, obj))
|
||||
_LOGt ("cache-prune: drop-one: %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0));
|
||||
g_hash_table_remove (priv->prune_candidates, obj);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cache_prune_candidates_prune (NMPlatform *platform)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
GHashTable *prune_candidates;
|
||||
GHashTableIter iter;
|
||||
NMDedupMultiIter iter;
|
||||
const NMPObject *obj;
|
||||
gboolean was_visible;
|
||||
NMPCacheOpsType cache_op;
|
||||
NMPLookup lookup;
|
||||
|
||||
if (!priv->prune_candidates)
|
||||
return;
|
||||
nmp_lookup_init_obj_type (&lookup,
|
||||
obj_type,
|
||||
FALSE);
|
||||
nm_dedup_multi_iter_init (&iter,
|
||||
nmp_cache_lookup (priv->cache,
|
||||
&lookup));
|
||||
while (nm_dedup_multi_iter_next (&iter)) {
|
||||
if (iter.current->dirty) {
|
||||
nm_auto_nmpobj const NMPObject *obj_old = NULL;
|
||||
|
||||
prune_candidates = priv->prune_candidates;
|
||||
priv->prune_candidates = NULL;
|
||||
|
||||
g_hash_table_iter_init (&iter, prune_candidates);
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *)&obj, NULL)) {
|
||||
nm_auto_nmpobj NMPObject *obj_cache = NULL;
|
||||
|
||||
_LOGt ("cache-prune: prune %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0));
|
||||
cache_op = nmp_cache_remove (priv->cache, obj, TRUE, &obj_cache, &was_visible, cache_pre_hook, platform);
|
||||
do_emit_signal (platform, obj_cache, cache_op, was_visible);
|
||||
obj = iter.current->box->obj;
|
||||
_LOGt ("cache-prune: prune %s", nmp_object_to_string (obj, NMP_OBJECT_TO_STRING_ALL, NULL, 0));
|
||||
cache_op = nmp_cache_remove (priv->cache, obj, TRUE, &obj_old);
|
||||
nm_assert (cache_op == NMP_CACHE_OPS_REMOVED);
|
||||
cache_on_change (platform, cache_op, obj_old, NULL);
|
||||
do_emit_signal (platform, cache_op, obj_old, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_unref (prune_candidates);
|
||||
}
|
||||
|
||||
static void
|
||||
cache_pre_hook (NMPCache *cache, const NMPObject *obj_old, const NMPObject *obj_new, NMPCacheOpsType cache_op, gpointer user_data)
|
||||
cache_prune_all (NMPlatform *platform)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
DelayedActionType iflags, action_type;
|
||||
|
||||
action_type = DELAYED_ACTION_TYPE_REFRESH_ALL;
|
||||
FOR_EACH_DELAYED_ACTION (iflags, action_type) {
|
||||
bool *p = &priv->pruning[delayed_action_refresh_all_to_idx (iflags)];
|
||||
|
||||
if (*p) {
|
||||
*p = FALSE;
|
||||
cache_prune_one_type (platform, delayed_action_refresh_to_object_type (iflags));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cache_on_change (NMPlatform *platform,
|
||||
NMPCacheOpsType cache_op,
|
||||
const NMPObject *obj_old,
|
||||
const NMPObject *obj_new)
|
||||
{
|
||||
NMPlatform *platform = user_data;
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
const NMPClass *klass;
|
||||
char str_buf[sizeof (_nm_utils_to_string_buffer)];
|
||||
char str_buf2[sizeof (_nm_utils_to_string_buffer)];
|
||||
|
||||
nm_assert (obj_old || obj_new);
|
||||
nm_assert (NM_IN_SET (cache_op, NMP_CACHE_OPS_ADDED, NMP_CACHE_OPS_REMOVED, NMP_CACHE_OPS_UPDATED));
|
||||
nm_assert (cache_op != NMP_CACHE_OPS_ADDED || (obj_old == NULL && NMP_OBJECT_IS_VALID (obj_new) && nmp_object_is_alive (obj_new)));
|
||||
nm_assert (cache_op != NMP_CACHE_OPS_REMOVED || (obj_new == NULL && NMP_OBJECT_IS_VALID (obj_old) && nmp_object_is_alive (obj_old)));
|
||||
nm_assert (cache_op != NMP_CACHE_OPS_UPDATED || (NMP_OBJECT_IS_VALID (obj_old) && nmp_object_is_alive (obj_old) && NMP_OBJECT_IS_VALID (obj_new) && nmp_object_is_alive (obj_new)));
|
||||
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));
|
||||
ASSERT_nmp_cache_ops (priv->cache, cache_op, obj_old, obj_new);
|
||||
|
||||
if (cache_op == NMP_CACHE_OPS_UNCHANGED)
|
||||
return;
|
||||
|
||||
klass = obj_old ? NMP_OBJECT_GET_CLASS (obj_old) : NMP_OBJECT_GET_CLASS (obj_new);
|
||||
|
||||
nm_assert (klass == (obj_new ? NMP_OBJECT_GET_CLASS (obj_new) : NMP_OBJECT_GET_CLASS (obj_old)));
|
||||
|
||||
_LOGt ("update-cache-%s: %s: %s%s%s",
|
||||
klass->obj_type_name,
|
||||
(cache_op == NMP_CACHE_OPS_UPDATED
|
||||
|
|
@ -3478,7 +3440,7 @@ cache_pre_hook (NMPCache *cache, const NMPObject *obj_old, const NMPObject *obj_
|
|||
{
|
||||
/* check whether we are about to change a master link that needs toggling connected state. */
|
||||
if ( obj_new /* <-- nonsensical, make coverity happy */
|
||||
&& nmp_cache_link_connected_needs_toggle (cache, obj_new, obj_new, obj_old))
|
||||
&& nmp_cache_link_connected_needs_toggle (priv->cache, obj_new, obj_new, obj_old))
|
||||
delayed_action_schedule (platform, DELAYED_ACTION_TYPE_MASTER_CONNECTED, GINT_TO_POINTER (obj_new->link.ifindex));
|
||||
}
|
||||
{
|
||||
|
|
@ -3522,16 +3484,16 @@ cache_pre_hook (NMPCache *cache, const NMPObject *obj_old, const NMPObject *obj_
|
|||
ifindex = obj_new->link.ifindex;
|
||||
|
||||
if (ifindex > 0) {
|
||||
const NMPlatformLink *const *links;
|
||||
NMPLookup lookup;
|
||||
NMDedupMultiIter iter;
|
||||
const NMPlatformLink *l;
|
||||
|
||||
links = cache_lookup_all_objects (NMPlatformLink, platform, NMP_OBJECT_TYPE_LINK, FALSE);
|
||||
if (links) {
|
||||
for (; *links; links++) {
|
||||
const NMPlatformLink *l = (*links);
|
||||
|
||||
if (l->parent == ifindex)
|
||||
delayed_action_schedule (platform, DELAYED_ACTION_TYPE_REFRESH_LINK, GINT_TO_POINTER (l->ifindex));
|
||||
}
|
||||
nmp_lookup_init_link (&lookup, FALSE);
|
||||
nmp_cache_iter_for_each_link (&iter,
|
||||
nmp_cache_lookup (priv->cache, &lookup),
|
||||
&l) {
|
||||
if (l->parent == ifindex)
|
||||
delayed_action_schedule (platform, DELAYED_ACTION_TYPE_REFRESH_LINK, GINT_TO_POINTER (l->ifindex));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3664,14 +3626,12 @@ static void
|
|||
cache_post (NMPlatform *platform,
|
||||
struct nlmsghdr *msghdr,
|
||||
NMPCacheOpsType cache_op,
|
||||
NMPObject *obj,
|
||||
NMPObject *obj_cache)
|
||||
const NMPObject *obj,
|
||||
const NMPObject *obj_old,
|
||||
const NMPObject *obj_new)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
|
||||
nm_assert (NMP_OBJECT_IS_VALID (obj));
|
||||
nm_assert (!obj_cache || nmp_object_id_equal (obj, obj_cache));
|
||||
|
||||
if (msghdr->nlmsg_type == RTM_NEWROUTE) {
|
||||
DelayedActionType action_type;
|
||||
|
||||
|
|
@ -3739,8 +3699,13 @@ do_request_link_no_delayed_actions (NMPlatform *platform, int ifindex, const cha
|
|||
_LOGD ("do-request-link: %d %s", ifindex, name ? name : "");
|
||||
|
||||
if (ifindex > 0) {
|
||||
cache_prune_candidates_record_one (platform,
|
||||
(NMPObject *) nmp_cache_lookup_link (priv->cache, ifindex));
|
||||
const NMDedupMultiEntry *entry;
|
||||
|
||||
entry = nmp_cache_lookup_entry_link (priv->cache, ifindex);
|
||||
if (entry) {
|
||||
priv->pruning[DELAYED_ACTION_IDX_REFRESH_ALL_LINKS] = TRUE;
|
||||
nm_dedup_multi_entry_set_dirty (entry, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
event_handler_read_netlink (platform, FALSE);
|
||||
|
|
@ -3772,7 +3737,9 @@ do_request_all_no_delayed_actions (NMPlatform *platform, DelayedActionType actio
|
|||
action_type &= DELAYED_ACTION_TYPE_REFRESH_ALL;
|
||||
|
||||
FOR_EACH_DELAYED_ACTION (iflags, action_type) {
|
||||
cache_prune_candidates_record_all (platform, delayed_action_refresh_to_object_type (iflags));
|
||||
priv->pruning[delayed_action_refresh_all_to_idx (iflags)] = TRUE;
|
||||
nmp_cache_dirty_set_all (priv->cache,
|
||||
delayed_action_refresh_to_object_type (iflags));
|
||||
}
|
||||
|
||||
FOR_EACH_DELAYED_ACTION (iflags, action_type) {
|
||||
|
|
@ -3898,12 +3865,10 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_event
|
|||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
nm_auto_nmpobj NMPObject *obj = NULL;
|
||||
nm_auto_nmpobj NMPObject *obj_cache = NULL;
|
||||
NMPCacheOpsType cache_op;
|
||||
struct nlmsghdr *msghdr;
|
||||
char buf_nlmsg_type[16];
|
||||
gboolean id_only = FALSE;
|
||||
gboolean was_visible;
|
||||
|
||||
msghdr = nlmsg_hdr (msg);
|
||||
|
||||
|
|
@ -3932,31 +3897,36 @@ event_valid_msg (NMPlatform *platform, struct nl_msg *msg, gboolean handle_event
|
|||
msghdr->nlmsg_seq, nmp_object_to_string (obj,
|
||||
id_only ? NMP_OBJECT_TO_STRING_ID : NMP_OBJECT_TO_STRING_PUBLIC, NULL, 0));
|
||||
|
||||
switch (msghdr->nlmsg_type) {
|
||||
{
|
||||
nm_auto_nmpobj const NMPObject *obj_old = NULL;
|
||||
nm_auto_nmpobj const NMPObject *obj_new = NULL;
|
||||
|
||||
case RTM_NEWLINK:
|
||||
case RTM_NEWADDR:
|
||||
case RTM_NEWROUTE:
|
||||
case RTM_GETLINK:
|
||||
cache_op = nmp_cache_update_netlink (priv->cache, obj, &obj_cache, &was_visible, cache_pre_hook, platform);
|
||||
switch (msghdr->nlmsg_type) {
|
||||
|
||||
cache_post (platform, msghdr, cache_op, obj, obj_cache);
|
||||
case RTM_NEWLINK:
|
||||
case RTM_NEWADDR:
|
||||
case RTM_NEWROUTE:
|
||||
case RTM_GETLINK:
|
||||
cache_op = nmp_cache_update_netlink (priv->cache, obj, &obj_old, &obj_new);
|
||||
cache_on_change (platform, cache_op, obj_old, obj_new);
|
||||
cache_post (platform, msghdr, cache_op, obj, obj_old, obj_new);
|
||||
do_emit_signal (platform, cache_op, obj_old, obj_new);
|
||||
break;
|
||||
|
||||
do_emit_signal (platform, obj_cache, cache_op, was_visible);
|
||||
break;
|
||||
case RTM_DELLINK:
|
||||
case RTM_DELADDR:
|
||||
case RTM_DELROUTE:
|
||||
cache_op = nmp_cache_remove_netlink (priv->cache, obj, &obj_old, &obj_new);
|
||||
if (cache_op != NMP_CACHE_OPS_UNCHANGED) {
|
||||
cache_on_change (platform, cache_op, obj_old, obj_new);
|
||||
do_emit_signal (platform, cache_op, obj_old, obj_new);
|
||||
}
|
||||
break;
|
||||
|
||||
case RTM_DELLINK:
|
||||
case RTM_DELADDR:
|
||||
case RTM_DELROUTE:
|
||||
cache_op = nmp_cache_remove_netlink (priv->cache, obj, &obj_cache, &was_visible, cache_pre_hook, platform);
|
||||
do_emit_signal (platform, obj_cache, cache_op, was_visible);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
cache_prune_candidates_drop (platform, obj_cache);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -3973,25 +3943,15 @@ cache_lookup_link (NMPlatform *platform, int ifindex)
|
|||
return obj_cache;
|
||||
}
|
||||
|
||||
const NMPlatformObject *const*
|
||||
nm_linux_platform_lookup (NMPlatform *platform, const NMPCacheId *cache_id, guint *out_len)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_LINUX_PLATFORM (platform), NULL);
|
||||
g_return_val_if_fail (cache_id, NULL);
|
||||
|
||||
return nmp_cache_lookup_multi (NM_LINUX_PLATFORM_GET_PRIVATE (platform)->cache,
|
||||
cache_id, out_len);
|
||||
}
|
||||
|
||||
static GArray *
|
||||
link_get_all (NMPlatform *platform)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
NMPCacheId cache_id;
|
||||
NMPLookup lookup;
|
||||
|
||||
return nmp_cache_lookup_multi_to_array (priv->cache,
|
||||
NMP_OBJECT_TYPE_LINK,
|
||||
nmp_cache_id_init_object_type (&cache_id, NMP_OBJECT_TYPE_LINK, TRUE));
|
||||
nmp_lookup_init_link (&lookup, TRUE);
|
||||
return nmp_cache_lookup_to_array (nmp_cache_lookup (priv->cache, &lookup),
|
||||
NMP_OBJECT_TYPE_LINK);
|
||||
}
|
||||
|
||||
static const NMPlatformLink *
|
||||
|
|
@ -5733,10 +5693,9 @@ static gboolean
|
|||
link_can_assume (NMPlatform *platform, int ifindex)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
NMPCacheId cache_id;
|
||||
const NMPlatformObject *const *objs;
|
||||
guint i, len;
|
||||
const NMPObject *link;
|
||||
NMPLookup lookup;
|
||||
const NMPObject *link, *o;
|
||||
NMDedupMultiIter iter;
|
||||
|
||||
if (ifindex <= 0)
|
||||
return FALSE;
|
||||
|
|
@ -5751,21 +5710,23 @@ link_can_assume (NMPlatform *platform, int ifindex)
|
|||
if (link->link.master > 0)
|
||||
return TRUE;
|
||||
|
||||
if (nmp_cache_lookup_multi (priv->cache,
|
||||
nmp_cache_id_init_addrroute_visible_by_ifindex (&cache_id, NMP_OBJECT_TYPE_IP4_ADDRESS, ifindex),
|
||||
NULL))
|
||||
nmp_lookup_init_addrroute (&lookup,
|
||||
NMP_OBJECT_TYPE_IP4_ADDRESS,
|
||||
ifindex,
|
||||
TRUE);
|
||||
if (nmp_cache_lookup (priv->cache, &lookup))
|
||||
return TRUE;
|
||||
|
||||
objs = nmp_cache_lookup_multi (priv->cache,
|
||||
nmp_cache_id_init_addrroute_visible_by_ifindex (&cache_id, NMP_OBJECT_TYPE_IP6_ADDRESS, ifindex),
|
||||
&len);
|
||||
if (objs) {
|
||||
for (i = 0; i < len; i++) {
|
||||
const NMPlatformIP6Address *a = (NMPlatformIP6Address *) objs[i];
|
||||
|
||||
if (!IN6_IS_ADDR_LINKLOCAL (&a->address))
|
||||
nmp_lookup_init_addrroute (&lookup,
|
||||
NMP_OBJECT_TYPE_IP6_ADDRESS,
|
||||
ifindex,
|
||||
TRUE);
|
||||
nmp_cache_iter_for_each (&iter,
|
||||
nmp_cache_lookup (priv->cache, &lookup),
|
||||
&o) {
|
||||
nm_assert (NMP_OBJECT_GET_TYPE (o) == NMP_OBJECT_TYPE_IP6_ADDRESS);
|
||||
if (!IN6_IS_ADDR_LINKLOCAL (&o->ip6_address.address))
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -5844,15 +5805,15 @@ static GArray *
|
|||
ipx_address_get_all (NMPlatform *platform, int ifindex, NMPObjectType obj_type)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
NMPCacheId cache_id;
|
||||
NMPLookup lookup;
|
||||
|
||||
nm_assert (NM_IN_SET (obj_type, NMP_OBJECT_TYPE_IP4_ADDRESS, NMP_OBJECT_TYPE_IP6_ADDRESS));
|
||||
|
||||
return nmp_cache_lookup_multi_to_array (priv->cache,
|
||||
obj_type,
|
||||
nmp_cache_id_init_addrroute_visible_by_ifindex (&cache_id,
|
||||
obj_type,
|
||||
ifindex));
|
||||
nmp_lookup_init_addrroute (&lookup,
|
||||
obj_type,
|
||||
ifindex,
|
||||
TRUE);
|
||||
return nmp_cache_lookup_to_array (nmp_cache_lookup (priv->cache, &lookup),
|
||||
obj_type);
|
||||
}
|
||||
|
||||
static GArray *
|
||||
|
|
@ -6010,12 +5971,13 @@ static GArray *
|
|||
ipx_route_get_all (NMPlatform *platform, int ifindex, NMPObjectType obj_type, NMPlatformGetRouteFlags flags)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
NMPCacheId cache_id;
|
||||
const NMPlatformIPRoute *const* routes;
|
||||
NMDedupMultiIter iter;
|
||||
NMPLookup lookup;
|
||||
const NMDedupMultiHeadEntry *head_entry;
|
||||
GArray *array;
|
||||
const NMPClass *klass;
|
||||
const NMPObject *o;
|
||||
gboolean with_rtprot_kernel;
|
||||
guint i, len;
|
||||
|
||||
nm_assert (NM_IN_SET (obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE));
|
||||
|
||||
|
|
@ -6024,23 +5986,24 @@ ipx_route_get_all (NMPlatform *platform, int ifindex, NMPObjectType obj_type, NM
|
|||
|
||||
klass = nmp_class_from_type (obj_type);
|
||||
|
||||
nmp_cache_id_init_routes_visible (&cache_id,
|
||||
obj_type,
|
||||
NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT),
|
||||
NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT),
|
||||
ifindex);
|
||||
head_entry = nmp_cache_lookup (priv->cache,
|
||||
nmp_lookup_init_route_visible (&lookup,
|
||||
obj_type,
|
||||
ifindex,
|
||||
NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_DEFAULT),
|
||||
NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_NON_DEFAULT)));
|
||||
|
||||
routes = (const NMPlatformIPRoute *const*) nmp_cache_lookup_multi (priv->cache, &cache_id, &len);
|
||||
|
||||
array = g_array_sized_new (FALSE, FALSE, klass->sizeof_public, len);
|
||||
array = g_array_sized_new (FALSE, FALSE, klass->sizeof_public, head_entry ? head_entry->len : 0);
|
||||
|
||||
with_rtprot_kernel = NM_FLAGS_HAS (flags, NM_PLATFORM_GET_ROUTE_FLAGS_WITH_RTPROT_KERNEL);
|
||||
for (i = 0; i < len; i++) {
|
||||
nm_assert (NMP_OBJECT_GET_CLASS (NMP_OBJECT_UP_CAST (routes[i])) == klass);
|
||||
|
||||
nmp_cache_iter_for_each (&iter,
|
||||
head_entry,
|
||||
&o) {
|
||||
nm_assert (NMP_OBJECT_GET_CLASS (o) == klass);
|
||||
if ( with_rtprot_kernel
|
||||
|| routes[i]->rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
|
||||
g_array_append_vals (array, routes[i], 1);
|
||||
|| o->ip_route.rt_source != NM_IP_CONFIG_SOURCE_RTPROT_KERNEL)
|
||||
g_array_append_vals (array, &o->ip_route, 1);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
|
@ -6634,18 +6597,19 @@ cache_update_link_udev (NMPlatform *platform,
|
|||
struct udev_device *udevice)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (platform);
|
||||
nm_auto_nmpobj NMPObject *obj_cache = NULL;
|
||||
gboolean was_visible;
|
||||
nm_auto_nmpobj const NMPObject *obj_old = NULL;
|
||||
nm_auto_nmpobj const NMPObject *obj_new = NULL;
|
||||
NMPCacheOpsType cache_op;
|
||||
|
||||
cache_op = nmp_cache_update_link_udev (priv->cache, ifindex, udevice, &obj_cache, &was_visible, cache_pre_hook, platform);
|
||||
cache_op = nmp_cache_update_link_udev (priv->cache, ifindex, udevice, &obj_old, &obj_new);
|
||||
|
||||
if (cache_op != NMP_CACHE_OPS_UNCHANGED) {
|
||||
nm_auto_pop_netns NMPNetns *netns = NULL;
|
||||
|
||||
cache_on_change (platform, cache_op, obj_old, obj_new);
|
||||
if (!nm_platform_netns_push (platform, &netns))
|
||||
return;
|
||||
do_emit_signal (platform, obj_cache, cache_op, was_visible);
|
||||
do_emit_signal (platform, cache_op, obj_old, obj_new);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6753,19 +6717,15 @@ static void
|
|||
nm_linux_platform_init (NMLinuxPlatform *self)
|
||||
{
|
||||
NMLinuxPlatformPrivate *priv = NM_LINUX_PLATFORM_GET_PRIVATE (self);
|
||||
gboolean use_udev;
|
||||
|
||||
use_udev = nmp_netns_is_initial ()
|
||||
&& access ("/sys", W_OK) == 0;
|
||||
|
||||
priv->nlh_seq_next = 1;
|
||||
priv->cache = nmp_cache_new (use_udev);
|
||||
priv->delayed_action.list_master_connected = g_ptr_array_new ();
|
||||
priv->delayed_action.list_refresh_link = g_ptr_array_new ();
|
||||
priv->delayed_action.list_wait_for_nl_response = g_array_new (FALSE, TRUE, sizeof (DelayedActionWaitForNlResponseData));
|
||||
priv->wifi_data = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) wifi_utils_deinit);
|
||||
|
||||
if (use_udev) {
|
||||
if ( nmp_netns_is_initial ()
|
||||
&& access ("/sys", W_OK) == 0) {
|
||||
priv->udev_client = nm_udev_client_new ((const char *[]) { "net", NULL },
|
||||
handle_udev_event, self);
|
||||
}
|
||||
|
|
@ -6782,6 +6742,9 @@ constructed (GObject *_object)
|
|||
|
||||
nm_assert (!platform->_netns || platform->_netns == nmp_netns_get_current ());
|
||||
|
||||
priv->cache = nmp_cache_new (nm_platform_get_multi_idx (platform),
|
||||
priv->udev_client != NULL);
|
||||
|
||||
_LOGD ("create (%s netns, %s, %s udev)",
|
||||
!platform->_netns ? "ignore" : "use",
|
||||
!platform->_netns && nmp_netns_is_initial ()
|
||||
|
|
@ -6892,8 +6855,6 @@ dispose (GObject *object)
|
|||
g_ptr_array_set_size (priv->delayed_action.list_master_connected, 0);
|
||||
g_ptr_array_set_size (priv->delayed_action.list_refresh_link, 0);
|
||||
|
||||
g_clear_pointer (&priv->prune_candidates, g_hash_table_unref);
|
||||
|
||||
G_OBJECT_CLASS (nm_linux_platform_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,10 +39,4 @@ NMPlatform *nm_linux_platform_new (gboolean log_with_ptr, gboolean netns_support
|
|||
|
||||
void nm_linux_platform_setup (void);
|
||||
|
||||
struct _NMPCacheId;
|
||||
|
||||
const NMPlatformObject *const *nm_linux_platform_lookup (NMPlatform *platform,
|
||||
const struct _NMPCacheId *cache_id,
|
||||
guint *out_len);
|
||||
|
||||
#endif /* __NETWORKMANAGER_LINUX_PLATFORM_H__ */
|
||||
|
|
|
|||
|
|
@ -4149,6 +4149,39 @@ nm_platform_ip6_route_to_string (const NMPlatformIP6Route *route, char *buf, gsi
|
|||
return c < 0 ? -1 : 1; \
|
||||
} G_STMT_END
|
||||
|
||||
guint
|
||||
nm_platform_link_hash (const NMPlatformLink *obj)
|
||||
{
|
||||
guint h = 99413953;
|
||||
guint8 i8;
|
||||
|
||||
h = NM_HASH_COMBINE (h, obj->ifindex);
|
||||
h = NM_HASH_COMBINE (h, obj->type);
|
||||
h = NM_HASH_COMBINE (h, g_str_hash (obj->name));
|
||||
h = NM_HASH_COMBINE (h, obj->master);
|
||||
h = NM_HASH_COMBINE (h, obj->parent);
|
||||
h = NM_HASH_COMBINE (h, obj->n_ifi_flags);
|
||||
h = NM_HASH_COMBINE (h, obj->connected);
|
||||
h = NM_HASH_COMBINE (h, obj->mtu);
|
||||
h = NM_HASH_COMBINE (h, !!obj->initialized);
|
||||
h = NM_HASH_COMBINE (h, obj->arptype);
|
||||
h = NM_HASH_COMBINE (h, obj->addr.len);
|
||||
h = NM_HASH_COMBINE (h, obj->inet6_addr_gen_mode_inv);
|
||||
if (obj->kind)
|
||||
h = NM_HASH_COMBINE (h, g_str_hash (obj->kind));
|
||||
if (obj->driver)
|
||||
h = NM_HASH_COMBINE (h, g_str_hash (obj->driver));
|
||||
for (i8 = 0; i8 < obj->addr.len; i8++)
|
||||
h = NM_HASH_COMBINE (h, obj->addr.data[i8]);
|
||||
for (i8 = 0; i8 < sizeof (obj->inet6_token); i8++)
|
||||
h = NM_HASH_COMBINE (h, obj->inet6_token.id_u8[i8]);
|
||||
h = NM_HASH_COMBINE (h, obj->rx_packets);
|
||||
h = NM_HASH_COMBINE (h, obj->rx_bytes);
|
||||
h = NM_HASH_COMBINE (h, obj->tx_packets);
|
||||
h = NM_HASH_COMBINE (h, obj->tx_bytes);
|
||||
return h;
|
||||
}
|
||||
|
||||
int
|
||||
nm_platform_link_cmp (const NMPlatformLink *a, const NMPlatformLink *b)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1024,6 +1024,7 @@ nm_platform_ip6_route_cmp (const NMPlatformIP6Route *a, const NMPlatformIP6Route
|
|||
return nm_platform_ip6_route_cmp_full (a, b, TRUE);
|
||||
}
|
||||
|
||||
guint nm_platform_link_hash (const NMPlatformLink *obj);
|
||||
guint nm_platform_ip4_address_hash (const NMPlatformIP4Address *obj);
|
||||
guint nm_platform_ip6_address_hash (const NMPlatformIP6Address *obj);
|
||||
guint nm_platform_ip4_route_hash (const NMPlatformIP4Route *obj);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -24,7 +24,6 @@
|
|||
#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;
|
||||
|
||||
|
|
@ -60,7 +59,14 @@ typedef enum { /*< skip >*/
|
|||
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). */
|
||||
NMP_CACHE_ID_TYPE_OBJECT_TYPE,
|
||||
|
||||
/* index for the link objects by ifname. */
|
||||
|
|
@ -76,7 +82,7 @@ typedef enum { /*< skip >*/
|
|||
/* 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. */
|
||||
/* 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,
|
||||
|
||||
|
|
@ -95,50 +101,6 @@ typedef enum { /*< skip >*/
|
|||
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;
|
||||
|
|
@ -155,10 +117,6 @@ 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);
|
||||
|
||||
guint (*cmd_obj_hash) (const NMPObject *obj);
|
||||
int (*cmd_obj_cmp) (const NMPObject *obj1, const NMPObject *obj2);
|
||||
void (*cmd_obj_copy) (NMPObject *dst, const NMPObject *src);
|
||||
|
|
@ -276,7 +234,6 @@ struct _NMPObject {
|
|||
const NMPClass *_class;
|
||||
};
|
||||
guint _ref_count;
|
||||
bool is_cached;
|
||||
union {
|
||||
NMPlatformObject object;
|
||||
|
||||
|
|
@ -387,8 +344,8 @@ NMP_OBJECT_GET_TYPE (const NMPObject *obj)
|
|||
|
||||
const NMPClass *nmp_class_from_type (NMPObjectType obj_type);
|
||||
|
||||
NMPObject *nmp_object_ref (NMPObject *object);
|
||||
void nmp_object_unref (NMPObject *object);
|
||||
const NMPObject *nmp_object_ref (const NMPObject *object);
|
||||
void nmp_object_unref (const NMPObject *object);
|
||||
NMPObject *nmp_object_new (NMPObjectType obj_type, const NMPlatformObject *plob);
|
||||
NMPObject *nmp_object_new_link (int ifindex);
|
||||
|
||||
|
|
@ -411,13 +368,13 @@ guint nmp_object_id_hash (const NMPObject *obj);
|
|||
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));
|
||||
}
|
||||
|
||||
typedef struct _NMPCache NMPCache;
|
||||
|
|
@ -425,23 +382,90 @@ 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_link (const NMPCache *cache, int ifindex);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
typedef struct {
|
||||
NMPCacheIdType cache_id_type;
|
||||
NMPObject selector_obj;
|
||||
} NMPLookup;
|
||||
|
||||
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,
|
||||
gboolean visible_only);
|
||||
const NMPLookup *nmp_lookup_init_link (NMPLookup *lookup,
|
||||
gboolean visible_only);
|
||||
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,
|
||||
gboolean visible_only);
|
||||
const NMPLookup *nmp_lookup_init_route_visible (NMPLookup *lookup,
|
||||
NMPObjectType obj_type,
|
||||
int ifindex,
|
||||
gboolean with_default,
|
||||
gboolean with_non_default);
|
||||
const NMPLookup *nmp_lookup_init_route_by_dest (NMPLookup *lookup,
|
||||
int addr_family,
|
||||
gconstpointer network,
|
||||
guint plen,
|
||||
guint32 metric);
|
||||
|
||||
GArray *nmp_cache_lookup_to_array (const NMDedupMultiHeadEntry *head_entry,
|
||||
NMPObjectType obj_type);
|
||||
|
||||
static inline gboolean
|
||||
nmp_cache_iter_next (NMDedupMultiIter *iter, const NMPObject **out_obj)
|
||||
{
|
||||
gboolean has_next;
|
||||
|
||||
has_next = nm_dedup_multi_iter_next (iter);
|
||||
if (has_next) {
|
||||
nm_assert (NMP_OBJECT_IS_VALID (iter->current->box->obj));
|
||||
NM_SET_OUT (out_obj, iter->current->box->obj);
|
||||
}
|
||||
return has_next;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
nmp_cache_iter_next_link (NMDedupMultiIter *iter, const NMPlatformLink **out_obj)
|
||||
{
|
||||
gboolean has_next;
|
||||
|
||||
has_next = nm_dedup_multi_iter_next (iter);
|
||||
if (has_next) {
|
||||
nm_assert (NMP_OBJECT_GET_TYPE (iter->current->box->obj) == NMP_OBJECT_TYPE_LINK);
|
||||
NM_SET_OUT (out_obj, &(((const NMPObject *) iter->current->box->obj)->link));
|
||||
}
|
||||
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)); \
|
||||
)
|
||||
|
||||
#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_find_other_route_for_same_destination (const NMPCache *cache, const NMPObject *route);
|
||||
|
||||
const NMPObject *nmp_cache_lookup_link_full (const NMPCache *cache,
|
||||
|
|
@ -451,9 +475,6 @@ 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_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);
|
||||
|
|
@ -462,13 +483,71 @@ 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);
|
||||
NMPCacheOpsType nmp_cache_remove (NMPCache *cache,
|
||||
const NMPObject *obj_needle,
|
||||
gboolean equals_by_ptr,
|
||||
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,
|
||||
const NMPObject **out_obj_old,
|
||||
const NMPObject **out_obj_new);
|
||||
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);
|
||||
|
||||
NMPCache *nmp_cache_new (gboolean use_udev);
|
||||
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
|
||||
}
|
||||
|
||||
#endif /* __NMP_OBJECT_H__ */
|
||||
|
|
|
|||
|
|
@ -103,150 +103,141 @@ _nmp_object_equal (const NMPObject *a, const NMPObject *b)
|
|||
/*****************************************************************************/
|
||||
|
||||
static void
|
||||
_assert_cache_multi_lookup_contains (const NMPCache *cache, const NMPCacheId *cache_id, const NMPObject *obj, gboolean contains)
|
||||
_assert_cache_multi_lookup_contains (const NMPCache *cache, const NMDedupMultiHeadEntry *head_entry, const NMPObject *obj, gboolean contains)
|
||||
{
|
||||
const NMPlatformObject *const *objects;
|
||||
guint i, len;
|
||||
NMDedupMultiIter iter;
|
||||
gboolean found;
|
||||
guint i, len;
|
||||
const NMPObject *o;
|
||||
|
||||
g_assert (cache_id);
|
||||
g_assert (NMP_OBJECT_IS_VALID (obj));
|
||||
|
||||
g_assert (nmp_cache_lookup_obj (cache, obj) == obj);
|
||||
g_assert (!head_entry || (head_entry->len > 0 && c_list_length (&head_entry->lst_entries_head) == head_entry->len));
|
||||
|
||||
objects = nmp_cache_lookup_multi (cache, cache_id, &len);
|
||||
|
||||
g_assert ((len == 0 && !objects) || (len > 0 && objects && !objects[len]));
|
||||
len = head_entry ? head_entry->len : 0;
|
||||
|
||||
found = FALSE;
|
||||
for (i = 0; i < len; i++) {
|
||||
NMPObject *o;
|
||||
|
||||
g_assert (objects[i]);
|
||||
o = NMP_OBJECT_UP_CAST (objects[i]);
|
||||
i = 0;
|
||||
nmp_cache_iter_for_each (&iter,
|
||||
head_entry,
|
||||
&o) {
|
||||
g_assert (NMP_OBJECT_IS_VALID (o));
|
||||
|
||||
if (obj == o) {
|
||||
g_assert (!found);
|
||||
found = TRUE;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
g_assert (len == i);
|
||||
g_assert (!!contains == found);
|
||||
}
|
||||
|
||||
static void
|
||||
_assert_cache_multi_lookup_contains_link (const NMPCache *cache,
|
||||
gboolean visible_only,
|
||||
const NMPObject *obj,
|
||||
gboolean contains)
|
||||
{
|
||||
const NMDedupMultiHeadEntry *head_entry;
|
||||
NMPLookup lookup;
|
||||
|
||||
g_assert (cache);
|
||||
|
||||
nmp_lookup_init_link (&lookup, visible_only);
|
||||
head_entry = nmp_cache_lookup (cache, &lookup);
|
||||
_assert_cache_multi_lookup_contains (cache, head_entry, obj, contains);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
NMPCache *cache;
|
||||
NMPCacheOpsType expected_ops_type;
|
||||
const NMPObject *obj_clone;
|
||||
NMPObject *new_clone;
|
||||
gboolean was_visible;
|
||||
gboolean called;
|
||||
} _NMPCacheUpdateData;
|
||||
|
||||
static void
|
||||
_nmp_cache_update_hook (NMPCache *cache, const NMPObject *old, const NMPObject *new, NMPCacheOpsType ops_type, gpointer user_data)
|
||||
ops_post_check (NMPCache *cache,
|
||||
NMPCacheOpsType ops_type,
|
||||
const NMPObject *obj_old,
|
||||
const NMPObject *obj_new,
|
||||
const NMPObject *obj_new_expected,
|
||||
NMPCacheOpsType expected_ops_type)
|
||||
{
|
||||
_NMPCacheUpdateData *data = user_data;
|
||||
g_assert (cache);
|
||||
|
||||
g_assert (data);
|
||||
g_assert (!data->called);
|
||||
g_assert (data->cache == cache);
|
||||
|
||||
g_assert_cmpint (data->expected_ops_type, ==, ops_type);
|
||||
g_assert_cmpint (expected_ops_type, ==, ops_type);
|
||||
|
||||
switch (ops_type) {
|
||||
case NMP_CACHE_OPS_ADDED:
|
||||
g_assert (!old);
|
||||
g_assert (NMP_OBJECT_IS_VALID (new));
|
||||
g_assert (nmp_object_is_alive (new));
|
||||
g_assert (nmp_object_id_equal (data->obj_clone, new));
|
||||
g_assert (nmp_object_equal (data->obj_clone, new));
|
||||
g_assert (!obj_old);
|
||||
g_assert (NMP_OBJECT_IS_VALID (obj_new));
|
||||
g_assert (nmp_object_is_alive (obj_new));
|
||||
g_assert (nmp_object_id_equal (obj_new_expected, obj_new));
|
||||
g_assert (nmp_object_equal (obj_new_expected, obj_new));
|
||||
break;
|
||||
case NMP_CACHE_OPS_UPDATED:
|
||||
g_assert (NMP_OBJECT_IS_VALID (old));
|
||||
g_assert (NMP_OBJECT_IS_VALID (new));
|
||||
g_assert (nmp_object_is_alive (old));
|
||||
g_assert (nmp_object_is_alive (new));
|
||||
g_assert (nmp_object_id_equal (data->obj_clone, new));
|
||||
g_assert (nmp_object_id_equal (data->obj_clone, old));
|
||||
g_assert (nmp_object_id_equal (old, new));
|
||||
g_assert (nmp_object_equal (data->obj_clone, new));
|
||||
g_assert (!nmp_object_equal (data->obj_clone, old));
|
||||
g_assert (!nmp_object_equal (old, new));
|
||||
g_assert (obj_old != obj_new);
|
||||
g_assert (NMP_OBJECT_IS_VALID (obj_old));
|
||||
g_assert (NMP_OBJECT_IS_VALID (obj_new));
|
||||
g_assert (nmp_object_is_alive (obj_old));
|
||||
g_assert (nmp_object_is_alive (obj_new));
|
||||
g_assert (nmp_object_id_equal (obj_new_expected, obj_new));
|
||||
g_assert (nmp_object_id_equal (obj_new_expected, obj_old));
|
||||
g_assert (nmp_object_id_equal (obj_old, obj_new));
|
||||
g_assert (nmp_object_equal (obj_new_expected, obj_new));
|
||||
g_assert (!nmp_object_equal (obj_new_expected, obj_old));
|
||||
g_assert (!nmp_object_equal (obj_old, obj_new));
|
||||
break;
|
||||
case NMP_CACHE_OPS_REMOVED:
|
||||
g_assert (!new);
|
||||
g_assert (NMP_OBJECT_IS_VALID (old));
|
||||
g_assert (nmp_object_is_alive (old));
|
||||
g_assert (nmp_object_id_equal (data->obj_clone, old));
|
||||
g_assert (!obj_new);
|
||||
g_assert (NMP_OBJECT_IS_VALID (obj_old));
|
||||
g_assert (nmp_object_is_alive (obj_old));
|
||||
if (obj_new_expected)
|
||||
g_assert (nmp_object_id_equal (obj_new_expected, obj_old));
|
||||
break;
|
||||
case NMP_CACHE_OPS_UNCHANGED:
|
||||
g_assert (obj_old == obj_new);
|
||||
if (obj_old) {
|
||||
g_assert (NMP_OBJECT_IS_VALID (obj_old));
|
||||
g_assert (nmp_object_is_alive (obj_old));
|
||||
g_assert (nmp_object_equal (obj_old, obj_new));
|
||||
g_assert (nmp_object_id_equal (obj_new_expected, obj_new));
|
||||
} else
|
||||
g_assert (!obj_new_expected);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
data->was_visible = old ? nmp_object_is_visible (old) : FALSE;
|
||||
data->new_clone = new ? nmp_object_clone (new, FALSE) : NULL;
|
||||
data->called = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_nmp_cache_update_netlink (NMPCache *cache, NMPObject *obj, NMPObject **out_obj, gboolean *out_was_visible, NMPCacheOpsType expected_ops_type)
|
||||
_nmp_cache_update_netlink (NMPCache *cache, NMPObject *obj, const NMPObject **out_obj_old, const NMPObject **out_obj_new, NMPCacheOpsType expected_ops_type)
|
||||
{
|
||||
NMPCacheOpsType ops_type;
|
||||
NMPObject *obj2;
|
||||
gboolean was_visible;
|
||||
nm_auto_nmpobj NMPObject *obj_clone = nmp_object_clone (obj, FALSE);
|
||||
nm_auto_nmpobj NMPObject *new_clone = NULL;
|
||||
const NMPObject *obj_prev;
|
||||
const NMPObject *obj_old;
|
||||
_NMPCacheUpdateData data = {
|
||||
.cache = cache,
|
||||
.expected_ops_type = expected_ops_type,
|
||||
.obj_clone = obj_clone,
|
||||
};
|
||||
|
||||
obj_old = nmp_cache_lookup_link (cache, obj->object.ifindex);
|
||||
if (obj_old && obj_old->_link.udev.device)
|
||||
obj_clone->_link.udev.device = udev_device_ref (obj_old->_link.udev.device);
|
||||
_nmp_object_fixup_link_udev_fields (obj_clone, nmp_cache_use_udev_get (cache));
|
||||
const NMPObject *obj_new;
|
||||
nm_auto_nmpobj NMPObject *obj_new_expected = NULL;
|
||||
|
||||
g_assert (cache);
|
||||
g_assert (NMP_OBJECT_IS_VALID (obj));
|
||||
|
||||
ops_type = nmp_cache_update_netlink (cache, obj, &obj2, &was_visible, _nmp_cache_update_hook, &data);
|
||||
obj_prev = nmp_cache_lookup_link (cache, obj->object.ifindex);
|
||||
obj_new_expected = nmp_object_clone (obj, FALSE);
|
||||
if (obj_prev && obj_prev->_link.udev.device)
|
||||
obj_new_expected->_link.udev.device = udev_device_ref (obj_prev->_link.udev.device);
|
||||
_nmp_object_fixup_link_udev_fields (&obj_new_expected, NULL, nmp_cache_use_udev_get (cache));
|
||||
|
||||
new_clone = data.new_clone;
|
||||
ops_type = nmp_cache_update_netlink (cache, obj, &obj_old, &obj_new);
|
||||
ops_post_check (cache, ops_type, obj_old, obj_new,
|
||||
nmp_object_is_alive (obj_new_expected) ? obj_new_expected : NULL,
|
||||
expected_ops_type);
|
||||
|
||||
g_assert_cmpint (ops_type, ==, expected_ops_type);
|
||||
|
||||
if (ops_type != NMP_CACHE_OPS_UNCHANGED) {
|
||||
g_assert (NMP_OBJECT_IS_VALID (obj2));
|
||||
g_assert (data.called);
|
||||
g_assert_cmpint (data.was_visible, ==, was_visible);
|
||||
|
||||
if (ops_type == NMP_CACHE_OPS_REMOVED)
|
||||
g_assert (!data.new_clone);
|
||||
else {
|
||||
g_assert (data.new_clone);
|
||||
g_assert (nmp_object_equal (obj2, data.new_clone));
|
||||
}
|
||||
} else {
|
||||
g_assert (!data.called);
|
||||
g_assert (!obj2 || was_visible == nmp_object_is_visible (obj2));
|
||||
}
|
||||
|
||||
g_assert (!obj2 || nmp_object_id_equal (obj, obj2));
|
||||
if (ops_type != NMP_CACHE_OPS_REMOVED && obj2)
|
||||
g_assert (nmp_object_equal (obj, obj2));
|
||||
|
||||
if (out_obj)
|
||||
*out_obj = obj2;
|
||||
if (out_obj_new)
|
||||
*out_obj_new = obj_new;
|
||||
else
|
||||
nmp_object_unref (obj2);
|
||||
if (out_was_visible)
|
||||
*out_was_visible = was_visible;
|
||||
nmp_object_unref (obj_new);
|
||||
if (out_obj_old)
|
||||
*out_obj_old = obj_old;
|
||||
else
|
||||
nmp_object_unref (obj_old);
|
||||
}
|
||||
|
||||
static const NMPlatformLink pl_link_2 = {
|
||||
|
|
@ -265,168 +256,189 @@ static void
|
|||
test_cache_link (void)
|
||||
{
|
||||
NMPCache *cache;
|
||||
NMPObject *obj1, *obj2;
|
||||
NMPObject *objm1;
|
||||
const NMPObject *obj_old, *obj_new;
|
||||
NMPObject objs1;
|
||||
gboolean was_visible;
|
||||
NMPCacheId cache_id_storage;
|
||||
struct udev_device *udev_device_2 = g_list_nth_data (global.udev_devices, 0);
|
||||
struct udev_device *udev_device_3 = g_list_nth_data (global.udev_devices, 0);
|
||||
NMPCacheOpsType ops_type;
|
||||
nm_auto_unref_dedup_multi_index NMDedupMultiIndex *multi_idx = NULL;
|
||||
|
||||
cache = nmp_cache_new (nmtst_get_rand_int () % 2);
|
||||
multi_idx = nm_dedup_multi_index_new ();
|
||||
|
||||
cache = nmp_cache_new (multi_idx, nmtst_get_rand_int () % 2);
|
||||
|
||||
/* if we have a link, and don't set is_in_netlink, adding it has no effect. */
|
||||
obj1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
g_assert (NMP_OBJECT_UP_CAST (&obj1->object) == obj1);
|
||||
g_assert (!nmp_object_is_alive (obj1));
|
||||
_nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, NMP_CACHE_OPS_UNCHANGED);
|
||||
objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
g_assert (NMP_OBJECT_UP_CAST (&objm1->object) == objm1);
|
||||
g_assert (!nmp_object_is_alive (objm1));
|
||||
_nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_UNCHANGED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (!obj2);
|
||||
g_assert (!was_visible);
|
||||
g_assert (!nmp_cache_lookup_obj (cache, obj1));
|
||||
g_assert (!obj_old);
|
||||
g_assert (!obj_new);
|
||||
g_assert (!nmp_cache_lookup_obj (cache, objm1));
|
||||
g_assert (!nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)));
|
||||
nmp_object_unref (obj1);
|
||||
nmp_object_unref (objm1);
|
||||
|
||||
/* Only when setting @is_in_netlink the link is added. */
|
||||
obj1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
obj1->_link.netlink.is_in_netlink = TRUE;
|
||||
g_assert (nmp_object_is_alive (obj1));
|
||||
_nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, NMP_CACHE_OPS_ADDED);
|
||||
objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
objm1->_link.netlink.is_in_netlink = TRUE;
|
||||
g_assert (nmp_object_is_alive (objm1));
|
||||
_nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_ADDED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (nmp_object_equal (obj1, obj2));
|
||||
g_assert (!was_visible);
|
||||
g_assert (nmp_cache_lookup_obj (cache, obj1) == obj2);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj2);
|
||||
g_assert (nmp_object_is_visible (obj2));
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, TRUE), obj2, TRUE);
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, FALSE), obj2, TRUE);
|
||||
nmp_object_unref (obj1);
|
||||
nmp_object_unref (obj2);
|
||||
g_assert (!obj_old);
|
||||
g_assert (obj_new);
|
||||
g_assert (objm1 == obj_new);
|
||||
g_assert (nmp_object_equal (objm1, obj_new));
|
||||
g_assert (nmp_cache_lookup_obj (cache, objm1) == obj_new);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj_new);
|
||||
g_assert (nmp_object_is_visible (obj_new));
|
||||
_assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE);
|
||||
_assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, TRUE);
|
||||
nmp_object_unref (objm1);
|
||||
nmp_object_unref (obj_new);
|
||||
|
||||
/* updating the same link with identical value, has no effect. */
|
||||
obj1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
obj1->_link.netlink.is_in_netlink = TRUE;
|
||||
g_assert (nmp_object_is_alive (obj1));
|
||||
_nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, NMP_CACHE_OPS_UNCHANGED);
|
||||
objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
objm1->_link.netlink.is_in_netlink = TRUE;
|
||||
g_assert (nmp_object_is_alive (objm1));
|
||||
_nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_UNCHANGED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (obj2 != obj1);
|
||||
g_assert (nmp_object_equal (obj1, obj2));
|
||||
g_assert (was_visible);
|
||||
g_assert (nmp_cache_lookup_obj (cache, obj1) == obj2);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj2);
|
||||
nmp_object_unref (obj1);
|
||||
nmp_object_unref (obj2);
|
||||
g_assert (obj_old);
|
||||
g_assert (obj_new);
|
||||
g_assert (obj_new != objm1);
|
||||
g_assert (nmp_object_equal (objm1, obj_new));
|
||||
g_assert (nmp_cache_lookup_obj (cache, objm1) == obj_new);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj_new);
|
||||
nmp_object_unref (objm1);
|
||||
nmp_object_unref (obj_new);
|
||||
nmp_object_unref (obj_new);
|
||||
|
||||
/* remove the link from netlink */
|
||||
obj1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
g_assert (!nmp_object_is_alive (obj1));
|
||||
_nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, NMP_CACHE_OPS_REMOVED);
|
||||
objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
g_assert (!nmp_object_is_alive (objm1));
|
||||
_nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_REMOVED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (obj2 != obj1);
|
||||
g_assert (was_visible);
|
||||
g_assert (!nmp_cache_lookup_obj (cache, obj1));
|
||||
g_assert (obj_old);
|
||||
g_assert (!obj_new);
|
||||
g_assert (!nmp_cache_lookup_obj (cache, objm1));
|
||||
g_assert (!nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)));
|
||||
nmp_object_unref (obj1);
|
||||
nmp_object_unref (obj2);
|
||||
nmp_object_unref (objm1);
|
||||
nmp_object_unref (obj_old);
|
||||
nmp_object_unref (obj_new);
|
||||
|
||||
if (udev_device_2) {
|
||||
/* now add the link only with aspect UDEV. */
|
||||
ops_type = nmp_cache_update_link_udev (cache, pl_link_2.ifindex, udev_device_2, &obj2, &was_visible, NULL, NULL);
|
||||
ops_type = nmp_cache_update_link_udev (cache, pl_link_2.ifindex, udev_device_2, &obj_old, &obj_new);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert_cmpint (ops_type, ==, NMP_CACHE_OPS_ADDED);
|
||||
g_assert (!was_visible);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj2);
|
||||
g_assert (!nmp_object_is_visible (obj2));
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, TRUE), obj2, FALSE);
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, FALSE), obj2, TRUE);
|
||||
nmp_object_unref (obj2);
|
||||
g_assert (!obj_old);
|
||||
g_assert (obj_new);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj_new);
|
||||
g_assert (!nmp_object_is_visible (obj_new));
|
||||
_assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, FALSE);
|
||||
_assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE);
|
||||
nmp_object_unref (obj_new);
|
||||
}
|
||||
|
||||
/* add it in netlink too. */
|
||||
obj1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
obj1->_link.netlink.is_in_netlink = TRUE;
|
||||
g_assert (nmp_object_is_alive (obj1));
|
||||
_nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, udev_device_2 ? NMP_CACHE_OPS_UPDATED : NMP_CACHE_OPS_ADDED);
|
||||
objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
objm1->_link.netlink.is_in_netlink = TRUE;
|
||||
g_assert (nmp_object_is_alive (objm1));
|
||||
_nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, udev_device_2 ? NMP_CACHE_OPS_UPDATED : NMP_CACHE_OPS_ADDED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (nmp_object_equal (obj1, obj2));
|
||||
g_assert (!was_visible);
|
||||
g_assert (nmp_cache_lookup_obj (cache, obj1) == obj2);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj2);
|
||||
g_assert (nmp_object_is_visible (obj2));
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, TRUE), obj2, TRUE);
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, FALSE), obj2, TRUE);
|
||||
nmp_object_unref (obj1);
|
||||
nmp_object_unref (obj2);
|
||||
if (udev_device_2) {
|
||||
g_assert (obj_old);
|
||||
g_assert (!nmp_object_is_visible (obj_old));
|
||||
} else
|
||||
g_assert (!obj_old);
|
||||
g_assert (nmp_object_equal (objm1, obj_new));
|
||||
g_assert (nmp_cache_lookup_obj (cache, objm1) == obj_new);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj_new);
|
||||
g_assert (nmp_object_is_visible (obj_new));
|
||||
_assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, TRUE);
|
||||
_assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE);
|
||||
nmp_object_unref (objm1);
|
||||
nmp_object_unref (obj_old);
|
||||
nmp_object_unref (obj_new);
|
||||
|
||||
/* remove again from netlink. */
|
||||
obj1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
obj1->_link.netlink.is_in_netlink = FALSE;
|
||||
g_assert (!nmp_object_is_alive (obj1));
|
||||
_nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, udev_device_2 ? NMP_CACHE_OPS_UPDATED : NMP_CACHE_OPS_REMOVED);
|
||||
objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_2);
|
||||
objm1->_link.netlink.is_in_netlink = FALSE;
|
||||
g_assert (!nmp_object_is_alive (objm1));
|
||||
_nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, udev_device_2 ? NMP_CACHE_OPS_UPDATED : NMP_CACHE_OPS_REMOVED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (obj2 != obj1);
|
||||
g_assert (was_visible);
|
||||
if (udev_device_2)
|
||||
g_assert (obj_new == objm1);
|
||||
else
|
||||
g_assert (!obj_new);
|
||||
g_assert (obj_old);
|
||||
g_assert (nmp_object_is_alive (obj_old));
|
||||
if (udev_device_2) {
|
||||
g_assert (nmp_cache_lookup_obj (cache, obj1) == obj2);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj2);
|
||||
g_assert (!nmp_object_is_visible (obj2));
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, TRUE), obj2, FALSE);
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, FALSE), obj2, TRUE);
|
||||
g_assert (nmp_cache_lookup_obj (cache, objm1) == obj_new);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == obj_new);
|
||||
g_assert (!nmp_object_is_visible (obj_new));
|
||||
_assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, FALSE);
|
||||
_assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE);
|
||||
} else {
|
||||
g_assert (nmp_cache_lookup_obj (cache, obj1) == NULL);
|
||||
g_assert (nmp_cache_lookup_obj (cache, objm1) == NULL);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_2.ifindex)) == NULL);
|
||||
g_assert (nmp_object_is_visible (obj2));
|
||||
g_assert (nmp_object_is_visible (obj_new));
|
||||
}
|
||||
nmp_object_unref (obj1);
|
||||
nmp_object_unref (obj2);
|
||||
nmp_object_unref (objm1);
|
||||
nmp_object_unref (obj_old);
|
||||
nmp_object_unref (obj_new);
|
||||
|
||||
/* now another link only with aspect UDEV. */
|
||||
if (udev_device_3) {
|
||||
/* now add the link only with aspect UDEV. */
|
||||
ops_type = nmp_cache_update_link_udev (cache, pl_link_3.ifindex, udev_device_3, &obj2, &was_visible, NULL, NULL);
|
||||
ops_type = nmp_cache_update_link_udev (cache, pl_link_3.ifindex, udev_device_3, &obj_old, &obj_new);
|
||||
g_assert_cmpint (ops_type, ==, NMP_CACHE_OPS_ADDED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (NMP_OBJECT_IS_VALID (obj2));
|
||||
g_assert (!was_visible);
|
||||
g_assert (!nmp_object_is_visible (obj2));
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj2);
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, TRUE), obj2, FALSE);
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, FALSE), obj2, TRUE);
|
||||
g_assert_cmpint (obj2->_link.netlink.is_in_netlink, ==, FALSE);
|
||||
g_assert_cmpint (obj2->link.initialized, ==, FALSE);
|
||||
nmp_object_unref (obj2);
|
||||
g_assert (NMP_OBJECT_IS_VALID (obj_new));
|
||||
g_assert (!obj_old);
|
||||
g_assert (!nmp_object_is_visible (obj_new));
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj_new);
|
||||
_assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, FALSE);
|
||||
_assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE);
|
||||
g_assert_cmpint (obj_new->_link.netlink.is_in_netlink, ==, FALSE);
|
||||
g_assert_cmpint (obj_new->link.initialized, ==, FALSE);
|
||||
nmp_object_unref (obj_new);
|
||||
|
||||
/* add it in netlink too. */
|
||||
obj1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_3);
|
||||
obj1->_link.netlink.is_in_netlink = TRUE;
|
||||
g_assert (nmp_object_is_alive (obj1));
|
||||
_nmp_cache_update_netlink (cache, obj1, &obj2, &was_visible, NMP_CACHE_OPS_UPDATED);
|
||||
objm1 = nmp_object_new (NMP_OBJECT_TYPE_LINK, (NMPlatformObject *) &pl_link_3);
|
||||
objm1->_link.netlink.is_in_netlink = TRUE;
|
||||
g_assert (nmp_object_is_alive (objm1));
|
||||
_nmp_cache_update_netlink (cache, objm1, &obj_old, &obj_new, NMP_CACHE_OPS_UPDATED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (obj2 != obj1);
|
||||
g_assert (nmp_object_equal (obj1, obj2));
|
||||
g_assert (!was_visible);
|
||||
g_assert (nmp_cache_lookup_obj (cache, obj1) == obj2);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj2);
|
||||
g_assert (nmp_object_is_visible (obj2));
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, TRUE), obj2, TRUE);
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, FALSE), obj2, TRUE);
|
||||
g_assert_cmpint (obj2->_link.netlink.is_in_netlink, ==, TRUE);
|
||||
g_assert_cmpint (obj2->link.initialized, ==, TRUE);
|
||||
nmp_object_unref (obj1);
|
||||
nmp_object_unref (obj2);
|
||||
g_assert (obj_old);
|
||||
g_assert (obj_new == objm1);
|
||||
g_assert (nmp_object_equal (objm1, obj_new));
|
||||
g_assert (!obj_old || !nmp_object_is_visible (obj_old));
|
||||
g_assert (nmp_cache_lookup_obj (cache, objm1) == obj_new);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj_new);
|
||||
g_assert (nmp_object_is_visible (obj_new));
|
||||
_assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, TRUE);
|
||||
_assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE);
|
||||
g_assert_cmpint (obj_new->_link.netlink.is_in_netlink, ==, TRUE);
|
||||
g_assert_cmpint (obj_new->link.initialized, ==, TRUE);
|
||||
nmp_object_unref (objm1);
|
||||
nmp_object_unref (obj_old);
|
||||
nmp_object_unref (obj_new);
|
||||
|
||||
/* remove UDEV. */
|
||||
ops_type = nmp_cache_update_link_udev (cache, pl_link_3.ifindex, NULL, &obj2, &was_visible, NULL, NULL);
|
||||
ops_type = nmp_cache_update_link_udev (cache, pl_link_3.ifindex, NULL, &obj_old, &obj_new);
|
||||
g_assert_cmpint (ops_type, ==, NMP_CACHE_OPS_UPDATED);
|
||||
ASSERT_nmp_cache_is_consistent (cache);
|
||||
g_assert (was_visible);
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj2);
|
||||
g_assert (nmp_object_is_visible (obj2));
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, TRUE), obj2, TRUE);
|
||||
_assert_cache_multi_lookup_contains (cache, nmp_cache_id_init_object_type (&cache_id_storage, NMP_OBJECT_TYPE_LINK, FALSE), obj2, TRUE);
|
||||
g_assert_cmpint (obj2->_link.netlink.is_in_netlink, ==, TRUE);
|
||||
g_assert_cmpint (obj2->link.initialized, ==, !nmp_cache_use_udev_get (cache));
|
||||
nmp_object_unref (obj2);
|
||||
g_assert (obj_old && nmp_object_is_visible (obj_old));
|
||||
g_assert (nmp_cache_lookup_obj (cache, nmp_object_stackinit_id_link (&objs1, pl_link_3.ifindex)) == obj_new);
|
||||
g_assert (nmp_object_is_visible (obj_new));
|
||||
_assert_cache_multi_lookup_contains_link (cache, TRUE, obj_new, TRUE);
|
||||
_assert_cache_multi_lookup_contains_link (cache, FALSE, obj_new, TRUE);
|
||||
g_assert_cmpint (obj_new->_link.netlink.is_in_netlink, ==, TRUE);
|
||||
g_assert_cmpint (obj_new->link.initialized, ==, !nmp_cache_use_udev_get (cache));
|
||||
nmp_object_unref (obj_new);
|
||||
nmp_object_unref (obj_old);
|
||||
}
|
||||
|
||||
nmp_cache_free (cache);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue