From: Hiroki Shirokura Date: Sat, 5 Dec 2020 23:01:39 +0000 (+0900) Subject: zebra: ZEBRA_ROUTE_ADD supports seg6local route (step1) X-Git-Tag: base_8.1~461^2~63 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=8689b25a08134924d8d8c5f009fd4081d11049f2;p=matthieu%2Ffrr.git 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 --- diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index fbf37230c7..54dee7d911 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -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 #include #include +#include +#include #include #include #include @@ -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) diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 544bb07fbe..752738b214 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -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'; diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 6b40eae5b7..ddd37b4df7 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -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)", diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 2c2c75c419..c178ce075c 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -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,