summaryrefslogtreecommitdiffstats
path: root/zebra/rt_netlink.c
diff options
context:
space:
mode:
authorStephen Worley <sworley@nvidia.com>2021-04-01 17:50:31 +0200
committerStephen Worley <sworley@nvidia.com>2023-02-14 00:12:05 +0100
commit5fa6bfffb1201c98960ea8a3808d6e1e7ed8c312 (patch)
treec49c7323b12e1c28e3172d08a0c10e74573e28a7 /zebra/rt_netlink.c
parentbgpd: send L3VNI as route labels to zebra (diff)
downloadfrr-5fa6bfffb1201c98960ea8a3808d6e1e7ed8c312.tar.xz
frr-5fa6bfffb1201c98960ea8a3808d6e1e7ed8c312.zip
zebra: encode vni label via lwt encap
Encode the vni label during route install on linux systems via lwt encap 64bit LWTUNNEL_IP_ID. The kernel expects this in network byte order, so we convert it. Signed-off-by: Stephen Worley <sworley@nvidia.com>
Diffstat (limited to '')
-rw-r--r--zebra/rt_netlink.c78
1 files changed, 60 insertions, 18 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index d09318a5a..390c78b7a 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1325,6 +1325,7 @@ static bool _netlink_route_add_gateway_info(uint8_t route_family,
}
static int build_label_stack(struct mpls_label_stack *nh_label,
+ enum lsp_types_t nh_label_type,
mpls_lse_t *out_lse, char *label_buf,
size_t label_buf_size)
{
@@ -1332,7 +1333,8 @@ static int build_label_stack(struct mpls_label_stack *nh_label,
int num_labels = 0;
for (int i = 0; nh_label && i < nh_label->num_labels; i++) {
- if (nh_label->label[i] == MPLS_LABEL_IMPLICIT_NULL)
+ if (nh_label_type == ZEBRA_LSP_EVPN
+ && nh_label->label[i] == MPLS_LABEL_IMPLICIT_NULL)
continue;
if (IS_ZEBRA_DEBUG_KERNEL) {
@@ -1346,15 +1348,18 @@ static int build_label_stack(struct mpls_label_stack *nh_label,
}
}
- out_lse[num_labels] =
- mpls_lse_encode(nh_label->label[i], 0, 0, 0);
+ if (nh_label_type == ZEBRA_LSP_EVPN)
+ out_lse[num_labels] = label2vni(&nh_label->label[i]);
+ else
+ out_lse[num_labels] =
+ mpls_lse_encode(nh_label->label[i], 0, 0, 0);
num_labels++;
}
return num_labels;
}
-static bool _netlink_route_encode_label_info(struct mpls_label_stack *nh_label,
+static bool _netlink_route_encode_label_info(const struct nexthop *nexthop,
struct nlmsghdr *nlmsg,
size_t buflen, struct rtmsg *rtmsg,
char *label_buf,
@@ -1362,6 +1367,12 @@ static bool _netlink_route_encode_label_info(struct mpls_label_stack *nh_label,
{
mpls_lse_t out_lse[MPLS_MAX_LABELS];
int num_labels;
+ struct rtattr *nest;
+ struct mpls_label_stack *nh_label;
+ enum lsp_types_t nh_label_type;
+
+ nh_label = nexthop->nh_label;
+ nh_label_type = nexthop->nh_label_type;
/*
* label_buf is *only* currently used within debugging.
@@ -1371,10 +1382,45 @@ static bool _netlink_route_encode_label_info(struct mpls_label_stack *nh_label,
*/
label_buf[0] = '\0';
- num_labels =
- build_label_stack(nh_label, out_lse, label_buf, label_buf_size);
+ num_labels = build_label_stack(nh_label, nh_label_type, out_lse,
+ label_buf, label_buf_size);
+
+ if (num_labels && nh_label_type == ZEBRA_LSP_EVPN) {
+
+ if (!nl_attr_put16(nlmsg, buflen, RTA_ENCAP_TYPE,
+ LWTUNNEL_ENCAP_IP))
+ return false;
+
+ nest = nl_attr_nest(nlmsg, buflen, RTA_ENCAP);
+ if (!nest)
+ return false;
+
+ if (!nl_attr_put64(nlmsg, buflen, LWTUNNEL_IP_ID,
+ htonll((uint64_t)out_lse[0])))
+ return false;
+
+ if (nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) {
+ if (!nl_attr_put(nlmsg, buflen, LWTUNNEL_IP_DST,
+ &nexthop->gate.ipv4, 4))
+ return false;
- if (num_labels) {
+ } else if (nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
+ if (!nl_attr_put(nlmsg, buflen, LWTUNNEL_IP_DST,
+ &nexthop->gate.ipv6, 16))
+ return false;
+
+ } else {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug(
+ "%s: nexthop %pNHv %s must NEXTHOP_TYPE_IPV*_IFINDEX to be vxlan encapped",
+ __func__, nexthop, label_buf);
+
+ return false;
+ }
+
+ nl_attr_nest_end(nlmsg, nest);
+
+ } else if (num_labels) {
/* Set the BoS bit */
out_lse[num_labels - 1] |= htonl(1 << MPLS_LS_S_SHIFT);
@@ -1383,8 +1429,6 @@ static bool _netlink_route_encode_label_info(struct mpls_label_stack *nh_label,
num_labels * sizeof(mpls_lse_t)))
return false;
} else {
- struct rtattr *nest;
-
if (!nl_attr_put16(nlmsg, buflen, RTA_ENCAP_TYPE,
LWTUNNEL_ENCAP_MPLS))
return false;
@@ -1498,9 +1542,8 @@ static bool _netlink_route_build_singlepath(const struct prefix *p,
vrf = vrf_lookup_by_id(nexthop->vrf_id);
- if (!_netlink_route_encode_label_info(nexthop->nh_label, nlmsg,
- req_size, rtmsg, label_buf,
- sizeof(label_buf)))
+ if (!_netlink_route_encode_label_info(nexthop, nlmsg, req_size, rtmsg,
+ label_buf, sizeof(label_buf)))
return false;
if (nexthop->nh_srv6) {
@@ -1781,9 +1824,8 @@ static bool _netlink_route_build_multipath(
vrf = vrf_lookup_by_id(nexthop->vrf_id);
- if (!_netlink_route_encode_label_info(nexthop->nh_label, nlmsg,
- req_size, rtmsg, label_buf,
- sizeof(label_buf)))
+ if (!_netlink_route_encode_label_info(nexthop, nlmsg, req_size, rtmsg,
+ label_buf, sizeof(label_buf)))
return false;
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
@@ -2665,9 +2707,9 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd,
if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ONLINK))
req->nhm.nh_flags |= RTNH_F_ONLINK;
- num_labels =
- build_label_stack(nh->nh_label, out_lse,
- label_buf, sizeof(label_buf));
+ num_labels = build_label_stack(
+ nh->nh_label, nh->nh_label_type, out_lse,
+ label_buf, sizeof(label_buf));
if (num_labels) {
/* Set the BoS bit */