Skip to content

Commit

Permalink
bgpd: prefix-sid srv6 l3vpn service tlv
Browse files Browse the repository at this point in the history
bgpd already supports BGP Prefix-SID path attribute and
there are some sub-types of Prefix-SID path attribute.
This commits makes bgpd to support additional sub-types.
sub-Type-4 and sub-Type-5 for construct the VPNv4 SRv6 backend
with vpnv4-unicast address family.
This path attributes is already supported by Ciscos IOS-XR and NX-OS.

Prefix-SID sub-Type-4 and sub-Type-5 is defined on following
IETF-drafts.

Supports(A-part-of):
- https://tools.ietf.org/html/draft-dawra-idr-srv6-vpn-04
- https://tools.ietf.org/html/draft-dawra-idr-srv6-vpn-05

Signed-off-by: Hiroki Shirokura <slank.dev@gmail.com>
  • Loading branch information
slankdev committed Jan 15, 2020
1 parent 770df5f commit e496b42
Show file tree
Hide file tree
Showing 10 changed files with 647 additions and 13 deletions.
318 changes: 305 additions & 13 deletions bgpd/bgp_attr.c

Large diffs are not rendered by default.

32 changes: 32 additions & 0 deletions bgpd/bgp_attr.h
Expand Up @@ -62,12 +62,15 @@
#define BGP_PREFIX_SID_LABEL_INDEX 1
#define BGP_PREFIX_SID_IPV6 2
#define BGP_PREFIX_SID_ORIGINATOR_SRGB 3
#define BGP_PREFIX_SID_VPN_SID 4
#define BGP_PREFIX_SID_SRV6_L3_SERVICE 5
#define BGP_PREFIX_SID_SRV6_L2_SERVICE 6

#define BGP_PREFIX_SID_LABEL_INDEX_LENGTH 7
#define BGP_PREFIX_SID_IPV6_LENGTH 19
#define BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH 6
#define BGP_PREFIX_SID_VPN_SID_LENGTH 19
#define BGP_PREFIX_SID_SRV6_L3_SERVICE_LENGTH 21

#define BGP_ATTR_NH_AFI(afi, attr) \
((afi != AFI_L2VPN) ? afi : \
Expand Down Expand Up @@ -111,6 +114,29 @@ enum pta_type {
PMSI_TNLTYPE_MAX = PMSI_TNLTYPE_MLDP_MP2MP
};

/*
* Prefix-SID type-4
* SRv6-VPN-SID-TLV
* draft-dawra-idr-srv6-vpn-04
*/
struct bgp_attr_srv6_vpn {
unsigned long refcnt;
uint8_t sid_flags;
struct in6_addr sid;
};

/*
* Prefix-SID type-5
* SRv6-L3VPN-Service-TLV
* draft-dawra-idr-srv6-vpn-05
*/
struct bgp_attr_srv6_l3vpn {
unsigned long refcnt;
uint8_t sid_flags;
uint16_t endpoint_behavior;
struct in6_addr sid;
};

/* BGP core attribute structure. */
struct attr {
/* AS Path structure */
Expand Down Expand Up @@ -198,6 +224,12 @@ struct attr {
/* MPLS label */
mpls_label_t label;

/* SRv6 VPN SID */
struct bgp_attr_srv6_vpn *srv6_vpn;

/* SRv6 L3VPN SID */
struct bgp_attr_srv6_l3vpn *srv6_l3vpn;

uint16_t encap_tunneltype; /* grr */
struct bgp_attr_encap_subtlv *encap_subtlvs; /* rfc5512 */

Expand Down
3 changes: 3 additions & 0 deletions bgpd/bgp_memory.c
Expand Up @@ -128,3 +128,6 @@ DEFINE_MTYPE(BGPD, BGP_FLOWSPEC_RULE_STR, "BGP flowspec rule str")
DEFINE_MTYPE(BGPD, BGP_FLOWSPEC_COMPILED, "BGP flowspec compiled")
DEFINE_MTYPE(BGPD, BGP_FLOWSPEC_NAME, "BGP flowspec name")
DEFINE_MTYPE(BGPD, BGP_FLOWSPEC_INDEX, "BGP flowspec index")

DEFINE_MTYPE(BGPD, BGP_SRV6_L3VPN, "BGP prefix-sid srv6 l3vpn servcie")
DEFINE_MTYPE(BGPD, BGP_SRV6_VPN, "BGP prefix-sid srv6 vpn service")
3 changes: 3 additions & 0 deletions bgpd/bgp_memory.h
Expand Up @@ -126,4 +126,7 @@ DECLARE_MTYPE(BGP_FLOWSPEC_COMPILED)
DECLARE_MTYPE(BGP_FLOWSPEC_NAME)
DECLARE_MTYPE(BGP_FLOWSPEC_INDEX)

DECLARE_MTYPE(BGP_SRV6_L3VPN)
DECLARE_MTYPE(BGP_SRV6_VPN)

#endif /* _QUAGGA_BGP_MEMORY_H */
38 changes: 38 additions & 0 deletions bgpd/bgp_route.c
Expand Up @@ -38,6 +38,7 @@
#include "workqueue.h"
#include "queue.h"
#include "memory.h"
#include "srv6.h"
#include "lib/json.h"
#include "lib_errors.h"

Expand Down Expand Up @@ -3431,6 +3432,22 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
bgp_set_valid_label(&extra->label[0]);
}

/* Update SRv6 SID */
if (attr->srv6_l3vpn) {
extra = bgp_path_info_extra_get(pi);
if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
sid_copy(&extra->sid[0],
&attr->srv6_l3vpn->sid);
extra->num_sids = 1;
}
} else if (attr->srv6_vpn) {
extra = bgp_path_info_extra_get(pi);
if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
extra->num_sids = 1;
}
}

#if ENABLE_BGP_VNC
if ((afi == AFI_IP || afi == AFI_IP6)
&& (safi == SAFI_UNICAST)) {
Expand Down Expand Up @@ -3610,6 +3627,18 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
bgp_set_valid_label(&extra->label[0]);
}

/* Update SRv6 SID */
if (safi == SAFI_MPLS_VPN) {
extra = bgp_path_info_extra_get(new);
if (attr->srv6_l3vpn) {
sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
extra->num_sids = 1;
} else if (attr->srv6_vpn) {
sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
extra->num_sids = 1;
}
}

/* Update Overlay Index */
if (afi == AFI_L2VPN) {
overlay_index_update(new->attr,
Expand Down Expand Up @@ -8994,6 +9023,15 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
vty_out(vty, " Remote label: %d\n", label);
}

/* Remote SID */
if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
if (json_paths)
json_object_string_add(json_path, "remoteSid", buf);
else
vty_out(vty, " Remote SID: %s\n", buf);
}

/* Label Index */
if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
if (json_paths)
Expand Down
7 changes: 7 additions & 0 deletions bgpd/bgp_route.h
Expand Up @@ -78,6 +78,9 @@ enum bgp_show_adj_route_type {
*/
#define BGP_MAX_LABELS 2

/* Maximum number of sids we can process or send with a prefix. */
#define BGP_MAX_SIDS 6

/* Error codes for handling NLRI */
#define BGP_NLRI_PARSE_OK 0
#define BGP_NLRI_PARSE_ERROR_PREFIX_OVERFLOW -1
Expand Down Expand Up @@ -118,6 +121,10 @@ struct bgp_path_info_extra {
uint16_t af_flags;
#define BGP_EVPN_MACIP_TYPE_SVI_IP (1 << 0)

/* SRv6 SID(s) for SRv6-VPN */
struct in6_addr sid[BGP_MAX_SIDS];
uint32_t num_sids;

#if ENABLE_BGP_VNC
union {

Expand Down
8 changes: 8 additions & 0 deletions bgpd/rfapi/rfapi_vty.c
Expand Up @@ -431,6 +431,14 @@ void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p,
else
vty_out(vty, " label=%u",
decode_label(&bpi->extra->label[0]));

if (bpi->extra->num_sids) {
char buf[BUFSIZ];

vty_out(vty, " sid=%s",
inet_ntop(AF_INET6, &bpi->extra->sid[0], buf,
sizeof(buf)));
}
}

if (!rfapiGetVncLifetime(bpi->attr, &lifetime)) {
Expand Down
116 changes: 116 additions & 0 deletions lib/srv6.c
@@ -0,0 +1,116 @@
/*
* SRv6 definitions
* Copyright (C) 2020 Hiroki Shirokura, LINE Corporation
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "srv6.h"
#include "log.h"

const char *seg6local_action2str(uint32_t action)
{
switch (action) {
case ZEBRA_SEG6_LOCAL_ACTION_END:
return "End";
case ZEBRA_SEG6_LOCAL_ACTION_END_X:
return "End.X";
case ZEBRA_SEG6_LOCAL_ACTION_END_T:
return "End.T";
case ZEBRA_SEG6_LOCAL_ACTION_END_DX2:
return "End.DX2";
case ZEBRA_SEG6_LOCAL_ACTION_END_DX6:
return "End.DX6";
case ZEBRA_SEG6_LOCAL_ACTION_END_DX4:
return "End.DX4";
case ZEBRA_SEG6_LOCAL_ACTION_END_DT6:
return "End.DT6";
case ZEBRA_SEG6_LOCAL_ACTION_END_DT4:
return "End.DT4";
case ZEBRA_SEG6_LOCAL_ACTION_END_B6:
return "End.B6";
case ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP:
return "End.B6.Encap";
case ZEBRA_SEG6_LOCAL_ACTION_END_BM:
return "End.BM";
case ZEBRA_SEG6_LOCAL_ACTION_END_S:
return "End.S";
case ZEBRA_SEG6_LOCAL_ACTION_END_AS:
return "End.AS";
case ZEBRA_SEG6_LOCAL_ACTION_END_AM:
return "End.AM";
case ZEBRA_SEG6_LOCAL_ACTION_UNSPEC:
return "unspec";
default:
return "unknown";
}
}

int snprintf_seg6_segs(char *str,
size_t size, const struct seg6_segs *segs)
{
str[0] = '\0';
for (size_t i = 0; i < segs->num_segs; i++) {
char addr[INET6_ADDRSTRLEN];
bool not_last = (i + 1) < segs->num_segs;

inet_ntop(AF_INET6, &segs->segs[i], addr, sizeof(addr));
strlcat(str, addr, size);
strlcat(str, not_last ? "," : "", size);
}
return strlen(str);
}

const char *seg6local_context2str(char *str, size_t size,
struct seg6local_context *ctx, uint32_t action)
{
char b0[128];

switch (action) {

case ZEBRA_SEG6_LOCAL_ACTION_END:
snprintf(str, size, "USP");
return str;

case ZEBRA_SEG6_LOCAL_ACTION_END_X:
case ZEBRA_SEG6_LOCAL_ACTION_END_DX6:
inet_ntop(AF_INET6, &ctx->nh6, b0, 128);
snprintf(str, size, "nh6 %s", b0);
return str;

case ZEBRA_SEG6_LOCAL_ACTION_END_DX4:
inet_ntop(AF_INET, &ctx->nh4, b0, 128);
snprintf(str, size, "nh4 %s", b0);
return str;

case ZEBRA_SEG6_LOCAL_ACTION_END_T:
case ZEBRA_SEG6_LOCAL_ACTION_END_DT6:
case ZEBRA_SEG6_LOCAL_ACTION_END_DT4:
snprintf(str, size, "table %u", ctx->table);
return str;

case ZEBRA_SEG6_LOCAL_ACTION_END_DX2:
case ZEBRA_SEG6_LOCAL_ACTION_END_B6:
case ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP:
case ZEBRA_SEG6_LOCAL_ACTION_END_BM:
case ZEBRA_SEG6_LOCAL_ACTION_END_S:
case ZEBRA_SEG6_LOCAL_ACTION_END_AS:
case ZEBRA_SEG6_LOCAL_ACTION_END_AM:
case ZEBRA_SEG6_LOCAL_ACTION_UNSPEC:
default:
snprintf(str, size, "unknown(%s)", __func__);
return str;
}
}

0 comments on commit e496b42

Please sign in to comment.