From 5dc42ce177188e969864ca5a365ecf0297d3a8be Mon Sep 17 00:00:00 2001 From: Maxime Leroy Date: Mon, 22 Dec 2025 15:38:55 +0100 Subject: [PATCH 1/3] frr: add vrf fixes not merged FRR presumes that vrf_id == ifindex, some fixes has been upstream it. These ones are not merged yet. Signed-off-by: Maxime Leroy --- subprojects/frr.wrap | 4 +- ...ly-on-dplane-table_id-for-VRF-delete.patch | 211 ++++++++++++++++++ ...-provided-vrf_id-instead-of-casting-.patch | 164 ++++++++++++++ 3 files changed, 378 insertions(+), 1 deletion(-) create mode 100644 subprojects/packagefiles/frr/0001-zebra-do-not-rely-on-dplane-table_id-for-VRF-delete.patch create mode 100644 subprojects/packagefiles/frr/0002-zebra-use-dplane-provided-vrf_id-instead-of-casting-.patch diff --git a/subprojects/frr.wrap b/subprojects/frr.wrap index e31735931..5faea8641 100644 --- a/subprojects/frr.wrap +++ b/subprojects/frr.wrap @@ -3,7 +3,9 @@ url = https://github.com/FRRouting/frr revision = frr-10.5.0 depth = 1 diff_files = - frr/meson-add-dependency-definition.patch + frr/meson-add-dependency-definition.patch, + frr/0001-zebra-do-not-rely-on-dplane-table_id-for-VRF-delete.patch, + frr/0002-zebra-use-dplane-provided-vrf_id-instead-of-casting-.patch [provide] dependency_names = frr diff --git a/subprojects/packagefiles/frr/0001-zebra-do-not-rely-on-dplane-table_id-for-VRF-delete.patch b/subprojects/packagefiles/frr/0001-zebra-do-not-rely-on-dplane-table_id-for-VRF-delete.patch new file mode 100644 index 000000000..eb1b138cc --- /dev/null +++ b/subprojects/packagefiles/frr/0001-zebra-do-not-rely-on-dplane-table_id-for-VRF-delete.patch @@ -0,0 +1,211 @@ +From adaa85be78e69e92bd2cc46f8c41462edd16c541 Mon Sep 17 00:00:00 2001 +From: Maxime Leroy +Date: Mon, 22 Dec 2025 14:28:32 +0100 +Subject: [PATCH 1/2] zebra: do not rely on dplane table_id for VRF delete + +zebra_if_dplane_ifp_handling() was reading dplane_ctx_get_ifp_table_id() +for VRF events. + +In the netlink dplane backend, ifp_table_id is only set via +netlink_vrf_change(), which is invoked from netlink_link_change() for +RTM_NEWLINK VRF events. It is not set for RTM_DELLINK. + +The VRF delete path does not require table_id and should not depend +on a dplane field that is unset for delete operations. + +Split VRF handling into interface_vrf_update() and interface_vrf_del() +so: +- add/update uses the dplane-provided table_id +- delete only relies on the VRF identity + +Signed-off-by: Maxime Leroy +--- + zebra/interface.c | 137 +++++++++++++++++++++++----------------------- + 1 file changed, 67 insertions(+), 70 deletions(-) + +diff --git a/zebra/interface.c b/zebra/interface.c +index 52c2619eed..17b62cf586 100644 +--- a/zebra/interface.c ++++ b/zebra/interface.c +@@ -1425,86 +1425,81 @@ static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx, + (*linkdown_set ? "ON" : "OFF")); + } + +-static void interface_vrf_change(enum dplane_op_e op, ifindex_t ifindex, +- const char *name, uint32_t tableid, +- ns_id_t ns_id) ++static void interface_vrf_del(ifindex_t ifindex, const char *name) + { + struct vrf *vrf; +- struct zebra_vrf *zvrf = NULL; + +- if (op == DPLANE_OP_INTF_DELETE) { +- if (IS_ZEBRA_DEBUG_DPLANE) +- zlog_debug("DPLANE_OP_INTF_DELETE for VRF %s(%u)", name, +- ifindex); ++ if (IS_ZEBRA_DEBUG_DPLANE) ++ zlog_debug("DPLANE_OP_INTF_DELETE for VRF %s(%u)", name, ifindex); + +- vrf = vrf_lookup_by_id((vrf_id_t)ifindex); +- if (!vrf) { +- flog_warn(EC_ZEBRA_VRF_NOT_FOUND, +- "%s(%u): vrf not found", name, ifindex); +- return; +- } ++ vrf = vrf_lookup_by_id((vrf_id_t)ifindex); ++ if (!vrf) { ++ flog_warn(EC_ZEBRA_VRF_NOT_FOUND, "%s(%u): vrf not found", name, ifindex); ++ return; ++ } + +- vrf_delete(vrf); +- } else { +- if (IS_ZEBRA_DEBUG_DPLANE) +- zlog_debug( +- "DPLANE_OP_INTF_UPDATE for VRF %s(%u) table %u", +- name, ifindex, tableid); ++ vrf_delete(vrf); ++} + +- /* +- * For a given tableid, if there already exists a vrf and it +- * is different from the current vrf to be operated, then there +- * is a misconfiguration and zebra will exit. +- */ +- vrf_id_t exist_id = zebra_vrf_lookup_by_table(tableid, ns_id); + +- if (exist_id != VRF_DEFAULT || strmatch(name, VRF_DEFAULT_NAME)) { +- vrf = vrf_lookup_by_id(exist_id); ++static void interface_vrf_update(ifindex_t ifindex, const char *name, uint32_t tableid, ++ ns_id_t ns_id) ++{ ++ struct vrf *vrf; ++ struct zebra_vrf *zvrf = NULL; + +- if (!vrf_lookup_by_id((vrf_id_t)ifindex) && !vrf) { +- flog_err(EC_ZEBRA_VRF_NOT_FOUND, +- "VRF %s id %u does not exist", name, +- ifindex); +- frr_exit_with_buffer_flush(-1); +- } ++ if (IS_ZEBRA_DEBUG_DPLANE) ++ zlog_debug("DPLANE_OP_INTF_UPDATE for VRF %s(%u) table %u", name, ifindex, tableid); + +- if (vrf && strcmp(name, vrf->name)) { +- flog_err(EC_ZEBRA_VRF_MISCONFIGURED, +- "VRF %s id %u table id overlaps existing vrf %s(%d), misconfiguration exiting", +- name, ifindex, vrf->name, vrf->vrf_id); +- frr_exit_with_buffer_flush(-1); +- } ++ /* ++ * For a given tableid, if there already exists a vrf and it ++ * is different from the current vrf to be operated, then there ++ * is a misconfiguration and zebra will exit. ++ */ ++ vrf_id_t exist_id = zebra_vrf_lookup_by_table(tableid, ns_id); ++ ++ if (exist_id != VRF_DEFAULT || strmatch(name, VRF_DEFAULT_NAME)) { ++ vrf = vrf_lookup_by_id(exist_id); ++ ++ if (!vrf_lookup_by_id((vrf_id_t)ifindex) && !vrf) { ++ flog_err(EC_ZEBRA_VRF_NOT_FOUND, "VRF %s id %u does not exist", name, ++ ifindex); ++ frr_exit_with_buffer_flush(-1); + } + +- vrf = vrf_update((vrf_id_t)ifindex, name); +- if (!vrf) { +- flog_err(EC_LIB_INTERFACE, "VRF %s id %u not created", +- name, ifindex); +- return; ++ if (vrf && strcmp(name, vrf->name)) { ++ flog_err(EC_ZEBRA_VRF_MISCONFIGURED, ++ "VRF %s id %u table id overlaps existing vrf %s(%d), misconfiguration exiting", ++ name, ifindex, vrf->name, vrf->vrf_id); ++ frr_exit_with_buffer_flush(-1); + } ++ } + +- /* +- * This is the only place that we get the actual kernel table_id +- * being used. We need it to set the table_id of the routes +- * we are passing to the kernel.... And to throw some totally +- * awesome parties. that too. +- * +- * At this point we *must* have a zvrf because the vrf_create +- * callback creates one. We *must* set the table id +- * before the vrf_enable because of( at the very least ) +- * static routes being delayed for installation until +- * during the vrf_enable callbacks. +- */ +- zvrf = (struct zebra_vrf *)vrf->info; +- zvrf->table_id = tableid; ++ vrf = vrf_update((vrf_id_t)ifindex, name); ++ if (!vrf) { ++ flog_err(EC_LIB_INTERFACE, "VRF %s id %u not created", name, ifindex); ++ return; ++ } + +- /* Enable the created VRF. */ +- if (!vrf_enable(vrf)) { +- flog_err(EC_LIB_INTERFACE, +- "Failed to enable VRF %s id %u", name, +- ifindex); +- return; +- } ++ /* ++ * This is the only place that we get the actual kernel table_id ++ * being used. We need it to set the table_id of the routes ++ * we are passing to the kernel.... And to throw some totally ++ * awesome parties. that too. ++ * ++ * At this point we *must* have a zvrf because the vrf_create ++ * callback creates one. We *must* set the table id ++ * before the vrf_enable because of( at the very least ) ++ * static routes being delayed for installation until ++ * during the vrf_enable callbacks. ++ */ ++ zvrf = (struct zebra_vrf *)vrf->info; ++ zvrf->table_id = tableid; ++ ++ /* Enable the created VRF. */ ++ if (!vrf_enable(vrf)) { ++ flog_err(EC_LIB_INTERFACE, "Failed to enable VRF %s id %u", name, ifindex); ++ return; + } + } + +@@ -1876,7 +1871,6 @@ static void zebra_if_dplane_ifp_handling(struct zebra_dplane_ctx *ctx) + ns_id_t ns_id = dplane_ctx_get_ns_id(ctx); + ifindex_t ifindex = dplane_ctx_get_ifindex(ctx); + ifindex_t bond_ifindex = dplane_ctx_get_ifp_bond_ifindex(ctx); +- uint32_t tableid = dplane_ctx_get_ifp_table_id(ctx); + enum zebra_iftype zif_type = dplane_ctx_get_ifp_zif_type(ctx); + struct interface *ifp; + struct zebra_ns *zns; +@@ -1914,7 +1908,7 @@ static void zebra_if_dplane_ifp_handling(struct zebra_dplane_ctx *ctx) + if_delete_update(&ifp); + + if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) +- interface_vrf_change(op, ifindex, name, tableid, ns_id); ++ interface_vrf_del(ifindex, name); + } else { + ifindex_t master_ifindex, bridge_ifindex, link_ifindex; + enum zebra_slave_iftype zif_slave_type; +@@ -1931,8 +1925,11 @@ static void zebra_if_dplane_ifp_handling(struct zebra_dplane_ctx *ctx) + uint8_t family; + + /* If VRF, create or update the VRF structure itself. */ +- if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) +- interface_vrf_change(op, ifindex, name, tableid, ns_id); ++ if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) { ++ uint32_t tableid = dplane_ctx_get_ifp_table_id(ctx); ++ ++ interface_vrf_update(ifindex, name, tableid, ns_id); ++ } + + master_ifindex = dplane_ctx_get_ifp_master_ifindex(ctx); + zif_slave_type = dplane_ctx_get_ifp_zif_slave_type(ctx); +-- +2.43.0 + diff --git a/subprojects/packagefiles/frr/0002-zebra-use-dplane-provided-vrf_id-instead-of-casting-.patch b/subprojects/packagefiles/frr/0002-zebra-use-dplane-provided-vrf_id-instead-of-casting-.patch new file mode 100644 index 000000000..7efc7f680 --- /dev/null +++ b/subprojects/packagefiles/frr/0002-zebra-use-dplane-provided-vrf_id-instead-of-casting-.patch @@ -0,0 +1,164 @@ +From 1cc366a1a709f9cb58d5374888b49d4ed87b09da Mon Sep 17 00:00:00 2001 +From: Maxime Leroy +Date: Mon, 22 Dec 2025 15:02:41 +0100 +Subject: [PATCH 2/2] zebra: use dplane-provided vrf_id instead of casting + ifindex + +interface_vrf_change() was implicitly assuming that the VRF netdevice +ifindex could be used as zebra's vrf_id. + +This assumption holds true for the Linux kernel dataplane, where the VRF +ID is defined as the ifindex of the VRF interface, so this change does +not alter kernel behavior. + +However, the dataplane API already exposes both concepts explicitly via +dplane_ctx_get_ifindex() and dplane_ctx_get_ifp_vrf_id(ctx). Using the +proper accessor avoids casting an ifindex to vrf_id_t and better respects +the dataplane abstraction. + +On interface updates, the vrf_id provided by the dataplane is now used +directly. On interface deletion (DELLINK), where the dataplane context +may no longer carry vrf information, zebra relies on the existing ifp +state keyed by ifindex. + +This is required for non-kernel dataplanes such as Grout (DPDK), where +the VRF ID is not equal to the VRF interface ifindex. In that case, using +the correct vrf_id fixes VRF handling between zebra and the Grout +dataplane. + +Signed-off-by: Maxime Leroy +--- + zebra/interface.c | 34 +++++++++++++++++----------------- + 1 file changed, 17 insertions(+), 17 deletions(-) + +diff --git a/zebra/interface.c b/zebra/interface.c +index 17b62cf586..3c60d4e166 100644 +--- a/zebra/interface.c ++++ b/zebra/interface.c +@@ -1425,16 +1425,16 @@ static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx, + (*linkdown_set ? "ON" : "OFF")); + } + +-static void interface_vrf_del(ifindex_t ifindex, const char *name) ++static void interface_vrf_del(vrf_id_t vrf_id, const char *name) + { + struct vrf *vrf; + + if (IS_ZEBRA_DEBUG_DPLANE) +- zlog_debug("DPLANE_OP_INTF_DELETE for VRF %s(%u)", name, ifindex); ++ zlog_debug("DPLANE_OP_INTF_DELETE for VRF %s(%u)", name, vrf_id); + +- vrf = vrf_lookup_by_id((vrf_id_t)ifindex); ++ vrf = vrf_lookup_by_id(vrf_id); + if (!vrf) { +- flog_warn(EC_ZEBRA_VRF_NOT_FOUND, "%s(%u): vrf not found", name, ifindex); ++ flog_warn(EC_ZEBRA_VRF_NOT_FOUND, "%s(%u): vrf not found", name, vrf_id); + return; + } + +@@ -1442,14 +1442,13 @@ static void interface_vrf_del(ifindex_t ifindex, const char *name) + } + + +-static void interface_vrf_update(ifindex_t ifindex, const char *name, uint32_t tableid, +- ns_id_t ns_id) ++static void interface_vrf_update(vrf_id_t vrf_id, const char *name, uint32_t tableid, ns_id_t ns_id) + { + struct vrf *vrf; + struct zebra_vrf *zvrf = NULL; + + if (IS_ZEBRA_DEBUG_DPLANE) +- zlog_debug("DPLANE_OP_INTF_UPDATE for VRF %s(%u) table %u", name, ifindex, tableid); ++ zlog_debug("DPLANE_OP_INTF_UPDATE for VRF %s(%u) table %u", name, vrf_id, tableid); + + /* + * For a given tableid, if there already exists a vrf and it +@@ -1461,23 +1460,23 @@ static void interface_vrf_update(ifindex_t ifindex, const char *name, uint32_t t + if (exist_id != VRF_DEFAULT || strmatch(name, VRF_DEFAULT_NAME)) { + vrf = vrf_lookup_by_id(exist_id); + +- if (!vrf_lookup_by_id((vrf_id_t)ifindex) && !vrf) { ++ if (!vrf_lookup_by_id(vrf_id) && !vrf) { + flog_err(EC_ZEBRA_VRF_NOT_FOUND, "VRF %s id %u does not exist", name, +- ifindex); ++ vrf_id); + frr_exit_with_buffer_flush(-1); + } + + if (vrf && strcmp(name, vrf->name)) { + flog_err(EC_ZEBRA_VRF_MISCONFIGURED, + "VRF %s id %u table id overlaps existing vrf %s(%d), misconfiguration exiting", +- name, ifindex, vrf->name, vrf->vrf_id); ++ name, vrf_id, vrf->name, vrf->vrf_id); + frr_exit_with_buffer_flush(-1); + } + } + +- vrf = vrf_update((vrf_id_t)ifindex, name); ++ vrf = vrf_update(vrf_id, name); + if (!vrf) { +- flog_err(EC_LIB_INTERFACE, "VRF %s id %u not created", name, ifindex); ++ flog_err(EC_LIB_INTERFACE, "VRF %s id %u not created", name, vrf_id); + return; + } + +@@ -1498,7 +1497,7 @@ static void interface_vrf_update(ifindex_t ifindex, const char *name, uint32_t t + + /* Enable the created VRF. */ + if (!vrf_enable(vrf)) { +- flog_err(EC_LIB_INTERFACE, "Failed to enable VRF %s id %u", name, ifindex); ++ flog_err(EC_LIB_INTERFACE, "Failed to enable VRF %s id %u", name, vrf_id); + return; + } + } +@@ -1874,6 +1873,7 @@ static void zebra_if_dplane_ifp_handling(struct zebra_dplane_ctx *ctx) + enum zebra_iftype zif_type = dplane_ctx_get_ifp_zif_type(ctx); + struct interface *ifp; + struct zebra_ns *zns; ++ vrf_id_t vrf_id; + + zns = zebra_ns_lookup(ns_id); + if (!zns) { +@@ -1905,16 +1905,16 @@ static void zebra_if_dplane_ifp_handling(struct zebra_dplane_ctx *ctx) + else if (IS_ZEBRA_IF_VXLAN(ifp)) + zebra_l2_vxlanif_del(ifp); + ++ vrf_id = ifp->vrf->vrf_id; + if_delete_update(&ifp); + + if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) +- interface_vrf_del(ifindex, name); ++ interface_vrf_del(vrf_id, name); + } else { + ifindex_t master_ifindex, bridge_ifindex, link_ifindex; + enum zebra_slave_iftype zif_slave_type; + uint8_t bypass; + uint64_t flags; +- vrf_id_t vrf_id; + uint32_t mtu; + ns_id_t link_nsid; + struct zebra_if *zif; +@@ -1925,10 +1925,11 @@ static void zebra_if_dplane_ifp_handling(struct zebra_dplane_ctx *ctx) + uint8_t family; + + /* If VRF, create or update the VRF structure itself. */ ++ vrf_id = dplane_ctx_get_ifp_vrf_id(ctx); + if (zif_type == ZEBRA_IF_VRF && !vrf_is_backend_netns()) { + uint32_t tableid = dplane_ctx_get_ifp_table_id(ctx); + +- interface_vrf_update(ifindex, name, tableid, ns_id); ++ interface_vrf_update(vrf_id, name, tableid, ns_id); + } + + master_ifindex = dplane_ctx_get_ifp_master_ifindex(ctx); +@@ -1937,7 +1938,6 @@ static void zebra_if_dplane_ifp_handling(struct zebra_dplane_ctx *ctx) + bond_ifindex = dplane_ctx_get_ifp_bond_ifindex(ctx); + bypass = dplane_ctx_get_ifp_bypass(ctx); + flags = dplane_ctx_get_ifp_flags(ctx); +- vrf_id = dplane_ctx_get_ifp_vrf_id(ctx); + mtu = dplane_ctx_get_ifp_mtu(ctx); + link_ifindex = dplane_ctx_get_ifp_link_ifindex(ctx); + link_nsid = dplane_ctx_get_ifp_link_nsid(ctx); +-- +2.43.0 + From aeb5215a98b9c87a70b8e8f4d015bcc180a14429 Mon Sep 17 00:00:00 2001 From: Maxime Leroy Date: Mon, 22 Dec 2025 15:45:09 +0100 Subject: [PATCH 2/3] frr: no needs to convert vrf_id into frr ifindex TODO : make a commit log (just a draft) Signed-off-by: Maxime Leroy --- frr/if_grout.c | 14 ++------------ frr/rt_grout.c | 42 ++++++++++++------------------------------ 2 files changed, 14 insertions(+), 42 deletions(-) diff --git a/frr/if_grout.c b/frr/if_grout.c index 4fa7783c8..c0aa1a2dc 100644 --- a/frr/if_grout.c +++ b/frr/if_grout.c @@ -120,18 +120,8 @@ void grout_link_change(struct gr_iface *gr_if, bool new, bool startup) { dplane_ctx_set_ifp_zltype(ctx, link_type); dplane_ctx_set_ifp_flags(ctx, gr_if_flags_to_netlink(gr_if, link_type)); dplane_ctx_set_ifp_protodown_set(ctx, false); - - if (gr_if->base.vrf_id != 0) { - dplane_ctx_set_ifp_table_id(ctx, ifindex_grout_to_frr(gr_if->base.vrf_id)); - - // In Linux, vrf_id equals the interface index; in Grout we model a VRF - // with its gr‑vrf interface - // The gr‑vrf’s ifindex is guaranteed to match vrf_id - dplane_ctx_set_ifp_vrf_id(ctx, ifindex_grout_to_frr(gr_if->base.vrf_id)); - } else { - dplane_ctx_set_ifp_table_id(ctx, 0); - dplane_ctx_set_ifp_vrf_id(ctx, 0); - } + dplane_ctx_set_ifp_table_id(ctx, gr_if->base.vrf_id); + dplane_ctx_set_ifp_vrf_id(ctx, gr_if->base.vrf_id); if (mac) dplane_ctx_set_ifp_hw_addr( diff --git a/frr/rt_grout.c b/frr/rt_grout.c index b915af2aa..835fa0c7c 100644 --- a/frr/rt_grout.c +++ b/frr/rt_grout.c @@ -192,7 +192,7 @@ static int grout_gr_nexthop_to_frr_nexthop( int *nh_family ) { nh->ifindex = ifindex_grout_to_frr(gr_nh->iface_id); - nh->vrf_id = ifindex_grout_to_frr(gr_nh->vrf_id); + nh->vrf_id = gr_nh->vrf_id; nh->weight = 1; switch (gr_nh->type) { @@ -268,7 +268,7 @@ static int grout_gr_nexthop_to_frr_nexthop( break; } - ctx.table = ifindex_grout_to_frr(sr6->out_vrf_id); + ctx.table = sr6->out_vrf_id; nexthop_add_srv6_seg6local(nh, action, &ctx); break; } @@ -292,7 +292,7 @@ static int grout_gr_nexthop_to_frr_nexthop( } case GR_NH_T_GROUP: nh->ifindex = ifindex_grout_to_frr(gr_nh->iface_id); - nh->vrf_id = ifindex_grout_to_frr(gr_nh->vrf_id); + nh->vrf_id = gr_nh->vrf_id; *nh_family = AF_UNSPEC; nh->weight = 1; break; @@ -314,7 +314,7 @@ static void grout_route_change( uint8_t dest_prefixlen, struct gr_nexthop *gr_nh ) { - uint32_t vrf_id = ifindex_grout_to_frr(gr_nh->vrf_id); + uint32_t vrf_id = gr_nh->vrf_id; int proto = ZEBRA_ROUTE_KERNEL; uint32_t nh_id = gr_nh->nh_id; // Grout has no per‑VRF routing tables; table_id always equals vrf_id @@ -464,7 +464,7 @@ enum zebra_dplane_result grout_add_del_route(struct zebra_dplane_ctx *ctx) { struct gr_ip6_route_del_req r6_del; } req; uint32_t nh_id = dplane_ctx_get_nhe_id(ctx); - uint32_t vrf_id = ifindex_frr_to_grout(dplane_ctx_get_vrf(ctx)); + uint32_t vrf_id = dplane_ctx_get_vrf(ctx); const struct prefix *p; gr_nh_origin_t origin; uint32_t req_type; @@ -668,7 +668,7 @@ grout_add_nexthop(uint32_t nh_id, gr_nh_origin_t origin, const struct nexthop *n req->nh.nh_id = nh_id; req->nh.origin = origin; req->nh.type = type; - req->nh.vrf_id = ifindex_frr_to_grout(nh->vrf_id); + req->nh.vrf_id = nh->vrf_id; req->nh.iface_id = ifindex_frr_to_grout(nh->ifindex); switch (type) { @@ -704,27 +704,19 @@ grout_add_nexthop(uint32_t nh_id, gr_nh_origin_t origin, const struct nexthop *n break; case ZEBRA_SEG6_LOCAL_ACTION_END_T: sr6_local->behavior = SR_BEHAVIOR_END_T; - sr6_local->out_vrf_id = ifindex_frr_to_grout( - nh->nh_srv6->seg6local_ctx.table - ); + sr6_local->out_vrf_id = nh->nh_srv6->seg6local_ctx.table; break; case ZEBRA_SEG6_LOCAL_ACTION_END_DT6: sr6_local->behavior = SR_BEHAVIOR_END_DT6; - sr6_local->out_vrf_id = ifindex_frr_to_grout( - nh->nh_srv6->seg6local_ctx.table - ); + sr6_local->out_vrf_id = nh->nh_srv6->seg6local_ctx.table; break; case ZEBRA_SEG6_LOCAL_ACTION_END_DT4: sr6_local->behavior = SR_BEHAVIOR_END_DT4; - sr6_local->out_vrf_id = ifindex_frr_to_grout( - nh->nh_srv6->seg6local_ctx.table - ); + sr6_local->out_vrf_id = nh->nh_srv6->seg6local_ctx.table; break; case ZEBRA_SEG6_LOCAL_ACTION_END_DT46: sr6_local->behavior = SR_BEHAVIOR_END_DT46; - sr6_local->out_vrf_id = ifindex_frr_to_grout( - nh->nh_srv6->seg6local_ctx.table - ); + sr6_local->out_vrf_id = nh->nh_srv6->seg6local_ctx.table; break; default: gr_log_err( @@ -831,7 +823,7 @@ void grout_nexthop_change(bool new, struct gr_nexthop *gr_nh, bool startup) { } if (!new) { - zebra_nhg_kernel_del(gr_nh->nh_id, ifindex_grout_to_frr(gr_nh->vrf_id)); + zebra_nhg_kernel_del(gr_nh->nh_id, gr_nh->vrf_id); return; } @@ -850,17 +842,7 @@ void grout_nexthop_change(bool new, struct gr_nexthop *gr_nh, bool startup) { type = origin2zebra(gr_nh->origin, family, false); SET_FLAG(nh->flags, NEXTHOP_FLAG_ACTIVE); - zebra_nhg_kernel_find( - gr_nh->nh_id, - nh, - NULL, - 0, - ifindex_grout_to_frr(gr_nh->vrf_id), - afi, - type, - startup, - NULL - ); + zebra_nhg_kernel_find(gr_nh->nh_id, nh, NULL, 0, gr_nh->vrf_id, afi, type, startup, NULL); // zebra_nhg_kernel_find() makes a *shallow* copy of the allocated nexthop. // nexthop_free() must *NOT* be used to preserve the nh_srv6 context. From 586629d78ba7dc6a066d34e010453c164fd40f61 Mon Sep 17 00:00:00 2001 From: Maxime Leroy Date: Mon, 22 Dec 2025 12:35:49 +0100 Subject: [PATCH 3/3] =?UTF-8?q?Revert=20"infra:=20reserve=20ifindex=201?= =?UTF-8?q?=E2=80=91255=20so=20gr=E2=80=91loopX=20=3D=3D=20VRF=E2=80=AFX"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 18355c32c009c07e3bd19fd6616a6d7581151ae3. Signed-off-by: Maxime Leroy --- modules/infra/control/iface.c | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/modules/infra/control/iface.c b/modules/infra/control/iface.c index af08ba1ff..73848e23f 100644 --- a/modules/infra/control/iface.c +++ b/modules/infra/control/iface.c @@ -48,28 +48,13 @@ void iface_type_register(struct iface_type *type) { // the first slot is wasted by GR_IFACE_ID_UNDEF static struct iface **ifaces; -// Reserve a specific interface id. -// Returns 0 on success, -errno on failure. -static int reserve_ifid(uint16_t ifid) { - if (ifid >= MAX_IFACES) - return errno_set(EINVAL); - - if (ifaces[ifid] == NULL) - return 0; - - return errno_set(EBUSY); -} - -// The slot 1 to 255 are reserved for gr_loopback static int next_ifid(uint16_t *ifid) { - for (uint16_t i = GR_MAX_VRFS; i < MAX_IFACES; i++) { - if (reserve_ifid(i) < 0) - continue; - - *ifid = i; - return 0; + for (uint16_t i = IFACE_ID_FIRST; i < MAX_IFACES; i++) { + if (ifaces[i] == NULL) { + *ifid = i; + return 0; + } } - return errno_set(ENOSPC); } @@ -100,11 +85,7 @@ struct iface *iface_create(const struct gr_iface *conf, const void *api_info) { vrf_incref(conf->vrf_id); vrf_ref = true; } - if (conf->type == GR_IFACE_TYPE_LOOPBACK && conf->vrf_id) { - ifid = conf->vrf_id; - if (reserve_ifid(ifid) < 0) - goto fail; - } else if (next_ifid(&ifid) < 0) + if (next_ifid(&ifid) < 0) goto fail; iface->base = conf->base;