zebra: ZEBRA_ROUTE_ADD supports seg6local route (step1)

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>
This commit is contained in:
Hiroki Shirokura 2020-12-06 08:01:39 +09:00 committed by Mark Stapp
parent cb7775a974
commit 8689b25a08
4 changed files with 151 additions and 0 deletions

View File

@ -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>
@ -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"
@ -1262,6 +1273,52 @@ static bool _netlink_route_build_singlepath(const struct prefix *p,
sizeof(label_buf)))
return false;
if (nexthop->nh_seg6local_ctx) {
struct rtattr *nest;
const struct seg6local_context *ctx;
ctx = nexthop->nh_seg6local_ctx;
nl_attr_put16(nlmsg, req_size, RTA_ENCAP_TYPE,
LWTUNNEL_ENCAP_SEG6_LOCAL);
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;
case ZEBRA_SEG6_LOCAL_ACTION_END_DT6:
nl_attr_put32(nlmsg, req_size, SEG6_LOCAL_ACTION,
SEG6_LOCAL_ACTION_END_DT6);
nl_attr_put32(nlmsg, req_size, SEG6_LOCAL_TABLE,
ctx->table);
break;
default:
zlog_err("%s: unsupport seg6local behaviour action=%u",
__func__, nexthop->nh_seg6local_action);
break;
}
nl_attr_nest_end(nlmsg, nest);
}
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
rtmsg->rtm_flags |= RTNH_F_ONLINK;
@ -2256,6 +2313,67 @@ 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;
case SEG6_LOCAL_ACTION_END_DT6:
nl_attr_put32(&req->n, buflen,
SEG6_LOCAL_ACTION,
SEG6_LOCAL_ACTION_END_DT6);
nl_attr_put32(&req->n, buflen,
SEG6_LOCAL_TABLE,
ctx->table);
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)

View File

@ -1747,6 +1747,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';

View File

@ -1007,6 +1007,7 @@ 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);
@ -1377,6 +1378,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)",

View File

@ -653,6 +653,15 @@ 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);
@ -675,6 +684,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",
@ -852,6 +862,15 @@ 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,