Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zebra: ZEBRA_ROUTE_ADD api supports seg6local route #7680

Closed
wants to merge 9 commits into from
Prev Previous commit
Next Next commit
zebra: ZEBRA_ROUTE_ADD supports seg6local route
With this patch, zclient can intall seg6local rotues whem
they set properties nh_seg6local_{action,ctx} on struct nexthop
and set ZEBRA_FLAG_SEG6LOCAL_ROUTE on zapi_route's flag.

Signed-off-by: Hiroki Shirokura <slank.dev@gmail.com>
  • Loading branch information
slankdev committed Dec 6, 2020
commit 9998a19716f9445863e54849abd8628d78325500
108 changes: 108 additions & 0 deletions zebra/rt_netlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,18 @@

#ifdef HAVE_NETLINK

/* The following definition is to workaround an issue in the Linux kernel
* header files with redefinition of 'struct in6_addr' in both
* netinet/in.h and linux/in6.h.
* Reference - https://sourceware.org/ml/libc-alpha/2013-01/msg00599.html
*/
#define _LINUX_IN6_H

#include <net/if_arp.h>
#include <linux/lwtunnel.h>
#include <linux/mpls_iptunnel.h>
#include <linux/seg6_iptunnel.h>
#include <linux/seg6_local.h>
#include <linux/neighbour.h>
#include <linux/rtnetlink.h>
#include <linux/nexthop.h>
Expand All @@ -38,6 +47,8 @@
#include "if.h"
#include "log.h"
#include "prefix.h"
#include "plist.h"
#include "plist_int.h"
#include "connected.h"
#include "table.h"
#include "memory.h"
Expand Down Expand Up @@ -1269,6 +1280,50 @@ static bool _netlink_route_build_singlepath(const struct prefix *p,
sizeof(label_buf)))
return false;

if (nexthop->nh_seg6local_ctx) {
uint32_t action;
uint16_t encap;
struct rtattr *nest;
const struct seg6local_context *ctx;

ctx = nexthop->nh_seg6local_ctx;
action = nexthop->nh_seg6local_action;
encap = LWTUNNEL_ENCAP_SEG6_LOCAL;
nl_attr_put(nlmsg, req_size, RTA_ENCAP_TYPE, &encap,
sizeof(uint16_t));

nest = nl_attr_nest(nlmsg, req_size, RTA_ENCAP);
switch (nexthop->nh_seg6local_action) {
case ZEBRA_SEG6_LOCAL_ACTION_END:
nl_attr_put32(nlmsg, req_size, SEG6_LOCAL_ACTION,
SEG6_LOCAL_ACTION_END);
break;
case ZEBRA_SEG6_LOCAL_ACTION_END_X:
nl_attr_put32(nlmsg, req_size, SEG6_LOCAL_ACTION,
SEG6_LOCAL_ACTION_END_X);
nl_attr_put(nlmsg, req_size, SEG6_LOCAL_NH6, &ctx->nh6,
sizeof(struct in6_addr));
break;
case ZEBRA_SEG6_LOCAL_ACTION_END_T:
nl_attr_put32(nlmsg, req_size, SEG6_LOCAL_ACTION,
SEG6_LOCAL_ACTION_END_T);
nl_attr_put32(nlmsg, req_size, SEG6_LOCAL_TABLE,
ctx->table);
break;
case ZEBRA_SEG6_LOCAL_ACTION_END_DX4:
nl_attr_put32(nlmsg, req_size, SEG6_LOCAL_ACTION,
SEG6_LOCAL_ACTION_END_DX4);
nl_attr_put(nlmsg, req_size, SEG6_LOCAL_NH4, &ctx->nh4,
sizeof(struct in_addr));
break;
default:
zlog_err("%s: unsupport seg6local behaviour action=%u",
__func__, action);
break;
}
nl_attr_nest_end(nlmsg, nest);
}

if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
rtmsg->rtm_flags |= RTNH_F_ONLINK;

Expand Down Expand Up @@ -2248,6 +2303,59 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd,
nl_attr_nest_end(&req->n, nest);
}

if (nh->nh_seg6local_ctx) {
uint32_t action;
uint16_t encap;
struct rtattr *nest;
const struct seg6local_context *ctx;

req->nhm.nh_family = AF_INET6;
action = nh->nh_seg6local_action;
ctx = nh->nh_seg6local_ctx;
encap = LWTUNNEL_ENCAP_SEG6_LOCAL;
nl_attr_put(&req->n, buflen, NHA_ENCAP_TYPE,
&encap, sizeof(uint16_t));

nest = nl_attr_nest(&req->n, buflen,
NHA_ENCAP | NLA_F_NESTED);
switch (action) {
case SEG6_LOCAL_ACTION_END:
nl_attr_put32(&req->n, buflen,
SEG6_LOCAL_ACTION,
SEG6_LOCAL_ACTION_END);
break;
case SEG6_LOCAL_ACTION_END_X:
nl_attr_put32(&req->n, buflen,
SEG6_LOCAL_ACTION,
SEG6_LOCAL_ACTION_END_X);
nl_attr_put(&req->n, buflen,
SEG6_LOCAL_NH6, &ctx->nh6,
sizeof(struct in6_addr));
break;
case SEG6_LOCAL_ACTION_END_T:
nl_attr_put32(&req->n, buflen,
SEG6_LOCAL_ACTION,
SEG6_LOCAL_ACTION_END_T);
nl_attr_put32(&req->n, buflen,
SEG6_LOCAL_TABLE,
ctx->table);
break;
case SEG6_LOCAL_ACTION_END_DX4:
nl_attr_put32(&req->n, buflen,
SEG6_LOCAL_ACTION,
SEG6_LOCAL_ACTION_END_DX4);
nl_attr_put(&req->n, buflen,
SEG6_LOCAL_NH4, &ctx->nh4,
sizeof(struct in_addr));
break;
default:
zlog_err("%s: unsupport seg6local behaviour action=%u",
__func__, action);
break;
}
nl_attr_nest_end(&req->n, nest);
}

nexthop_done:

if (IS_ZEBRA_DEBUG_KERNEL)
Expand Down
12 changes: 12 additions & 0 deletions zebra/zapi_msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1695,6 +1695,18 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p,
&api_nh->labels[0]);
}

if (CHECK_FLAG(flags, ZEBRA_FLAG_SEG6LOCAL_ROUTE)
&& api_nh->type != NEXTHOP_TYPE_BLACKHOLE) {
if (IS_ZEBRA_DEBUG_RECV)
zlog_debug("%s: adding seg6local action %s",
__func__,
seg6local_action2str(
api_nh->seg6local_action));

nexthop_add_seg6local(nexthop, api_nh->seg6local_action,
&api_nh->seg6local_ctx);
}

if (IS_ZEBRA_DEBUG_RECV) {
labelbuf[0] = '\0';
nhbuf[0] = '\0';
Expand Down
2 changes: 2 additions & 0 deletions zebra/zebra_nhg.c
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,7 @@ static void nhg_ctx_free(struct nhg_ctx **ctx)
nh = nhg_ctx_get_nh(*ctx);

nexthop_del_labels(nh);
nexthop_del_seg6local(nh);

done:
XFREE(MTYPE_NHG_CTX, *ctx);
Expand Down Expand Up @@ -1357,6 +1358,7 @@ static struct nhg_hash_entry *depends_find_singleton(const struct nexthop *nh,

/* The copy may have allocated labels; free them if necessary. */
nexthop_del_labels(&lookup);
nexthop_del_seg6local(&lookup);

if (IS_ZEBRA_DEBUG_NHG_DETAIL)
zlog_debug("%s: nh %pNHv => %p (%u)",
Expand Down
22 changes: 22 additions & 0 deletions zebra/zebra_vty.c
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,16 @@ static void show_route_nexthop_helper(struct vty *vty,
sizeof(buf), 1));
}

if (nexthop->nh_seg6local_ctx) {
seg6local_context2str(buf, sizeof(buf),
nexthop->nh_seg6local_ctx,
nexthop->nh_seg6local_action);
vty_out(vty, ", seg6local %s %s",
seg6local_action2str(
nexthop->nh_seg6local_action),
buf);
}

if (nexthop->weight)
vty_out(vty, ", weight %u", nexthop->weight);

Expand All @@ -622,6 +632,7 @@ static void show_nexthop_json_helper(json_object *json_nexthop,
char buf[SRCDEST2STR_BUFFER];
json_object *json_labels = NULL;
json_object *json_backups = NULL;
json_object *json_seg6local = NULL;
int i;

json_object_int_add(json_nexthop, "flags",
Expand Down Expand Up @@ -799,6 +810,17 @@ static void show_nexthop_json_helper(json_object *json_nexthop,
if (nexthop->srte_color)
json_object_int_add(json_nexthop, "srteColor",
nexthop->srte_color);

if (nexthop->nh_seg6local_ctx) {
json_seg6local = json_object_new_object();
json_object_string_add(
json_seg6local, "action",
seg6local_action2str(
nexthop->nh_seg6local_action));
json_object_object_add(json_nexthop,
"seg6local",
json_seg6local);
}
}

static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
Expand Down