Skip to content

Commit cca8e2e

Browse files
frr: add basic multipath support
Using the new nexthop type group, allow multiple nexthop as a gateway from frr. The following zebra conf: ! ip route 192.168.1.20/32 cv0 ip route 192.168.1.20/32 192.168.210.3 ip route 192.168.1.20/32 192.168.210.254 ! translates into these rib nexthops: ID: 35 (zebra) RefCnt: 2 Uptime: 00:00:07 VRF: default(No AFI) Nexthop Count: 3 Valid, Installed Depends: (20) (24) (30) is directly connected, cv0 (vrf default), weight 1 via 192.168.210.3, cv0 (vrf default), weight 1 via 192.168.210.254, cv0 (vrf default), weight 1 With grout displays the proper NHs: grout# nexthop type group VRF ID ORIGIN IFACE TYPE INFO 0 35 user group id(20/1) id(24/1) id(30/1) Signed-off-by: Christophe Fontaine <[email protected]>
1 parent e489879 commit cca8e2e

File tree

1 file changed

+47
-7
lines changed

1 file changed

+47
-7
lines changed

frr/rt_grout.c

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,12 @@ static int grout_gr_nexthop_to_frr_nexthop(
289289
nexthop_add_srv6_seg6(nh, (void *)sr6->seglist, sr6->n_seglist, encap_behavior);
290290
break;
291291
}
292+
case GR_NH_T_GROUP:
293+
nh->ifindex = gr_nh->iface_id;
294+
nh->vrf_id = gr_nh->vrf_id;
295+
*nh_family = AF_UNSPEC;
296+
nh->weight = 1;
297+
break;
292298
default:
293299
gr_log_err(
294300
"sync %s nexthops from grout not supported", gr_nh_type_name(gr_nh->type)
@@ -572,12 +578,49 @@ enum zebra_dplane_result grout_add_del_route(struct zebra_dplane_ctx *ctx) {
572578
return ZEBRA_DPLANE_REQUEST_SUCCESS;
573579
}
574580

581+
static enum zebra_dplane_result grout_add_nexthop_group(struct zebra_dplane_ctx *ctx) {
582+
uint32_t nh_id = dplane_ctx_get_nhe_id(ctx);
583+
struct gr_nexthop_info_group *group;
584+
struct gr_nh_add_req *req = NULL;
585+
size_t len;
586+
587+
len = sizeof(*req) + sizeof(*group);
588+
if ((req = calloc(1, len)) == NULL)
589+
return ZEBRA_DPLANE_REQUEST_FAILURE;
590+
591+
req->exist_ok = true;
592+
req->nh.nh_id = nh_id;
593+
req->nh.type = GR_NH_T_GROUP;
594+
req->nh.origin = zebra2origin(dplane_ctx_get_nhe_type(ctx));
595+
group = (struct gr_nexthop_info_group *)req->nh.info;
596+
group->count = dplane_ctx_get_nhe_nh_grp_count(ctx);
597+
598+
if (group->count > GR_NH_GROUP_MAX) {
599+
gr_log_err(
600+
"nexthop-group %u has too many members (%u > %u)",
601+
nh_id,
602+
group->count,
603+
GR_NH_GROUP_MAX
604+
);
605+
return ZEBRA_DPLANE_REQUEST_FAILURE;
606+
}
607+
const struct nh_grp *nhs = dplane_ctx_get_nhe_nh_grp(ctx);
608+
for (size_t i = 0; i < group->count; i++) {
609+
group->nh_ids[i] = nhs[i].id;
610+
group->weights[i] = nhs[i].weight;
611+
}
612+
613+
if (grout_client_send_recv(GR_NH_ADD, len, req, NULL) < 0)
614+
return ZEBRA_DPLANE_REQUEST_FAILURE;
615+
616+
return ZEBRA_DPLANE_REQUEST_SUCCESS;
617+
}
618+
575619
static enum zebra_dplane_result grout_del_nexthop(uint32_t nh_id) {
576620
struct gr_nh_del_req req = {.missing_ok = true, .nh_id = nh_id};
577621

578622
if (grout_client_send_recv(GR_NH_DEL, sizeof(req), &req, NULL) < 0)
579623
return ZEBRA_DPLANE_REQUEST_FAILURE;
580-
581624
return ZEBRA_DPLANE_REQUEST_SUCCESS;
582625
}
583626

@@ -762,15 +805,12 @@ enum zebra_dplane_result grout_add_del_nexthop(struct zebra_dplane_ctx *ctx) {
762805
return ZEBRA_DPLANE_REQUEST_FAILURE;
763806
}
764807

765-
if (dplane_ctx_get_nhe_nh_grp_count(ctx)) {
766-
// next group are not supported in grout
767-
gr_log_err("impossible to add/del nexthop grout %u (nhg not supported)", nh_id);
768-
return ZEBRA_DPLANE_REQUEST_FAILURE;
769-
}
770-
771808
if (dplane_ctx_get_op(ctx) == DPLANE_OP_NH_DELETE)
772809
return grout_del_nexthop(nh_id);
773810

811+
if (dplane_ctx_get_nhe_nh_grp_count(ctx))
812+
return grout_add_nexthop_group(ctx);
813+
774814
return grout_add_nexthop(nh_id, origin, dplane_ctx_get_nhe_ng(ctx)->nexthop);
775815
}
776816

0 commit comments

Comments
 (0)