Skip to content

Commit

Permalink
zebra: encode vni label via lwt encap
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
sworleys committed Feb 13, 2023
1 parent 31e1a10 commit 5fa6bff
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 18 deletions.
6 changes: 6 additions & 0 deletions zebra/kernel_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions zebra/kernel_netlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
78 changes: 60 additions & 18 deletions zebra/rt_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -1325,14 +1325,16 @@ 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)
{
char label_buf1[20];
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) {
Expand All @@ -1346,22 +1348,31 @@ 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,
size_t label_buf_size)
{
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.
Expand All @@ -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);

Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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 */
Expand Down

0 comments on commit 5fa6bff

Please sign in to comment.