]> git.puffer.fish Git - mirror/frr.git/commitdiff
bgpd,lib,sharpd,zebra: srv6 introduce multiple segs/SIDs in nexthop
authorDmytro Shytyi <dmytro.shytyi@6wind.com>
Wed, 26 Jul 2023 15:56:32 +0000 (17:56 +0200)
committerDmytro Shytyi <dmytro.shytyi@6wind.com>
Wed, 20 Sep 2023 13:07:15 +0000 (15:07 +0200)
Append zebra and lib to use muliple SRv6 segs SIDs, and keep one
seg SID for bgpd and sharpd.

Note: bgpd and sharpd compilation relies on the lib and zebra files,
i.e if we separate this: lib or zebra or bgpd or sharpd in different
commits - this will not compile.

Signed-off-by: Dmytro Shytyi <dmytro.shytyi@6wind.com>
12 files changed:
bgpd/bgp_zebra.c
include/linux/seg6.h
lib/nexthop.c
lib/nexthop.h
lib/srv6.h
lib/zclient.c
lib/zclient.h
sharpd/sharp_vty.c
zebra/rt_netlink.c
zebra/zapi_msg.c
zebra/zebra_nhg.c
zebra/zebra_rnh.c

index 3d993e12c05476f6457ca02c1865c14180ff2938..9e02f1b5505f694aeb3598e669ffc2b19f7e8748 100644 (file)
@@ -1557,17 +1557,17 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
                api_nh->weight = nh_weight;
 
                if (((mpinfo->attr->srv6_l3vpn &&
-                     !sid_zero(&mpinfo->attr->srv6_l3vpn->sid)) ||
+                     !sid_zero_ipv6(&mpinfo->attr->srv6_l3vpn->sid)) ||
                     (mpinfo->attr->srv6_vpn &&
-                     !sid_zero(&mpinfo->attr->srv6_vpn->sid))) &&
+                     !sid_zero_ipv6(&mpinfo->attr->srv6_vpn->sid))) &&
                    !is_evpn && bgp_is_valid_label(&labels[0])) {
                        struct in6_addr *sid_tmp =
                                mpinfo->attr->srv6_l3vpn
                                        ? (&mpinfo->attr->srv6_l3vpn->sid)
                                        : (&mpinfo->attr->srv6_vpn->sid);
 
-                       memcpy(&api_nh->seg6_segs, sid_tmp,
-                              sizeof(api_nh->seg6_segs));
+                       memcpy(&api_nh->seg6_segs[0], sid_tmp,
+                              sizeof(api_nh->seg6_segs[0]));
 
                        if (mpinfo->attr->srv6_l3vpn &&
                            mpinfo->attr->srv6_l3vpn->transposition_len != 0) {
@@ -1581,13 +1581,14 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
                                        continue;
                                }
 
-                               transpose_sid(&api_nh->seg6_segs, nh_label,
+                               transpose_sid(&api_nh->seg6_segs[0], nh_label,
                                              mpinfo->attr->srv6_l3vpn
                                                      ->transposition_offset,
                                              mpinfo->attr->srv6_l3vpn
                                                      ->transposition_len);
                        }
 
+                       api_nh->seg_num = 1;
                        SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6);
                }
 
@@ -1704,7 +1705,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
                        if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6) &&
                            !CHECK_FLAG(api_nh->flags,
                                        ZAPI_NEXTHOP_FLAG_EVPN)) {
-                               inet_ntop(AF_INET6, &api_nh->seg6_segs,
+                               inet_ntop(AF_INET6, &api_nh->seg6_segs[0],
                                          sid_buf, sizeof(sid_buf));
                                snprintf(segs_buf, sizeof(segs_buf), "segs %s",
                                         sid_buf);
index 329163e4a08d270ec84bc917f94b4e1c9078e105..5b572ba3dbf831f9bb368d6aa90b771c3861b0de 100644 (file)
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+// SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note
 /*
  *  SR-IPv6 implementation
  *
@@ -30,7 +30,7 @@ struct ipv6_sr_hdr {
        __u8    flags;
        __u16   tag;
 
-       struct in6_addr segments[0];
+       struct in6_addr segments[];
 };
 
 #define SR6_FLAG1_PROTECTED    (1 << 6)
index 4f92ef9c8b52fc92483f49337e988afff6882e55..92fbed5eae01ff2a82df3227a6f6356ddf5e0556 100644 (file)
@@ -570,13 +570,15 @@ void nexthop_del_srv6_seg6local(struct nexthop *nexthop)
 
        nexthop->nh_srv6->seg6local_action = ZEBRA_SEG6_LOCAL_ACTION_UNSPEC;
 
-       if (sid_zero(&nexthop->nh_srv6->seg6_segs))
+       if (nexthop->nh_srv6->seg6_segs == NULL)
                XFREE(MTYPE_NH_SRV6, nexthop->nh_srv6);
 }
 
-void nexthop_add_srv6_seg6(struct nexthop *nexthop,
-                          const struct in6_addr *segs)
+void nexthop_add_srv6_seg6(struct nexthop *nexthop, const struct in6_addr *segs,
+                          int num_segs)
 {
+       int i;
+
        if (!segs)
                return;
 
@@ -584,7 +586,22 @@ void nexthop_add_srv6_seg6(struct nexthop *nexthop,
                nexthop->nh_srv6 = XCALLOC(MTYPE_NH_SRV6,
                                           sizeof(struct nexthop_srv6));
 
-       nexthop->nh_srv6->seg6_segs = *segs;
+       /* Enforce limit on srv6 seg stack size */
+       if (num_segs > SRV6_MAX_SIDS)
+               num_segs = SRV6_MAX_SIDS;
+
+       if (!nexthop->nh_srv6->seg6_segs) {
+               nexthop->nh_srv6->seg6_segs =
+                       XCALLOC(MTYPE_NH_SRV6,
+                               sizeof(struct seg6_seg_stack) +
+                                       num_segs * sizeof(struct in6_addr));
+       }
+
+       nexthop->nh_srv6->seg6_segs->num_segs = num_segs;
+
+       for (i = 0; i < num_segs; i++)
+               memcpy(&nexthop->nh_srv6->seg6_segs->seg[i], &segs[i],
+                      sizeof(struct in6_addr));
 }
 
 void nexthop_del_srv6_seg6(struct nexthop *nexthop)
@@ -810,9 +827,13 @@ void nexthop_copy_no_recurse(struct nexthop *copy,
                        nexthop_add_srv6_seg6local(copy,
                                nexthop->nh_srv6->seg6local_action,
                                &nexthop->nh_srv6->seg6local_ctx);
-               if (!sid_zero(&nexthop->nh_srv6->seg6_segs))
+               if (nexthop->nh_srv6->seg6_segs &&
+                   nexthop->nh_srv6->seg6_segs->num_segs &&
+                   !sid_zero(nexthop->nh_srv6->seg6_segs))
                        nexthop_add_srv6_seg6(copy,
-                               &nexthop->nh_srv6->seg6_segs);
+                                             &nexthop->nh_srv6->seg6_segs->seg[0],
+                                             nexthop->nh_srv6->seg6_segs
+                                                     ->num_segs);
        }
 }
 
index 2be89f8240bd384c6523f5f91f230cbefb69e36a..bed6447d49ed8b6a6ddbf38671c767879a5002eb 100644 (file)
@@ -157,8 +157,8 @@ void nexthop_del_labels(struct nexthop *);
 void nexthop_add_srv6_seg6local(struct nexthop *nexthop, uint32_t action,
                                const struct seg6local_context *ctx);
 void nexthop_del_srv6_seg6local(struct nexthop *nexthop);
-void nexthop_add_srv6_seg6(struct nexthop *nexthop,
-                          const struct in6_addr *segs);
+void nexthop_add_srv6_seg6(struct nexthop *nexthop, const struct in6_addr *seg,
+                          int num_segs);
 void nexthop_del_srv6_seg6(struct nexthop *nexthop);
 
 /*
index 7c8c6b4a6596e3a47c00390459d86b4d661bed54..fb34f861c8c2f82386af5f0652d19aa4d409db45 100644 (file)
 #include <arpa/inet.h>
 #include <netinet/in.h>
 
-#define SRV6_MAX_SIDS 16
+#define SRV6_MAX_SIDS    16
+#define SRV6_MAX_SEGS    8
 #define SRV6_LOCNAME_SIZE 256
+#define SRH_BASE_HEADER_LENGTH 8
+#define SRH_SEGMENT_LENGTH     16
 
 #ifdef __cplusplus
 extern "C" {
@@ -74,6 +77,8 @@ enum seg6local_flavor_op {
        ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID    = 4,
 };
 
+#define SRV6_SEG_STRLEN 1024
+
 struct seg6_segs {
        size_t num_segs;
        struct in6_addr segs[256];
@@ -89,6 +94,11 @@ struct seg6local_flavors_info {
        uint8_t lcnode_func_len;
 };
 
+struct seg6_seg_stack {
+       uint8_t num_segs;
+       struct in6_addr seg[0]; /* 1 or more segs */
+};
+
 struct seg6local_context {
        struct in_addr nh4;
        struct in6_addr nh6;
@@ -170,7 +180,7 @@ struct nexthop_srv6 {
        struct seg6local_context seg6local_ctx;
 
        /* SRv6 Headend-behaviour */
-       struct in6_addr seg6_segs;
+       struct seg6_seg_stack *seg6_segs;
 };
 
 static inline const char *seg6_mode2str(enum seg6_mode_t mode)
@@ -206,12 +216,21 @@ static inline bool sid_diff(
        return !sid_same(a, b);
 }
 
-static inline bool sid_zero(
-               const struct in6_addr *a)
+
+static inline bool sid_zero(const struct seg6_seg_stack *a)
+{
+       struct in6_addr zero = {};
+
+       assert(a);
+
+       return sid_same(&a->seg[0], &zero);
+}
+
+static inline bool sid_zero_ipv6(const struct in6_addr *a)
 {
        struct in6_addr zero = {};
 
-       return sid_same(a, &zero);
+       return sid_same(&a[0], &zero);
 }
 
 static inline void *sid_copy(struct in6_addr *dst,
index 68a342982230d2d13f033a5c0b9b1d614b6b36b6..f8f9cf7aba05ea25d9c3a83af2e797ccf85737bc 100644 (file)
@@ -1061,10 +1061,11 @@ int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
                             sizeof(struct seg6local_context));
        }
 
-       if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_SEG6))
-               stream_write(s, &api_nh->seg6_segs,
-                            sizeof(struct in6_addr));
-
+       if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_SEG6)) {
+               stream_putc(s, api_nh->seg_num);
+               stream_put(s, &api_nh->seg6_segs[0],
+                          api_nh->seg_num * sizeof(struct in6_addr));
+       }
 done:
        return ret;
 }
@@ -1430,9 +1431,18 @@ int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh,
                           sizeof(struct seg6local_context));
        }
 
-       if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6))
-               STREAM_GET(&api_nh->seg6_segs, s,
-                          sizeof(struct in6_addr));
+       if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_SEG6)) {
+               STREAM_GETC(s, api_nh->seg_num);
+               if (api_nh->seg_num > SRV6_MAX_SIDS) {
+                       flog_err(EC_LIB_ZAPI_ENCODE,
+                                "%s: invalid number of SRv6 Segs (%u)",
+                                __func__, api_nh->seg_num);
+                       return -1;
+               }
+
+               STREAM_GET(&api_nh->seg6_segs[0], s,
+                          api_nh->seg_num * sizeof(struct in6_addr));
+       }
 
        /* Success */
        ret = 0;
@@ -2132,8 +2142,8 @@ struct nexthop *nexthop_from_zapi_nexthop(const struct zapi_nexthop *znh)
                nexthop_add_srv6_seg6local(n, znh->seg6local_action,
                                           &znh->seg6local_ctx);
 
-       if (!sid_zero(&znh->seg6_segs))
-               nexthop_add_srv6_seg6(n, &znh->seg6_segs);
+       if (znh->seg_num && !sid_zero_ipv6(znh->seg6_segs))
+               nexthop_add_srv6_seg6(n, &znh->seg6_segs[0], znh->seg_num);
 
        return n;
 }
@@ -2193,10 +2203,14 @@ int zapi_nexthop_from_nexthop(struct zapi_nexthop *znh,
                               sizeof(struct seg6local_context));
                }
 
-               if (!sid_zero(&nh->nh_srv6->seg6_segs)) {
+               if (nh->nh_srv6->seg6_segs && nh->nh_srv6->seg6_segs->num_segs &&
+                   !sid_zero(nh->nh_srv6->seg6_segs)) {
                        SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_SEG6);
-                       memcpy(&znh->seg6_segs, &nh->nh_srv6->seg6_segs,
-                              sizeof(struct in6_addr));
+                       znh->seg_num = nh->nh_srv6->seg6_segs->num_segs;
+                       for (i = 0; i < nh->nh_srv6->seg6_segs->num_segs; i++)
+                               memcpy(&znh->seg6_segs[i],
+                                      &nh->nh_srv6->seg6_segs->seg[i],
+                                      sizeof(struct in6_addr));
                }
        }
 
index 42c5a5fdac601a31a760bc9ae0db5b5527525bae..2a3ce4e4880cec30edc36a5bda5f68e40eea784f 100644 (file)
@@ -438,7 +438,8 @@ struct zapi_nexthop {
        struct seg6local_context seg6local_ctx;
 
        /* SRv6 Headend-behaviour */
-       struct in6_addr seg6_segs;
+       int seg_num;
+       struct in6_addr seg6_segs[SRV6_MAX_SEGS];
 };
 
 /*
index f0a75a5fc23a15e501795990df0773f0854fb6ff..e891c1b6be6ae492097275d264f9a3494eb4adf0 100644 (file)
@@ -402,7 +402,7 @@ DEFPY (install_seg6_routes,
        sg.r.nhop.gate.ipv6 = seg6_nh6;
        sg.r.nhop.vrf_id = vrf->vrf_id;
        sg.r.nhop_group.nexthop = &sg.r.nhop;
-       nexthop_add_srv6_seg6(&sg.r.nhop, &seg6_seg);
+       nexthop_add_srv6_seg6(&sg.r.nhop, &seg6_seg, 1);
 
        sg.r.vrf_id = vrf->vrf_id;
        sharp_install_routes_helper(&prefix, sg.r.vrf_id, sg.r.inst, 0,
index 9d8ef00b5276d2d489ff8a8ce1f4a3ed80ad2f14..bfe1910a58052c29ece2b4ec5ad2db03628097b6 100644 (file)
@@ -66,6 +66,7 @@
 #include "zebra/zebra_evpn_mh.h"
 #include "zebra/zebra_trace.h"
 #include "zebra/zebra_neigh.h"
+#include "lib/srv6.h"
 
 #ifndef AF_MPLS
 #define AF_MPLS 28
@@ -77,6 +78,8 @@
 #define BR_SPH_LIST_SIZE 10
 #endif
 
+DEFINE_MTYPE_STATIC(LIB, NH_SRV6, "Nexthop srv6");
+
 static vlanid_t filter_vlan = 0;
 
 /* We capture whether the current kernel supports nexthop ids; by
@@ -476,19 +479,19 @@ static int parse_encap_seg6(struct rtattr *tb, struct in6_addr *segs)
 {
        struct rtattr *tb_encap[SEG6_IPTUNNEL_MAX + 1] = {};
        struct seg6_iptunnel_encap *ipt = NULL;
-       struct in6_addr *segments = NULL;
+       int i;
 
        netlink_parse_rtattr_nested(tb_encap, SEG6_IPTUNNEL_MAX, tb);
 
-       /*
-        * TODO: It's not support multiple SID list.
-        */
        if (tb_encap[SEG6_IPTUNNEL_SRH]) {
                ipt = (struct seg6_iptunnel_encap *)
                        RTA_DATA(tb_encap[SEG6_IPTUNNEL_SRH]);
-               segments = ipt->srh[0].segments;
-               *segs = segments[0];
-               return 1;
+
+               for (i = ipt->srh[0].first_segment; i >= 0; i--)
+                       memcpy(&segs[i], &ipt->srh[0].segments[i],
+                              sizeof(struct in6_addr));
+
+               return ipt->srh[0].first_segment + 1;
        }
 
        return 0;
@@ -506,7 +509,7 @@ parse_nexthop_unicast(ns_id_t ns_id, struct rtmsg *rtm, struct rtattr **tb,
        int num_labels = 0;
        enum seg6local_action_t seg6l_act = ZEBRA_SEG6_LOCAL_ACTION_UNSPEC;
        struct seg6local_context seg6l_ctx = {};
-       struct in6_addr seg6_segs = {};
+       struct in6_addr segs[SRV6_MAX_SIDS] = {};
        int num_segs = 0;
 
        vrf_id_t nh_vrf_id = vrf_id;
@@ -555,7 +558,7 @@ parse_nexthop_unicast(ns_id_t ns_id, struct rtmsg *rtm, struct rtattr **tb,
        if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE]
            && *(uint16_t *)RTA_DATA(tb[RTA_ENCAP_TYPE])
                       == LWTUNNEL_ENCAP_SEG6) {
-               num_segs = parse_encap_seg6(tb[RTA_ENCAP], &seg6_segs);
+               num_segs = parse_encap_seg6(tb[RTA_ENCAP], segs);
        }
 
        if (rtm->rtm_flags & RTNH_F_ONLINK)
@@ -581,7 +584,7 @@ parse_nexthop_unicast(ns_id_t ns_id, struct rtmsg *rtm, struct rtattr **tb,
                nexthop_add_srv6_seg6local(&nh, seg6l_act, &seg6l_ctx);
 
        if (num_segs)
-               nexthop_add_srv6_seg6(&nh, &seg6_segs);
+               nexthop_add_srv6_seg6(&nh, segs, num_segs);
 
        return nh;
 }
@@ -601,7 +604,7 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id,
        int num_labels = 0;
        enum seg6local_action_t seg6l_act = ZEBRA_SEG6_LOCAL_ACTION_UNSPEC;
        struct seg6local_context seg6l_ctx = {};
-       struct in6_addr seg6_segs = {};
+       struct in6_addr segs[SRV6_MAX_SIDS] = {};
        int num_segs = 0;
        struct rtattr *rtnh_tb[RTA_MAX + 1] = {};
 
@@ -657,7 +660,7 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id,
                            && *(uint16_t *)RTA_DATA(rtnh_tb[RTA_ENCAP_TYPE])
                                       == LWTUNNEL_ENCAP_SEG6) {
                                num_segs = parse_encap_seg6(rtnh_tb[RTA_ENCAP],
-                                                          &seg6_segs);
+                                                           segs);
                        }
                }
 
@@ -700,7 +703,7 @@ static uint8_t parse_multipath_nexthops_unicast(ns_id_t ns_id,
                                                           &seg6l_ctx);
 
                        if (num_segs)
-                               nexthop_add_srv6_seg6(nh, &seg6_segs);
+                               nexthop_add_srv6_seg6(nh, segs, num_segs);
 
                        if (rtnh->rtnh_flags & RTNH_F_ONLINK)
                                SET_FLAG(nh->flags, NEXTHOP_FLAG_ONLINK);
@@ -1514,37 +1517,40 @@ static bool _netlink_route_encode_nexthop_src(const struct nexthop *nexthop,
 }
 
 static ssize_t fill_seg6ipt_encap(char *buffer, size_t buflen,
-                                 const struct in6_addr *seg)
+                                 struct seg6_seg_stack *segs)
 {
        struct seg6_iptunnel_encap *ipt;
        struct ipv6_sr_hdr *srh;
-       const size_t srhlen = 24;
+       size_t srhlen;
+       int i;
 
-       /*
-        * Caution: Support only SINGLE-SID, not MULTI-SID
-        * This function only supports the case where segs represents
-        * a single SID. If you want to extend the SRv6 functionality,
-        * you should improve the Boundary Check.
-        * Ex. In case of set a SID-List include multiple-SIDs as an
-        * argument of the Transit Behavior, we must support variable
-        * boundary check for buflen.
-        */
-       if (buflen < (sizeof(struct seg6_iptunnel_encap) +
-                     sizeof(struct ipv6_sr_hdr) + 16))
+       if (segs->num_segs > SRV6_MAX_SEGS) {
+               /* Exceeding maximum supported SIDs */
+               return -1;
+       }
+
+       srhlen = SRH_BASE_HEADER_LENGTH + SRH_SEGMENT_LENGTH * segs->num_segs;
+
+       if (buflen < (sizeof(struct seg6_iptunnel_encap) + srhlen))
                return -1;
 
        memset(buffer, 0, buflen);
 
        ipt = (struct seg6_iptunnel_encap *)buffer;
        ipt->mode = SEG6_IPTUN_MODE_ENCAP;
-       srh = ipt->srh;
+
+       srh = (struct ipv6_sr_hdr *)&ipt->srh;
        srh->hdrlen = (srhlen >> 3) - 1;
        srh->type = 4;
-       srh->segments_left = 0;
-       srh->first_segment = 0;
-       memcpy(&srh->segments[0], seg, sizeof(struct in6_addr));
+       srh->segments_left = segs->num_segs - 1;
+       srh->first_segment = segs->num_segs - 1;
+
+       for (i = 0; i < segs->num_segs; i++) {
+               memcpy(&srh->segments[i], &segs->seg[i],
+                      sizeof(struct in6_addr));
+       }
 
-       return srhlen + 4;
+       return sizeof(struct seg6_iptunnel_encap) + srhlen;
 }
 
 static bool
@@ -1726,7 +1732,9 @@ static bool _netlink_route_build_singlepath(const struct prefix *p,
                        nl_attr_nest_end(nlmsg, nest);
                }
 
-               if (!sid_zero(&nexthop->nh_srv6->seg6_segs)) {
+               if (nexthop->nh_srv6->seg6_segs &&
+                   nexthop->nh_srv6->seg6_segs->num_segs &&
+                   !sid_zero(nexthop->nh_srv6->seg6_segs)) {
                        char tun_buf[4096];
                        ssize_t tun_len;
                        struct rtattr *nest;
@@ -1737,8 +1745,9 @@ static bool _netlink_route_build_singlepath(const struct prefix *p,
                        nest = nl_attr_nest(nlmsg, req_size, RTA_ENCAP);
                        if (!nest)
                                return false;
-                       tun_len = fill_seg6ipt_encap(tun_buf, sizeof(tun_buf),
-                                       &nexthop->nh_srv6->seg6_segs);
+                       tun_len =
+                               fill_seg6ipt_encap(tun_buf, sizeof(tun_buf),
+                                                  nexthop->nh_srv6->seg6_segs);
                        if (tun_len < 0)
                                return false;
                        if (!nl_attr_put(nlmsg, req_size, SEG6_IPTUNNEL_SRH,
@@ -2971,7 +2980,9 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd,
                                        nl_attr_nest_end(&req->n, nest);
                                }
 
-                               if (!sid_zero(&nh->nh_srv6->seg6_segs)) {
+                               if (nh->nh_srv6->seg6_segs &&
+                                   nh->nh_srv6->seg6_segs->num_segs &&
+                                   !sid_zero(nh->nh_srv6->seg6_segs)) {
                                        char tun_buf[4096];
                                        ssize_t tun_len;
                                        struct rtattr *nest;
@@ -2984,9 +2995,9 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd,
                                            NHA_ENCAP | NLA_F_NESTED);
                                        if (!nest)
                                                return 0;
-                                       tun_len = fill_seg6ipt_encap(tun_buf,
-                                           sizeof(tun_buf),
-                                           &nh->nh_srv6->seg6_segs);
+                                       tun_len = fill_seg6ipt_encap(
+                                               tun_buf, sizeof(tun_buf),
+                                               nh->nh_srv6->seg6_segs);
                                        if (tun_len < 0)
                                                return 0;
                                        if (!nl_attr_put(&req->n, buflen,
index 6bed6d87272cb3f4ab897a26390672d8e340b04f..8a480cfa1ca191517a822815846e50f5971cf78e 100644 (file)
@@ -1794,7 +1794,8 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p,
                        if (IS_ZEBRA_DEBUG_RECV)
                                zlog_debug("%s: adding seg6", __func__);
 
-                       nexthop_add_srv6_seg6(nexthop, &api_nh->seg6_segs);
+                       nexthop_add_srv6_seg6(nexthop, &api_nh->seg6_segs[0],
+                                             api_nh->seg_num);
                }
 
                if (IS_ZEBRA_DEBUG_RECV) {
index 3a56bf2a507505a104fbf64bafb49b4e7354edd3..9588f65fc6762797522f452154966636a31ecb50 100644 (file)
@@ -1868,11 +1868,18 @@ static struct nexthop *nexthop_set_resolved(afi_t afi,
                                   labels);
 
        if (nexthop->nh_srv6) {
-               nexthop_add_srv6_seg6local(resolved_hop,
-                                          nexthop->nh_srv6->seg6local_action,
-                                          &nexthop->nh_srv6->seg6local_ctx);
-               nexthop_add_srv6_seg6(resolved_hop,
-                                     &nexthop->nh_srv6->seg6_segs);
+               if (nexthop->nh_srv6->seg6local_action !=
+                   ZEBRA_SEG6_LOCAL_ACTION_UNSPEC)
+                       nexthop_add_srv6_seg6local(resolved_hop,
+                                                  nexthop->nh_srv6
+                                                          ->seg6local_action,
+                                                  &nexthop->nh_srv6
+                                                           ->seg6local_ctx);
+               if (nexthop->nh_srv6->seg6_segs)
+                       nexthop_add_srv6_seg6(resolved_hop,
+                                             &nexthop->nh_srv6->seg6_segs->seg[0],
+                                             nexthop->nh_srv6->seg6_segs
+                                                     ->num_segs);
        }
 
        resolved_hop->rparent = nexthop;
index 28b83ce8b6f6e139f45b47c8a3c0334cbbb95210..30d92c30f4d59386b24643f1e026dd4999f87795 100644 (file)
@@ -1268,6 +1268,7 @@ void show_nexthop_json_helper(json_object *json_nexthop,
        json_object *json_backups = NULL;
        json_object *json_seg6local = NULL;
        json_object *json_seg6 = NULL;
+       json_object *json_segs = NULL;
        int i;
 
        json_object_int_add(json_nexthop, "flags", nexthop->flags);
@@ -1425,11 +1426,31 @@ void show_nexthop_json_helper(json_object *json_nexthop,
                                nexthop->nh_srv6->seg6local_action));
                json_object_object_add(json_nexthop, "seg6local",
                                       json_seg6local);
-
-               json_seg6 = json_object_new_object();
-               json_object_string_addf(json_seg6, "segs", "%pI6",
-                                       &nexthop->nh_srv6->seg6_segs);
-               json_object_object_add(json_nexthop, "seg6", json_seg6);
+               if (nexthop->nh_srv6->seg6_segs &&
+                   nexthop->nh_srv6->seg6_segs->num_segs == 1) {
+                       json_seg6 = json_object_new_object();
+                       json_object_string_addf(json_seg6, "segs", "%pI6",
+                                               &nexthop->nh_srv6->seg6_segs
+                                                        ->seg[0]);
+                       json_object_object_add(json_nexthop, "seg6", json_seg6);
+               } else {
+                       json_segs = json_object_new_array();
+                       if (nexthop->nh_srv6->seg6_segs) {
+                               for (int seg_idx = 0;
+                                    seg_idx <
+                                    nexthop->nh_srv6->seg6_segs->num_segs;
+                                    seg_idx++)
+                                       json_object_array_add(
+                                               json_segs,
+                                               json_object_new_stringf(
+                                                       "%pI6",
+                                                       &nexthop->nh_srv6
+                                                                ->seg6_segs
+                                                                ->seg[seg_idx]));
+                               json_object_object_add(json_nexthop, "seg6",
+                                                      json_segs);
+                       }
+               }
        }
 }
 
@@ -1440,7 +1461,9 @@ void show_route_nexthop_helper(struct vty *vty, const struct route_entry *re,
                               const struct nexthop *nexthop)
 {
        char buf[MPLS_LABEL_STRLEN];
-       int i;
+       char seg_buf[SRV6_SEG_STRLEN];
+       struct seg6_segs segs;
+       uint8_t i;
 
        switch (nexthop->type) {
        case NEXTHOP_TYPE_IPV4:
@@ -1538,9 +1561,17 @@ void show_route_nexthop_helper(struct vty *vty, const struct route_entry *re,
                                seg6local_action2str(
                                        nexthop->nh_srv6->seg6local_action),
                                buf);
-               if (IPV6_ADDR_CMP(&nexthop->nh_srv6->seg6_segs, &in6addr_any))
-                       vty_out(vty, ", seg6 %pI6",
-                               &nexthop->nh_srv6->seg6_segs);
+               if (nexthop->nh_srv6->seg6_segs &&
+                   IPV6_ADDR_CMP(&nexthop->nh_srv6->seg6_segs->seg[0],
+                                 &in6addr_any)) {
+                       segs.num_segs = nexthop->nh_srv6->seg6_segs->num_segs;
+                       for (i = 0; i < segs.num_segs; i++)
+                               memcpy(&segs.segs[i],
+                                      &nexthop->nh_srv6->seg6_segs->seg[i],
+                                      sizeof(struct in6_addr));
+                       snprintf_seg6_segs(seg_buf, SRV6_SEG_STRLEN, &segs);
+                       vty_out(vty, ", seg6 %s", seg_buf);
+               }
        }
 
        if (nexthop->weight)