]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: encode vni label via lwt encap
authorStephen Worley <sworley@nvidia.com>
Thu, 1 Apr 2021 15:50:31 +0000 (11:50 -0400)
committerStephen Worley <sworley@nvidia.com>
Mon, 13 Feb 2023 23:12:05 +0000 (18:12 -0500)
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>
zebra/kernel_netlink.c
zebra/kernel_netlink.h
zebra/rt_netlink.c

index 42afe61469d4f3ce96a7143d93bfed124a0fff13..0c453507004f3ef8b52c6a443d5f8e28e3468521 100644 (file)
@@ -705,6 +705,12 @@ bool nl_attr_put32(struct nlmsghdr *n, unsigned int maxlen, int type,
        return nl_attr_put(n, maxlen, type, &data, sizeof(uint32_t));
 }
 
+bool nl_attr_put64(struct nlmsghdr *n, unsigned int maxlen, int type,
+                  uint64_t data)
+{
+       return nl_attr_put(n, maxlen, type, &data, sizeof(uint64_t));
+}
+
 struct rtattr *nl_attr_nest(struct nlmsghdr *n, unsigned int maxlen, int type)
 {
        struct rtattr *nest = NLMSG_TAIL(n);
index 08cd706a9f17b1015f30125878bee16421ecc418..ad6e639b423125f5c2d20decf44a9825c7a7066b 100644 (file)
@@ -48,6 +48,8 @@ extern bool nl_attr_put16(struct nlmsghdr *n, unsigned int maxlen, int type,
                          uint16_t data);
 extern bool nl_attr_put32(struct nlmsghdr *n, unsigned int maxlen, int type,
                          uint32_t data);
+extern bool nl_attr_put64(struct nlmsghdr *n, unsigned int maxlen, int type,
+                         uint64_t data);
 
 /*
  * nl_attr_nest - start an attribute nest.
index d09318a5a52a5b69dd86b4a1e5262025ccb03d23..390c78b7acd96db73b935aafb251debe3e54c3f0 100644 (file)
@@ -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 */