diff options
author | Dmytro Shytyi <dmytro.shytyi@6wind.com> | 2023-07-26 17:56:32 +0200 |
---|---|---|
committer | Dmytro Shytyi <dmytro.shytyi@6wind.com> | 2023-09-20 15:07:15 +0200 |
commit | f20cf1457d43c3d5f61845ea5db1c1743b29cfbf (patch) | |
tree | 933e0cc401c582be7b63878b1daea96b322a89a7 | |
parent | doc: srv6 multiple segs SIDs documentation (diff) | |
download | frr-f20cf1457d43c3d5f61845ea5db1c1743b29cfbf.tar.xz frr-f20cf1457d43c3d5f61845ea5db1c1743b29cfbf.zip |
bgpd,lib,sharpd,zebra: srv6 introduce multiple segs/SIDs in nexthop
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>
-rw-r--r-- | bgpd/bgp_zebra.c | 13 | ||||
-rw-r--r-- | include/linux/seg6.h | 4 | ||||
-rw-r--r-- | lib/nexthop.c | 33 | ||||
-rw-r--r-- | lib/nexthop.h | 4 | ||||
-rw-r--r-- | lib/srv6.h | 29 | ||||
-rw-r--r-- | lib/zclient.c | 38 | ||||
-rw-r--r-- | lib/zclient.h | 3 | ||||
-rw-r--r-- | sharpd/sharp_vty.c | 2 | ||||
-rw-r--r-- | zebra/rt_netlink.c | 87 | ||||
-rw-r--r-- | zebra/zapi_msg.c | 3 | ||||
-rw-r--r-- | zebra/zebra_nhg.c | 17 | ||||
-rw-r--r-- | zebra/zebra_rnh.c | 49 |
12 files changed, 194 insertions, 88 deletions
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 3d993e12c..9e02f1b55 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -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); diff --git a/include/linux/seg6.h b/include/linux/seg6.h index 329163e4a..5b572ba3d 100644 --- a/include/linux/seg6.h +++ b/include/linux/seg6.h @@ -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) diff --git a/lib/nexthop.c b/lib/nexthop.c index 4f92ef9c8..92fbed5ea 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -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); } } diff --git a/lib/nexthop.h b/lib/nexthop.h index 2be89f824..bed6447d4 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -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); /* diff --git a/lib/srv6.h b/lib/srv6.h index 7c8c6b4a6..fb34f861c 100644 --- a/lib/srv6.h +++ b/lib/srv6.h @@ -14,8 +14,11 @@ #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, diff --git a/lib/zclient.c b/lib/zclient.c index 68a342982..f8f9cf7ab 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -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)); } } diff --git a/lib/zclient.h b/lib/zclient.h index 42c5a5fda..2a3ce4e48 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -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]; }; /* diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index f0a75a5fc..e891c1b6b 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -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, diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 9d8ef00b5..bfe1910a5 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -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, diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 6bed6d872..8a480cfa1 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -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) { diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 3a56bf2a5..9588f65fc 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -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; diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 28b83ce8b..30d92c30f 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -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) |