mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-02 20:08:04 +02:00
platform: extend cmd_obj_{hash_update,cmp}() hooks to check for identity
We will extend IPv4 routes with the list of next hops. This field will
be heap allocated and be part of the NMPObjectIP4Route object, while
also being part of the identity. To support the ID operator that checks
fields of the NMPObject, add a "for_id" argument to the hash/cmp hooks.
Also, a function that sets cmd_obj_{hash_update,cmp}() MUST not set
cmd_plobj_id_{hashupdate,cmp}(), as it would have overlapping
functionality. Therefore, the objects that define
cmd_obj_{hash_update,cmp}() need to fully implement the ID comparison.
This commit is contained in:
parent
ff63b2eb6e
commit
c9123c2ece
3 changed files with 80 additions and 50 deletions
|
|
@ -1153,32 +1153,39 @@ nmp_object_hash_update_full(const NMPObject *obj, gboolean for_id, NMHashState *
|
|||
nm_assert((!!klass->cmd_plobj_cmp) == (!!klass->cmd_plobj_hash_update));
|
||||
|
||||
nm_assert((!!klass->cmd_obj_hash_update) ^ (!!klass->cmd_plobj_hash_update));
|
||||
nm_assert((!klass->cmd_obj_hash_update) || (!klass->cmd_plobj_id_hash_update));
|
||||
|
||||
nm_hash_update_val(h, klass->obj_type);
|
||||
|
||||
if (for_id) {
|
||||
if (!klass->cmd_plobj_id_hash_update) {
|
||||
if (klass->cmd_obj_hash_update)
|
||||
klass->cmd_obj_hash_update(obj, TRUE, h);
|
||||
else if (klass->cmd_plobj_id_hash_update)
|
||||
klass->cmd_plobj_id_hash_update(&obj->object, h);
|
||||
else {
|
||||
/* The klass doesn't implement ID compare. It means, to use pointer
|
||||
* equality. */
|
||||
nm_hash_update_val(h, obj);
|
||||
return;
|
||||
}
|
||||
|
||||
nm_hash_update_val(h, klass->obj_type);
|
||||
klass->cmd_plobj_id_hash_update(&obj->object, h);
|
||||
return;
|
||||
}
|
||||
|
||||
nm_hash_update_val(h, klass->obj_type);
|
||||
if (klass->cmd_obj_hash_update)
|
||||
klass->cmd_obj_hash_update(obj, h);
|
||||
klass->cmd_obj_hash_update(obj, FALSE, h);
|
||||
else
|
||||
klass->cmd_plobj_hash_update(&obj->object, h);
|
||||
}
|
||||
|
||||
static void
|
||||
_vt_cmd_obj_hash_update_link(const NMPObject *obj, NMHashState *h)
|
||||
_vt_cmd_obj_hash_update_link(const NMPObject *obj, gboolean for_id, NMHashState *h)
|
||||
{
|
||||
nm_assert(NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_LINK);
|
||||
|
||||
if (for_id) {
|
||||
nm_hash_update_val(h, obj->link.ifindex);
|
||||
return;
|
||||
}
|
||||
|
||||
nm_platform_link_hash_update(&obj->link, h);
|
||||
nm_hash_update_vals(h, obj->_link.netlink.is_in_netlink, obj->_link.udev.device);
|
||||
if (obj->_link.netlink.lnk)
|
||||
|
|
@ -1186,10 +1193,15 @@ _vt_cmd_obj_hash_update_link(const NMPObject *obj, NMHashState *h)
|
|||
}
|
||||
|
||||
static void
|
||||
_vt_cmd_obj_hash_update_lnk_vlan(const NMPObject *obj, NMHashState *h)
|
||||
_vt_cmd_obj_hash_update_lnk_vlan(const NMPObject *obj, gboolean for_id, NMHashState *h)
|
||||
{
|
||||
nm_assert(NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_LNK_VLAN);
|
||||
|
||||
if (for_id) {
|
||||
nm_hash_update_val(h, obj);
|
||||
return;
|
||||
}
|
||||
|
||||
nm_platform_lnk_vlan_hash_update(&obj->lnk_vlan, h);
|
||||
_vlan_xgress_qos_mappings_hash_update(obj->_lnk_vlan.n_ingress_qos_map,
|
||||
obj->_lnk_vlan.ingress_qos_map,
|
||||
|
|
@ -1200,12 +1212,17 @@ _vt_cmd_obj_hash_update_lnk_vlan(const NMPObject *obj, NMHashState *h)
|
|||
}
|
||||
|
||||
static void
|
||||
_vt_cmd_obj_hash_update_lnk_wireguard(const NMPObject *obj, NMHashState *h)
|
||||
_vt_cmd_obj_hash_update_lnk_wireguard(const NMPObject *obj, gboolean for_id, NMHashState *h)
|
||||
{
|
||||
guint i;
|
||||
|
||||
nm_assert(NMP_OBJECT_GET_TYPE(obj) == NMP_OBJECT_TYPE_LNK_WIREGUARD);
|
||||
|
||||
if (for_id) {
|
||||
nm_hash_update_val(h, obj);
|
||||
return;
|
||||
}
|
||||
|
||||
nm_platform_lnk_wireguard_hash_update(&obj->lnk_wireguard, h);
|
||||
|
||||
nm_hash_update_val(h, obj->_lnk_wireguard.peers_len);
|
||||
|
|
@ -1220,14 +1237,13 @@ nmp_object_cmp_full(const NMPObject *obj1, const NMPObject *obj2, NMPObjectCmpFl
|
|||
const NMPClass *klass2;
|
||||
NMPObject obj_stackcopy;
|
||||
|
||||
nm_assert(!NM_FLAGS_ANY(flags,
|
||||
~(NMP_OBJECT_CMP_FLAGS_ID | NMP_OBJECT_CMP_FLAGS_IGNORE_IFINDEX)));
|
||||
nm_assert(
|
||||
!NM_FLAGS_ANY(flags, ~(NMP_OBJECT_CMP_FLAGS_ID | NMP_OBJECT_CMP_FLAGS_IGNORE_IFINDEX)));
|
||||
|
||||
/* The ID flag (currently) cannot be combined with other flags. That's partly because
|
||||
* it's not implemented, but also because some objects use only pointer equality. So it's
|
||||
* not clear how that combines with other flags (well, they'd be ignored). */
|
||||
nm_assert(!NM_FLAGS_HAS(flags, NMP_OBJECT_CMP_FLAGS_ID)
|
||||
|| flags == NMP_OBJECT_CMP_FLAGS_ID);
|
||||
nm_assert(!NM_FLAGS_HAS(flags, NMP_OBJECT_CMP_FLAGS_ID) || flags == NMP_OBJECT_CMP_FLAGS_ID);
|
||||
|
||||
NM_CMP_SELF(obj1, obj2);
|
||||
|
||||
|
|
@ -1243,6 +1259,7 @@ nmp_object_cmp_full(const NMPObject *obj1, const NMPObject *obj2, NMPObjectCmpFl
|
|||
nm_assert((!!klass->cmd_plobj_cmp) == (!!klass->cmd_plobj_hash_update));
|
||||
|
||||
nm_assert((!!klass->cmd_obj_cmp) ^ (!!klass->cmd_plobj_cmp));
|
||||
nm_assert((!klass->cmd_obj_cmp) || (!klass->cmd_plobj_id_cmp));
|
||||
|
||||
klass2 = NMP_OBJECT_GET_CLASS(obj2);
|
||||
|
||||
|
|
@ -1253,14 +1270,15 @@ nmp_object_cmp_full(const NMPObject *obj1, const NMPObject *obj2, NMPObjectCmpFl
|
|||
}
|
||||
|
||||
if (NM_FLAGS_HAS(flags, NMP_OBJECT_CMP_FLAGS_ID)) {
|
||||
if (!klass->cmd_plobj_id_cmp) {
|
||||
/* the klass doesn't implement ID cmp(). That means, different objects
|
||||
* never compare equal, but the cmp() according to their pointer value. */
|
||||
NM_CMP_DIRECT_PTR(obj1, obj2);
|
||||
return nm_assert_unreachable_val(0);
|
||||
}
|
||||
if (klass->cmd_obj_cmp)
|
||||
return klass->cmd_obj_cmp(obj1, obj2, TRUE);
|
||||
if (klass->cmd_plobj_id_cmp)
|
||||
return klass->cmd_plobj_id_cmp(&obj1->object, &obj2->object);
|
||||
|
||||
return klass->cmd_plobj_id_cmp(&obj1->object, &obj2->object);
|
||||
/* the klass doesn't implement ID cmp(). That means, different objects
|
||||
* never compare equal, but the cmp() according to their pointer value. */
|
||||
NM_CMP_DIRECT_PTR(obj1, obj2);
|
||||
return nm_assert_unreachable_val(0);
|
||||
}
|
||||
|
||||
if (NM_FLAGS_HAS(flags, NMP_OBJECT_CMP_FLAGS_IGNORE_IFINDEX)) {
|
||||
|
|
@ -1280,13 +1298,18 @@ nmp_object_cmp_full(const NMPObject *obj1, const NMPObject *obj2, NMPObjectCmpFl
|
|||
}
|
||||
|
||||
if (klass->cmd_obj_cmp)
|
||||
return klass->cmd_obj_cmp(obj1, obj2);
|
||||
return klass->cmd_obj_cmp(obj1, obj2, FALSE);
|
||||
return klass->cmd_plobj_cmp(&obj1->object, &obj2->object);
|
||||
}
|
||||
|
||||
static int
|
||||
_vt_cmd_obj_cmp_link(const NMPObject *obj1, const NMPObject *obj2)
|
||||
_vt_cmd_obj_cmp_link(const NMPObject *obj1, const NMPObject *obj2, gboolean for_id)
|
||||
{
|
||||
if (for_id) {
|
||||
NM_CMP_FIELD(obj1, obj2, link.ifindex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
NM_CMP_RETURN(nm_platform_link_cmp(&obj1->link, &obj2->link));
|
||||
NM_CMP_DIRECT(obj1->_link.netlink.is_in_netlink, obj2->_link.netlink.is_in_netlink);
|
||||
NM_CMP_RETURN(nmp_object_cmp(obj1->_link.netlink.lnk, obj2->_link.netlink.lnk));
|
||||
|
|
@ -1308,10 +1331,15 @@ _vt_cmd_obj_cmp_link(const NMPObject *obj1, const NMPObject *obj2)
|
|||
}
|
||||
|
||||
static int
|
||||
_vt_cmd_obj_cmp_lnk_vlan(const NMPObject *obj1, const NMPObject *obj2)
|
||||
_vt_cmd_obj_cmp_lnk_vlan(const NMPObject *obj1, const NMPObject *obj2, gboolean for_id)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (for_id) {
|
||||
NM_CMP_DIRECT_PTR(obj1, obj2);
|
||||
return nm_assert_unreachable_val(0);
|
||||
}
|
||||
|
||||
c = nm_platform_lnk_vlan_cmp(&obj1->lnk_vlan, &obj2->lnk_vlan);
|
||||
if (c)
|
||||
return c;
|
||||
|
|
@ -1334,10 +1362,15 @@ _vt_cmd_obj_cmp_lnk_vlan(const NMPObject *obj1, const NMPObject *obj2)
|
|||
}
|
||||
|
||||
static int
|
||||
_vt_cmd_obj_cmp_lnk_wireguard(const NMPObject *obj1, const NMPObject *obj2)
|
||||
_vt_cmd_obj_cmp_lnk_wireguard(const NMPObject *obj1, const NMPObject *obj2, gboolean for_id)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (for_id) {
|
||||
NM_CMP_DIRECT_PTR(obj1, obj2);
|
||||
return nm_assert_unreachable_val(0);
|
||||
}
|
||||
|
||||
NM_CMP_RETURN(nm_platform_lnk_wireguard_cmp(&obj1->lnk_wireguard, &obj2->lnk_wireguard));
|
||||
|
||||
NM_CMP_FIELD(obj1, obj2, _lnk_wireguard.peers_len);
|
||||
|
|
@ -1513,8 +1546,6 @@ nmp_object_clone(const NMPObject *obj, gboolean id_only)
|
|||
} \
|
||||
_NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON
|
||||
|
||||
_vt_cmd_plobj_id_cmp(link, NMPlatformLink, { NM_CMP_FIELD(obj1, obj2, ifindex); });
|
||||
|
||||
static int
|
||||
_vt_cmd_plobj_id_cmp_ip4_address(const NMPlatformObject *obj1, const NMPlatformObject *obj2)
|
||||
{
|
||||
|
|
@ -1619,8 +1650,6 @@ nmp_object_id_hash(const NMPObject *obj)
|
|||
} \
|
||||
_NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON
|
||||
|
||||
_vt_cmd_plobj_id_hash_update(link, NMPlatformLink, { nm_hash_update_val(h, obj->ifindex); });
|
||||
|
||||
_vt_cmd_plobj_id_hash_update(ip4_address, NMPlatformIP4Address, {
|
||||
nm_hash_update_vals(
|
||||
h,
|
||||
|
|
@ -3122,25 +3151,23 @@ typedef int (*CmdPlobjCmpFunc)(const NMPlatformObject *obj1, const NMPlatformObj
|
|||
const NMPClass _nmp_classes[NMP_OBJECT_TYPE_MAX] = {
|
||||
[NMP_OBJECT_TYPE_LINK - 1] =
|
||||
{
|
||||
.parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
|
||||
.obj_type = NMP_OBJECT_TYPE_LINK,
|
||||
.sizeof_data = sizeof(NMPObjectLink),
|
||||
.sizeof_public = sizeof(NMPlatformLink),
|
||||
.obj_type_name = "link",
|
||||
.rtm_gettype = RTM_GETLINK,
|
||||
.signal_type_id = NM_PLATFORM_SIGNAL_ID_LINK,
|
||||
.signal_type = NM_PLATFORM_SIGNAL_LINK_CHANGED,
|
||||
.supported_cache_ids = _supported_cache_ids_link,
|
||||
.cmd_obj_hash_update = _vt_cmd_obj_hash_update_link,
|
||||
.cmd_obj_cmp = _vt_cmd_obj_cmp_link,
|
||||
.cmd_obj_copy = _vt_cmd_obj_copy_link,
|
||||
.cmd_obj_dispose = _vt_cmd_obj_dispose_link,
|
||||
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_link,
|
||||
.cmd_obj_is_visible = _vt_cmd_obj_is_visible_link,
|
||||
.cmd_obj_to_string = _vt_cmd_obj_to_string_link,
|
||||
.cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_link,
|
||||
.cmd_plobj_id_cmp = _vt_cmd_plobj_id_cmp_link,
|
||||
.cmd_plobj_id_hash_update = _vt_cmd_plobj_id_hash_update_link,
|
||||
.parent = DEDUP_MULTI_OBJ_CLASS_INIT(),
|
||||
.obj_type = NMP_OBJECT_TYPE_LINK,
|
||||
.sizeof_data = sizeof(NMPObjectLink),
|
||||
.sizeof_public = sizeof(NMPlatformLink),
|
||||
.obj_type_name = "link",
|
||||
.rtm_gettype = RTM_GETLINK,
|
||||
.signal_type_id = NM_PLATFORM_SIGNAL_ID_LINK,
|
||||
.signal_type = NM_PLATFORM_SIGNAL_LINK_CHANGED,
|
||||
.supported_cache_ids = _supported_cache_ids_link,
|
||||
.cmd_obj_hash_update = _vt_cmd_obj_hash_update_link,
|
||||
.cmd_obj_cmp = _vt_cmd_obj_cmp_link,
|
||||
.cmd_obj_copy = _vt_cmd_obj_copy_link,
|
||||
.cmd_obj_dispose = _vt_cmd_obj_dispose_link,
|
||||
.cmd_obj_is_alive = _vt_cmd_obj_is_alive_link,
|
||||
.cmd_obj_is_visible = _vt_cmd_obj_is_visible_link,
|
||||
.cmd_obj_to_string = _vt_cmd_obj_to_string_link,
|
||||
.cmd_plobj_id_copy = _vt_cmd_plobj_id_copy_link,
|
||||
},
|
||||
[NMP_OBJECT_TYPE_IP4_ADDRESS - 1] =
|
||||
{
|
||||
|
|
|
|||
|
|
@ -188,8 +188,8 @@ typedef struct {
|
|||
void (*cmd_obj_copy)(NMPObject *dst, const NMPObject *src);
|
||||
void (*cmd_obj_dispose)(NMPObject *obj);
|
||||
|
||||
void (*cmd_obj_hash_update)(const NMPObject *obj, NMHashState *h);
|
||||
int (*cmd_obj_cmp)(const NMPObject *obj1, const NMPObject *obj2);
|
||||
void (*cmd_obj_hash_update)(const NMPObject *obj, gboolean for_id, NMHashState *h);
|
||||
int (*cmd_obj_cmp)(const NMPObject *obj1, const NMPObject *obj2, gboolean for_id);
|
||||
const char *(*cmd_obj_to_string)(const NMPObject *obj,
|
||||
NMPObjectToStringMode to_string_mode,
|
||||
char *buf,
|
||||
|
|
|
|||
|
|
@ -158,6 +158,9 @@ test_nmpclass_consistency(void)
|
|||
g_assert((!!klass->cmd_obj_cmp) != (!!klass->cmd_plobj_cmp));
|
||||
g_assert((!!klass->cmd_obj_hash_update) != (!!klass->cmd_plobj_hash_update));
|
||||
|
||||
g_assert((!klass->cmd_obj_cmp) || (!klass->cmd_plobj_id_cmp));
|
||||
g_assert((!klass->cmd_obj_hash_update) || (!klass->cmd_plobj_id_hash_update));
|
||||
|
||||
g_assert_cmpint(klass->sizeof_public, >, 0);
|
||||
g_assert_cmpint(klass->sizeof_data, >=, klass->sizeof_public);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue