Skip to content

Commit

Permalink
bgpd,lib,sharpd,zebra: srv6 introduce multiple segs/SIDs in nexthop
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
dmytroshytyi-6WIND committed Sep 20, 2023
1 parent bc6d311 commit f20cf14
Show file tree
Hide file tree
Showing 12 changed files with 194 additions and 88 deletions.
13 changes: 7 additions & 6 deletions bgpd/bgp_zebra.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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);
}

Expand Down Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions include/linux/seg6.h
Original file line number Diff line number Diff line change
@@ -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
*
Expand Down Expand Up @@ -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)
Expand Down
33 changes: 27 additions & 6 deletions lib/nexthop.c
Original file line number Diff line number Diff line change
Expand Up @@ -570,21 +570,38 @@ 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;

if (!nexthop->nh_srv6)
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)
Expand Down Expand Up @@ -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);
}
}

Expand Down
4 changes: 2 additions & 2 deletions lib/nexthop.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/*
Expand Down
29 changes: 24 additions & 5 deletions lib/srv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand Down Expand Up @@ -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];
Expand All @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand Down
38 changes: 26 additions & 12 deletions lib/zclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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));
}
}

Expand Down
3 changes: 2 additions & 1 deletion lib/zclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
};

/*
Expand Down
2 changes: 1 addition & 1 deletion sharpd/sharp_vty.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading

0 comments on commit f20cf14

Please sign in to comment.