core: support nexthops in l3cd

Track a list of nexthops in NML3ConfigData.
This commit is contained in:
Beniamino Galvani 2025-12-10 14:18:00 +01:00
parent f696705727
commit 97de69515d
2 changed files with 142 additions and 1 deletions

View file

@ -42,6 +42,14 @@ struct _NML3ConfigData {
DedupMultiIdxType idx_routes_x[2];
};
union {
struct {
DedupMultiIdxType idx_nexthops_6;
DedupMultiIdxType idx_nexthops_4;
};
DedupMultiIdxType idx_nexthops_x[2];
};
union {
struct {
const NMPObject *best_default_route_6;
@ -455,6 +463,17 @@ nm_l3_config_data_log(const NML3ConfigData *self,
i++;
}
nm_l3_config_data_iter_obj_for_each (&iter,
self,
&obj,
NMP_OBJECT_TYPE_IP_NEXTHOP(IS_IPv4)) {
_L("nexthop%c[%u]: %s",
nm_utils_addr_family_to_char(addr_family),
i,
nmp_object_to_string(obj, NMP_OBJECT_TO_STRING_PUBLIC, sbuf, sizeof(sbuf)));
i++;
}
if (self->route_table_sync_x[IS_IPv4] != NM_IP_ROUTE_TABLE_SYNC_MODE_NONE) {
_L("route-table-sync-mode%c: %d",
nm_utils_addr_family_to_char(addr_family),
@ -777,6 +796,8 @@ nm_l3_config_data_new(NMDedupMultiIndex *multi_idx, int ifindex, NMIPConfigSourc
_idx_type_init(&self->idx_addresses_6, NMP_OBJECT_TYPE_IP6_ADDRESS);
_idx_type_init(&self->idx_routes_4, NMP_OBJECT_TYPE_IP4_ROUTE);
_idx_type_init(&self->idx_routes_6, NMP_OBJECT_TYPE_IP6_ROUTE);
_idx_type_init(&self->idx_nexthops_4, NMP_OBJECT_TYPE_IP4_NEXTHOP);
_idx_type_init(&self->idx_nexthops_6, NMP_OBJECT_TYPE_IP6_NEXTHOP);
return self;
}
@ -844,6 +865,8 @@ nm_l3_config_data_unref(const NML3ConfigData *self)
nm_dedup_multi_index_remove_idx(mutable->multi_idx, &mutable->idx_addresses_6.parent);
nm_dedup_multi_index_remove_idx(mutable->multi_idx, &mutable->idx_routes_4.parent);
nm_dedup_multi_index_remove_idx(mutable->multi_idx, &mutable->idx_routes_6.parent);
nm_dedup_multi_index_remove_idx(mutable->multi_idx, &mutable->idx_nexthops_4.parent);
nm_dedup_multi_index_remove_idx(mutable->multi_idx, &mutable->idx_nexthops_6.parent);
nmp_object_unref(mutable->best_default_route_4);
nmp_object_unref(mutable->best_default_route_6);
@ -938,6 +961,40 @@ nm_l3_config_data_lookup_route(const NML3ConfigData *self,
nmp_object_stackinit(&obj_stack, NMP_OBJECT_TYPE_IP_ROUTE(IS_IPv4), needle));
}
const NMPlatformIP4NextHop *
nm_l3_config_data_lookup_nexthop4(const NML3ConfigData *self, guint32 id)
{
const NMDedupMultiEntry *head;
NMPObject obj_stack;
nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE));
nmp_object_stackinit_id_ip4_nexthop(&obj_stack, id);
head = nm_l3_config_data_lookup_obj(self, &obj_stack);
if (!head)
return NULL;
return NMP_OBJECT_CAST_IP4_NEXTHOP(head->obj);
}
const NMPlatformIP6NextHop *
nm_l3_config_data_lookup_nexthop6(const NML3ConfigData *self, guint32 id)
{
const NMDedupMultiEntry *head;
NMPObject obj_stack;
nm_assert(_NM_IS_L3_CONFIG_DATA(self, TRUE));
nmp_object_stackinit_id_ip6_nexthop(&obj_stack, id);
head = nm_l3_config_data_lookup_obj(self, &obj_stack);
if (!head)
return NULL;
return NMP_OBJECT_CAST_IP6_NEXTHOP(head->obj);
}
const NMDedupMultiIdxType *
nm_l3_config_data_lookup_index(const NML3ConfigData *self, NMPObjectType obj_type)
{
@ -952,6 +1009,10 @@ nm_l3_config_data_lookup_index(const NML3ConfigData *self, NMPObjectType obj_typ
return &self->idx_routes_4.parent;
case NMP_OBJECT_TYPE_IP6_ROUTE:
return &self->idx_routes_6.parent;
case NMP_OBJECT_TYPE_IP4_NEXTHOP:
return &self->idx_nexthops_4.parent;
case NMP_OBJECT_TYPE_IP6_NEXTHOP:
return &self->idx_nexthops_6.parent;
default:
return nm_assert_unreachable_val(NULL);
}
@ -1168,7 +1229,9 @@ _l3_config_data_add_obj(NMDedupMultiIndex *multi_idx,
NMP_OBJECT_TYPE_IP4_ADDRESS,
NMP_OBJECT_TYPE_IP4_ROUTE,
NMP_OBJECT_TYPE_IP6_ADDRESS,
NMP_OBJECT_TYPE_IP6_ROUTE));
NMP_OBJECT_TYPE_IP6_ROUTE,
NMP_OBJECT_TYPE_IP4_NEXTHOP,
NMP_OBJECT_TYPE_IP6_NEXTHOP));
nm_assert((!!obj_new) != (!!pl_new));
if (NM_IN_SET(idx_type->obj_type, NMP_OBJECT_TYPE_IP4_ROUTE, NMP_OBJECT_TYPE_IP6_ROUTE)) {
@ -1257,6 +1320,9 @@ _l3_config_data_add_obj(NMDedupMultiIndex *multi_idx,
modified = TRUE;
}
break;
case NMP_OBJECT_TYPE_IP4_NEXTHOP:
case NMP_OBJECT_TYPE_IP6_NEXTHOP:
break;
default:
nm_assert_not_reached();
@ -1448,6 +1514,29 @@ nm_l3_config_data_add_route_full(NML3ConfigData *self,
return changed;
}
gboolean
nm_l3_config_data_add_nexthop(NML3ConfigData *self,
int addr_family,
const NMPObject *obj_new,
const NMPlatformIPNextHop *pl_new)
{
const int IS_IPv4 = NM_IS_IPv4(addr_family);
nm_assert(_NM_IS_L3_CONFIG_DATA(self, FALSE));
nm_assert_addr_family(addr_family);
nm_assert((!pl_new) != (!obj_new));
nm_assert(!obj_new || (NMP_OBJECT_GET_ADDR_FAMILY(obj_new) == addr_family));
return _l3_config_data_add_obj(self->multi_idx,
&self->idx_nexthops_x[IS_IPv4],
self->ifindex,
obj_new,
(const NMPlatformObject *) pl_new,
NM_L3_CONFIG_ADD_FLAGS_MERGE,
NULL,
NULL);
}
const NMPObject *
nm_l3_config_data_get_best_default_route(const NML3ConfigData *self, int addr_family)
{
@ -3673,6 +3762,41 @@ nm_l3_config_data_merge(NML3ConfigData *self,
#undef _ensure_r
}
nm_l3_config_data_iter_obj_for_each (&iter,
src,
&obj,
NMP_OBJECT_TYPE_IP_NEXTHOP(IS_IPv4)) {
const NMPlatformIPNextHop *nh_src = NMP_OBJECT_CAST_IP_NEXTHOP(obj);
NMPlatformIPXNextHop nh;
#define _ensure_a() \
G_STMT_START \
{ \
if (nh_src != &nh.nhx) { \
if (IS_IPv4) \
nh.nh4 = *NMP_OBJECT_CAST_IP4_NEXTHOP(obj); \
else \
nh.nh6 = *NMP_OBJECT_CAST_IP6_NEXTHOP(obj); \
nh_src = &nh.nhx; \
} \
} \
G_STMT_END
if (nh_src->ifindex != self->ifindex) {
_ensure_a();
nh.nhx.ifindex = self->ifindex;
}
_l3_config_data_add_obj(self->multi_idx,
&self->idx_nexthops_x[IS_IPv4],
self->ifindex,
nh_src == &nh.nhx ? NULL : obj,
(const NMPlatformObject *) (nh_src == &nh.nhx ? nh_src : NULL),
NM_L3_CONFIG_ADD_FLAGS_EXCLUSIVE,
NULL,
NULL);
#undef _ensure_r
}
if (!NM_FLAGS_HAS(merge_flags, NM_L3_CONFIG_MERGE_FLAGS_NO_DNS))
_strv_ptrarray_merge(&self->nameservers_x[IS_IPv4], src->nameservers_x[IS_IPv4]);

View file

@ -251,6 +251,12 @@ const NMDedupMultiEntry *nm_l3_config_data_lookup_route(const NML3ConfigData
int addr_family,
const NMPlatformIPRoute *needle);
const NMPlatformIP4NextHop *nm_l3_config_data_lookup_nexthop4(const NML3ConfigData *self,
guint32 id);
const NMPlatformIP6NextHop *nm_l3_config_data_lookup_nexthop6(const NML3ConfigData *self,
guint32 id);
const NMDedupMultiHeadEntry *nm_l3_config_data_lookup_objs(const NML3ConfigData *self,
NMPObjectType obj_type);
@ -266,6 +272,12 @@ nm_l3_config_data_lookup_routes(const NML3ConfigData *self, int addr_family)
return nm_l3_config_data_lookup_objs(self, NMP_OBJECT_TYPE_IP_ROUTE(NM_IS_IPv4(addr_family)));
}
static inline const NMDedupMultiHeadEntry *
nm_l3_config_data_lookup_nexthops(const NML3ConfigData *self, int addr_family)
{
return nm_l3_config_data_lookup_objs(self, NMP_OBJECT_TYPE_IP_NEXTHOP(NM_IS_IPv4(addr_family)));
}
#define nm_l3_config_data_iter_obj_for_each(iter, self, obj, type) \
for (nm_dedup_multi_iter_init((iter), nm_l3_config_data_lookup_objs((self), (type))); \
nm_platform_dedup_multi_iter_next_obj((iter), (obj), (type));)
@ -435,6 +447,11 @@ nm_l3_config_data_add_route(NML3ConfigData *self,
NULL);
}
gboolean nm_l3_config_data_add_nexthop(NML3ConfigData *self,
int addr_family,
const NMPObject *obj_new,
const NMPlatformIPNextHop *pl_new);
static inline gboolean
nm_l3_config_data_add_route_4(NML3ConfigData *self, const NMPlatformIP4Route *rt)
{