]> git.puffer.fish Git - matthieu/frr.git/commitdiff
zebra: ZEBRA_ROUTE_ADD supports seg6local route (step1)
authorHiroki Shirokura <slank.dev@gmail.com>
Sat, 5 Dec 2020 23:01:39 +0000 (08:01 +0900)
committerMark Stapp <mjs@voltanet.io>
Wed, 2 Jun 2021 14:24:47 +0000 (10:24 -0400)
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>
zebra/rt_netlink.c
zebra/zapi_msg.c
zebra/zebra_nhg.c
zebra/zebra_vty.c

index fbf37230c731d22454b63c30fb1a1f4ff7e8425e..54dee7d91187aa3d2f02972db3aecb67e71f167f 100644 (file)
 
 #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)
index 544bb07fbef42fc93e94e3bf8629ff32db99a82c..752738b2145ff7c6cc2cc084e08d6e47701815e4 100644 (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';
index 6b40eae5b7d4cfb2ff836741cf413420fc25cda0..ddd37b4df7d33e2ffb5cdf9e7360799e00fd85d7 100644 (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)",
index 2c2c75c419f19099aacdf035d8a814652fc2bfff..c178ce075c6cd8eaf3a87371c9ac5f2454f74a6a 100644 (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,