Skip to content

Commit

Permalink
Merge pull request #5653 from slankdev/slankdev-bgpd-support-prefix-s…
Browse files Browse the repository at this point in the history
…id-srv6-l3vpn

bgpd: additional Prefix-SID sub-types for supporting SRv6 l3vpn
  • Loading branch information
donaldsharp committed Feb 4, 2020
2 parents c7a7544 + e496b42 commit 7f1ace0
Show file tree
Hide file tree
Showing 17 changed files with 886 additions and 15 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 */
4 changes: 2 additions & 2 deletions bgpd/bgp_open.c
Expand Up @@ -658,7 +658,7 @@ static int bgp_capability_enhe(struct peer *peer, struct capability_header *hdr)
nh_afi = afi_iana2int(pkt_nh_afi);

if (afi != AFI_IP || nh_afi != AFI_IP6
|| !(safi == SAFI_UNICAST
|| !(safi == SAFI_UNICAST || safi == SAFI_MPLS_VPN
|| safi == SAFI_LABELED_UNICAST)) {
flog_warn(
EC_BGP_CAPABILITY_INVALID_DATA,
Expand Down Expand Up @@ -1435,7 +1435,7 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)
&& peer->su.sa.sa_family == AF_INET6
&& afi == AFI_IP
&& (safi == SAFI_UNICAST
&& (safi == SAFI_UNICAST || safi == SAFI_MPLS_VPN
|| safi == SAFI_LABELED_UNICAST)) {
/* RFC 5549 Extended Next Hop Encoding
*/
Expand Down
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"
#include "zclient.h"
Expand Down Expand Up @@ -3645,6 +3646,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 @@ -3824,6 +3841,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 @@ -9208,6 +9237,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
55 changes: 55 additions & 0 deletions include/linux/seg6.h
@@ -0,0 +1,55 @@
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* SR-IPv6 implementation
*
* Author:
* David Lebrun <david.lebrun@uclouvain.be>
*
*
* 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.
*/

#ifndef _LINUX_SEG6_H
#define _LINUX_SEG6_H

#include <linux/types.h>
#include <linux/in6.h> /* For struct in6_addr. */

/*
* SRH
*/
struct ipv6_sr_hdr {
__u8 nexthdr;
__u8 hdrlen;
__u8 type;
__u8 segments_left;
__u8 first_segment; /* Represents the last_entry field of SRH */
__u8 flags;
__u16 tag;

struct in6_addr segments[0];
};

#define SR6_FLAG1_PROTECTED (1 << 6)
#define SR6_FLAG1_OAM (1 << 5)
#define SR6_FLAG1_ALERT (1 << 4)
#define SR6_FLAG1_HMAC (1 << 3)

#define SR6_TLV_INGRESS 1
#define SR6_TLV_EGRESS 2
#define SR6_TLV_OPAQUE 3
#define SR6_TLV_PADDING 4
#define SR6_TLV_HMAC 5

#define sr_has_hmac(srh) ((srh)->flags & SR6_FLAG1_HMAC)

struct sr6_tlv {
__u8 type;
__u8 len;
__u8 data[0];
};

#endif
33 changes: 33 additions & 0 deletions include/linux/seg6_genl.h
@@ -0,0 +1,33 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _LINUX_SEG6_GENL_H
#define _LINUX_SEG6_GENL_H

#define SEG6_GENL_NAME "SEG6"
#define SEG6_GENL_VERSION 0x1

enum {
SEG6_ATTR_UNSPEC,
SEG6_ATTR_DST,
SEG6_ATTR_DSTLEN,
SEG6_ATTR_HMACKEYID,
SEG6_ATTR_SECRET,
SEG6_ATTR_SECRETLEN,
SEG6_ATTR_ALGID,
SEG6_ATTR_HMACINFO,
__SEG6_ATTR_MAX,
};

#define SEG6_ATTR_MAX (__SEG6_ATTR_MAX - 1)

enum {
SEG6_CMD_UNSPEC,
SEG6_CMD_SETHMAC,
SEG6_CMD_DUMPHMAC,
SEG6_CMD_SET_TUNSRC,
SEG6_CMD_GET_TUNSRC,
__SEG6_CMD_MAX,
};

#define SEG6_CMD_MAX (__SEG6_CMD_MAX - 1)

#endif
23 changes: 23 additions & 0 deletions include/linux/seg6_hmac.h
@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _LINUX_SEG6_HMAC_H
#define _LINUX_SEG6_HMAC_H

#include <linux/types.h>
#include <linux/seg6.h>

#define SEG6_HMAC_SECRET_LEN 64
#define SEG6_HMAC_FIELD_LEN 32

struct sr6_tlv_hmac {
struct sr6_tlv tlvhdr;
__u16 reserved;
__be32 hmackeyid;
__u8 hmac[SEG6_HMAC_FIELD_LEN];
};

enum {
SEG6_HMAC_ALGO_SHA1 = 1,
SEG6_HMAC_ALGO_SHA256 = 2,
};

#endif
41 changes: 41 additions & 0 deletions include/linux/seg6_iptunnel.h
@@ -0,0 +1,41 @@
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* SR-IPv6 implementation
*
* Author:
* David Lebrun <david.lebrun@uclouvain.be>
*
*
* 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.
*/

#ifndef _LINUX_SEG6_IPTUNNEL_H
#define _LINUX_SEG6_IPTUNNEL_H

#include <linux/seg6.h> /* For struct ipv6_sr_hdr. */

enum {
SEG6_IPTUNNEL_UNSPEC,
SEG6_IPTUNNEL_SRH,
__SEG6_IPTUNNEL_MAX,
};
#define SEG6_IPTUNNEL_MAX (__SEG6_IPTUNNEL_MAX - 1)

struct seg6_iptunnel_encap {
int mode;
struct ipv6_sr_hdr srh[0];
};

#define SEG6_IPTUN_ENCAP_SIZE(x) ((sizeof(*x)) + (((x)->srh->hdrlen + 1) << 3))

enum {
SEG6_IPTUN_MODE_INLINE,
SEG6_IPTUN_MODE_ENCAP,
SEG6_IPTUN_MODE_L2ENCAP,
};


#endif

0 comments on commit 7f1ace0

Please sign in to comment.