Skip to content

Commit c03a8b0

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 f40d836 commit c03a8b0

File tree

3 files changed

+101
-8
lines changed

3 files changed

+101
-8
lines changed

frr/rt_grout.c

Lines changed: 40 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,42 @@ 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+
+ dplane_ctx_get_nhe_nh_grp_count(ctx) * sizeof(group->members[0]);
589+
if ((req = calloc(1, len)) == NULL)
590+
return ZEBRA_DPLANE_REQUEST_FAILURE;
591+
592+
group = (struct gr_nexthop_info_group *)req->nh.info;
593+
group->n_members = dplane_ctx_get_nhe_nh_grp_count(ctx);
594+
595+
req->exist_ok = true;
596+
req->nh.nh_id = nh_id;
597+
req->nh.type = GR_NH_T_GROUP;
598+
req->nh.origin = zebra2origin(dplane_ctx_get_nhe_type(ctx));
599+
600+
const struct nh_grp *nhs = dplane_ctx_get_nhe_nh_grp(ctx);
601+
for (size_t i = 0; i < group->n_members; i++) {
602+
group->members[i].nh_id = nhs[i].id;
603+
group->members[i].weight = nhs[i].weight;
604+
}
605+
606+
if (grout_client_send_recv(GR_NH_ADD, len, req, NULL) < 0)
607+
return ZEBRA_DPLANE_REQUEST_FAILURE;
608+
609+
return ZEBRA_DPLANE_REQUEST_SUCCESS;
610+
}
611+
575612
static enum zebra_dplane_result grout_del_nexthop(uint32_t nh_id) {
576613
struct gr_nh_del_req req = {.missing_ok = true, .nh_id = nh_id};
577614

578615
if (grout_client_send_recv(GR_NH_DEL, sizeof(req), &req, NULL) < 0)
579616
return ZEBRA_DPLANE_REQUEST_FAILURE;
580-
581617
return ZEBRA_DPLANE_REQUEST_SUCCESS;
582618
}
583619

@@ -762,15 +798,12 @@ enum zebra_dplane_result grout_add_del_nexthop(struct zebra_dplane_ctx *ctx) {
762798
return ZEBRA_DPLANE_REQUEST_FAILURE;
763799
}
764800

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-
771801
if (dplane_ctx_get_op(ctx) == DPLANE_OP_NH_DELETE)
772802
return grout_del_nexthop(nh_id);
773803

804+
if (dplane_ctx_get_nhe_nh_grp_count(ctx))
805+
return grout_add_nexthop_group(ctx);
806+
774807
return grout_add_nexthop(nh_id, origin, dplane_ctx_get_nhe_ng(ctx)->nexthop);
775808
}
776809

smoke/ip_loadbalance_frr_test.sh

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: BSD-3-Clause
3+
# Copyright (c) 2025 Christophe Fontaine
4+
5+
#
6+
# | p1 (.1.2)
7+
# [p0 ns0] --- grout --- | ns1 lo
8+
# | p2 (.2.2)
9+
#
10+
#
11+
#
12+
. $(dirname $0)/_init_frr.sh
13+
14+
p0=${run_id}0
15+
p1=${run_id}1
16+
p2=${run_id}2
17+
18+
create_interface $p0 f0:0d:ac:dc:00:00
19+
create_interface $p1 f0:0d:ac:dc:00:01
20+
create_interface $p2 f0:0d:ac:dc:00:02
21+
22+
netns_add n-$p0
23+
ip l set $p0 netns n-$p0
24+
ip -n n-$p0 link set $p0 address ba:d0:ca:ca:00:00
25+
ip -n n-$p0 link set $p0 up
26+
ip -n n-$p0 link set lo up
27+
ip -n n-$p0 addr add 172.16.0.2/24 dev $p0
28+
ip -n n-$p0 route add default via 172.16.0.1
29+
30+
netns_add n-$p1
31+
ip l set $p1 netns n-$p1
32+
ip l set $p2 netns n-$p1
33+
ip -n n-$p1 link set lo up
34+
ip -n n-$p1 addr add 192.0.0.2/32 dev lo
35+
ip -n n-$p1 link set $p1 address ba:d0:ca:ca:00:01
36+
ip -n n-$p1 link set $p1 up
37+
ip -n n-$p1 addr add 172.16.1.2/24 dev $p1
38+
ip -n n-$p1 link set $p2 address ba:d0:ca:ca:00:02
39+
ip -n n-$p1 link set $p2 up
40+
ip -n n-$p1 addr add 172.16.2.2/24 dev $p2
41+
42+
set_ip_address $p0 172.16.0.1/24
43+
set_ip_address $p1 172.16.1.1/24
44+
set_ip_address $p2 172.16.2.1/24
45+
46+
set_ip_route 192.0.0.0/24 172.16.1.2
47+
# Can't use set_ip_route a second time
48+
# as the helper will look for the route
49+
# --> Configure it manually
50+
vtysh <<-EOF
51+
configure terminal
52+
ip route 192.0.0.0/24 172.16.2.2
53+
EOF
54+
55+
ip -n n-$p1 route add default via 172.16.1.1
56+
ip netns exec n-$p0 ping 192.0.0.2 -c 4
57+
58+
ip -n n-$p1 route del default
59+
ip -n n-$p1 route add default via 172.16.2.1
60+
ip netns exec n-$p0 ping 192.0.0.2 -c 4

subprojects/packagefiles/frr/meson-add-dependency-definition.patch

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ index 0000000..d26e979
103103
+ '"' + srcdir + '/configure" ' +
104104
+ '--prefix="' + prefix + '" ' +
105105
+ '--with-moduledir="' + moduledir + '" ' +
106-
+ '--disable-doc --enable-multipath=1 ' +
106+
+ '--disable-doc --enable-multipath=128 ' +
107107
+ '--disable-ripd --disable-ripngd --disable-ospfd --disable-ospf6d ' +
108108
+ '--disable-ldpd --disable-nhrpd --disable-eigrpd --disable-babeld ' +
109109
+ '--disable-isisd --disable-pimd --disable-pim6d --disable-pbrd --disable-fabricd ' +

0 commit comments

Comments
 (0)