From 7c40bf391c1d45e26b4dd342ca5fee1b0ae3fe19 Mon Sep 17 00:00:00 2001 From: jaydom Date: Mon, 23 Jan 2017 10:45:30 +0800 Subject: [PATCH] bgpd: add flowspec feature This work is derived from a work done by China-Telecom. That initial work can be found in [0]. As the gap between frr and quagga is important, a reworks has been done in the meantime. The initial work consists of bringing the following: - Bringing the client side of flowspec. - the enhancement of address-family ipv4/ipv6 flowspec - partial data path handling at reception has been prepared - the support for ipv4 flowspec or ipv6 flowspec in BGP open messages, and the internals of BGP has been done. - the memory contexts necessary for flowspec has been provisioned In addition to this work, the following has been done: - the complement of adaptation for FS safi in bgp code - the code checkstyle has been reworked so as to match frr checkstyle - the processing of IPv6 FS NLRI is prevented - the processing of FS NLRI is stopped ( temporary) [0] https://github.com/chinatelecom-sdn-group/quagga_flowspec/ Signed-off-by: Philippe Guibert Signed-off-by: jaydom --- bgpd/Makefile.am | 4 +- bgpd/bgp_attr.c | 20 +++++++ bgpd/bgp_ecommunity.h | 2 +- bgpd/bgp_flowspec.c | 78 +++++++++++++++++++++++++++ bgpd/bgp_flowspec.h | 27 ++++++++++ bgpd/bgp_flowspec_private.h | 24 +++++++++ bgpd/bgp_memory.c | 7 +++ bgpd/bgp_memory.h | 8 +++ bgpd/bgp_open.c | 11 ++++ bgpd/bgp_packet.c | 7 +++ bgpd/bgp_vty.c | 105 ++++++++++++++++++++++++++++++++---- bgpd/bgp_vty.h | 3 +- bgpd/bgpd.c | 21 ++++++++ bgpd/bgpd.h | 9 ++++ lib/command.c | 10 ++++ lib/command.h | 2 + lib/prefix.c | 2 + lib/zebra.h | 7 ++- 18 files changed, 332 insertions(+), 15 deletions(-) create mode 100644 bgpd/bgp_flowspec.c create mode 100644 bgpd/bgp_flowspec.h create mode 100644 bgpd/bgp_flowspec_private.h diff --git a/bgpd/Makefile.am b/bgpd/Makefile.am index 5e08f82774..84b3e0183c 100644 --- a/bgpd/Makefile.am +++ b/bgpd/Makefile.am @@ -86,7 +86,7 @@ libbgp_a_SOURCES = \ bgp_nht.c bgp_updgrp.c bgp_updgrp_packet.c bgp_updgrp_adv.c bgp_bfd.c \ bgp_encap_tlv.c $(BGP_VNC_RFAPI_SRC) bgp_attr_evpn.c \ bgp_evpn.c bgp_evpn_vty.c bgp_vpn.c bgp_label.c bgp_rd.c \ - bgp_keepalives.c bgp_io.c + bgp_keepalives.c bgp_io.c bgp_flowspec.c noinst_HEADERS = \ bgp_memory.h \ @@ -99,7 +99,7 @@ noinst_HEADERS = \ bgp_updgrp.h bgp_bfd.h bgp_encap_tlv.h bgp_encap_types.h \ $(BGP_VNC_RFAPI_HD) bgp_attr_evpn.h bgp_evpn.h bgp_evpn_vty.h \ bgp_vpn.h bgp_label.h bgp_rd.h bgp_evpn_private.h bgp_keepalives.h \ - bgp_io.h + bgp_io.h bgp_flowspec.h bgp_flowspec_private.h bgpd_SOURCES = bgp_main.c bgpd_LDADD = libbgp.a $(BGP_VNC_RFP_LIB) ../lib/libfrr.la @LIBCAP@ @LIBM@ diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 58788a8959..639365588c 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -52,6 +52,7 @@ #endif #include "bgp_encap_types.h" #include "bgp_evpn.h" +#include "bgp_flowspec_private.h" /* Attribute strings for logging. */ static const struct message attr_str[] = { @@ -1647,6 +1648,13 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args, /* Nexthop length check. */ switch (attr->mp_nexthop_len) { + case 0: + if (safi != SAFI_FLOWSPEC) { + zlog_info("%s: (%s) Wrong multiprotocol next hop length: %d", + __func__, peer->host, attr->mp_nexthop_len); + return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; + } + break; case BGP_ATTR_NHLEN_VPNV4: stream_getl(s); /* RD high */ stream_getl(s); /* RD low */ @@ -2669,6 +2677,8 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi, stream_putc(s, 4); stream_put(s, &attr->mp_nexthop_global_in, 4); break; + case SAFI_FLOWSPEC: + stream_putc(s, 0); /* no nexthop for flowspec */ default: break; } @@ -2719,6 +2729,8 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi, stream_put(s, &attr->mp_nexthop_global, IPV6_MAX_BYTELEN); break; + case SAFI_FLOWSPEC: + stream_putc(s, 0); /* no nexthop for flowspec */ default: break; } @@ -2756,6 +2768,14 @@ void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi, } else if (safi == SAFI_LABELED_UNICAST) { /* Prefix write with label. */ stream_put_labeled_prefix(s, p, label); + } else if (safi == SAFI_FLOWSPEC) { + if (PSIZE (p->prefixlen)+2 < FLOWSPEC_NLRI_SIZELIMIT) + stream_putc(s, PSIZE (p->prefixlen)+2); + else + stream_putw(s, (PSIZE (p->prefixlen)+2)|(0xf<<12)); + stream_putc(s, 2);/* Filter type */ + stream_putc(s, p->prefixlen);/* Prefix length */ + stream_put(s, &p->u.prefix, PSIZE (p->prefixlen)); } else stream_put_prefix_addpath(s, p, addpath_encode, addpath_tx_id); } diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index 4cdb8b8ac8..028b7a3166 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -53,7 +53,7 @@ #define ECOMMUNITY_SIZE 8 /* Extended Communities type flag. */ -#define ECOMMUNITY_FLAG_NON_TRANSITIVE 0x40 +#define ECOMMUNITY_FLAG_NON_TRANSITIVE 0x40 /* Extended Communities attribute. */ struct ecommunity { diff --git a/bgpd/bgp_flowspec.c b/bgpd/bgp_flowspec.c new file mode 100644 index 0000000000..5d61175dce --- /dev/null +++ b/bgpd/bgp_flowspec.c @@ -0,0 +1,78 @@ +/* BGP FlowSpec for packet handling + * Portions: + * Copyright (C) 2017 ChinaTelecom SDN Group + * Copyright (C) 2018 6WIND + * + * FRRouting 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, or (at your option) any + * later version. + * + * FRRouting 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 "math.h" + +#include +#include "prefix.h" + +#include "bgpd/bgpd.h" +#include "bgpd/bgp_route.h" +#include "bgpd/bgp_flowspec.h" +#include "bgpd/bgp_flowspec_private.h" + +int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, + struct bgp_nlri *packet, int withdraw) +{ + uint8_t *pnt; + uint8_t *lim; + afi_t afi; + int psize = 0; + uint8_t rlen; + struct prefix p; + + /* Start processing the NLRI - there may be multiple in the MP_REACH */ + pnt = packet->nlri; + lim = pnt + packet->length; + afi = packet->afi; + + if (afi == AFI_IP6) { + zlog_err("BGP flowspec IPv6 not supported"); + return -1; + } + + if (packet->length >= FLOWSPEC_NLRI_SIZELIMIT) { + zlog_err("BGP flowspec nlri length maximum reached (%u)", + packet->length); + return -1; + } + + for (; pnt < lim; pnt += psize) { + /* Clear prefix structure. */ + memset(&p, 0, sizeof(struct prefix)); + + /* All FlowSpec NLRI begin with length. */ + if (pnt + 1 > lim) + return -1; + + psize = rlen = *pnt++; + + /* When packet overflow occur return immediately. */ + if (pnt + psize > lim) { + zlog_err("Flowspec NLRI length inconsistent ( size %u seen)", + psize); + return -1; + } + /* TODO: validate prefix + * and add to FIB + */ + } + return 0; +} diff --git a/bgpd/bgp_flowspec.h b/bgpd/bgp_flowspec.h new file mode 100644 index 0000000000..bf019da3aa --- /dev/null +++ b/bgpd/bgp_flowspec.h @@ -0,0 +1,27 @@ +/* BGP Flowspec header for packet handling + * Copyright (C) 2018 6WIND + * + * FRRouting 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, or (at your option) any + * later version. + * + * FRRouting 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 + */ + +#ifndef _FRR_BGP_FLOWSPEC_H +#define _FRR_BGP_FLOWSPEC_H + +extern int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, + struct bgp_nlri *packet, int withdraw); + +extern void bgp_flowspec_vty_init(void); + +#endif /* _FRR_BGP_FLOWSPEC_H */ diff --git a/bgpd/bgp_flowspec_private.h b/bgpd/bgp_flowspec_private.h new file mode 100644 index 0000000000..c82bb78519 --- /dev/null +++ b/bgpd/bgp_flowspec_private.h @@ -0,0 +1,24 @@ +/* BGP Flowspec header . private structs and defines + * Copyright (C) 2018 6WIND + * + * FRRouting 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, or (at your option) any + * later version. + * + * FRRouting 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 + */ + +#ifndef _FRR_BGP_FLOWSPEC_PRIVATE_H +#define _FRR_BGP_FLOWSPEC_PRIVATE_H + +#define FLOWSPEC_NLRI_SIZELIMIT 240 + +#endif /* _FRR_BGP_FLOWSPEC_PRIVATE_H */ diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c index 64543ff019..4669fad3b7 100644 --- a/bgpd/bgp_memory.c +++ b/bgpd/bgp_memory.c @@ -119,3 +119,10 @@ DEFINE_MTYPE(BGPD, BGP_EVPN, "BGP EVPN Information") DEFINE_MTYPE(BGPD, BGP_EVPN_IMPORT_RT, "BGP EVPN Import RT") DEFINE_MTYPE(BGPD, BGP_EVPN_VRF_IMPORT_RT, "BGP EVPN VRF Import RT") DEFINE_MTYPE(BGPD, BGP_EVPN_MACIP, "BGP EVPN MAC IP") + +DEFINE_MTYPE(BGPD, BGP_FLOWSPEC, "BGP flowspec") +DEFINE_MTYPE(BGPD, BGP_FLOWSPEC_RULE, "BGP flowspec rule") +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") diff --git a/bgpd/bgp_memory.h b/bgpd/bgp_memory.h index fae98329c6..6fa3040a19 100644 --- a/bgpd/bgp_memory.h +++ b/bgpd/bgp_memory.h @@ -115,4 +115,12 @@ DECLARE_MTYPE(BGP_EVPN) DECLARE_MTYPE(BGP_EVPN_IMPORT_RT) DECLARE_MTYPE(BGP_EVPN_VRF_IMPORT_RT) DECLARE_MTYPE(BGP_EVPN_MACIP) + +DECLARE_MTYPE(BGP_FLOWSPEC) +DECLARE_MTYPE(BGP_FLOWSPEC_RULE) +DECLARE_MTYPE(BGP_FLOWSPEC_RULE_STR) +DECLARE_MTYPE(BGP_FLOWSPEC_COMPILED) +DECLARE_MTYPE(BGP_FLOWSPEC_NAME) +DECLARE_MTYPE(BGP_FLOWSPEC_INDEX) + #endif /* _QUAGGA_BGP_MEMORY_H */ diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 5ec63458f5..aa98f8a557 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -146,6 +146,12 @@ void bgp_capability_vty_out(struct vty *vty, struct peer *peer, "capabilityErrorMultiProtocolSafi", "EVPN"); break; + case SAFI_FLOWSPEC: + json_object_string_add( + json_cap, + "capabilityErrorMultiProtocolSafi", + "flowspec"); + break; default: json_object_int_add( json_cap, @@ -187,6 +193,9 @@ void bgp_capability_vty_out(struct vty *vty, struct peer *peer, case SAFI_ENCAP: vty_out(vty, "SAFI ENCAP"); break; + case SAFI_FLOWSPEC: + vty_out(vty, "SAFI FLOWSPEC"); + break; case SAFI_EVPN: vty_out(vty, "SAFI EVPN"); break; @@ -1166,11 +1175,13 @@ int bgp_open_option_parse(struct peer *peer, uint8_t length, int *mp_capability) && !peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST] && !peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] && !peer->afc_nego[AFI_IP][SAFI_ENCAP] + && !peer->afc_nego[AFI_IP][SAFI_FLOWSPEC] && !peer->afc_nego[AFI_IP6][SAFI_UNICAST] && !peer->afc_nego[AFI_IP6][SAFI_MULTICAST] && !peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST] && !peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] && !peer->afc_nego[AFI_IP6][SAFI_ENCAP] + && !peer->afc_nego[AFI_IP6][SAFI_FLOWSPEC] && !peer->afc_nego[AFI_L2VPN][SAFI_EVPN]) { zlog_err( "%s [Error] Configured AFI/SAFIs do not " diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 3c7bb65fd3..f0b30f0186 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -59,6 +59,7 @@ #include "bgpd/bgp_label.h" #include "bgpd/bgp_io.h" #include "bgpd/bgp_keepalives.h" +#include "bgpd/bgp_flowspec.h" /** * Sets marker and type fields for a BGP message. @@ -302,6 +303,8 @@ int bgp_nlri_parse(struct peer *peer, struct attr *attr, packet); case SAFI_EVPN: return bgp_nlri_parse_evpn(peer, attr, packet, mp_withdraw); + case SAFI_FLOWSPEC: + return bgp_nlri_parse_flowspec(peer, attr, packet, mp_withdraw); } return -1; } @@ -1275,6 +1278,8 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size) peer->afc[AFI_IP][SAFI_MULTICAST]; peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST] = peer->afc[AFI_IP][SAFI_LABELED_UNICAST]; + peer->afc_nego[AFI_IP][SAFI_FLOWSPEC] = + peer->afc[AFI_IP][SAFI_FLOWSPEC]; peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST]; peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = @@ -1283,6 +1288,8 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size) peer->afc[AFI_IP6][SAFI_LABELED_UNICAST]; peer->afc_nego[AFI_L2VPN][SAFI_EVPN] = peer->afc[AFI_L2VPN][SAFI_EVPN]; + peer->afc_nego[AFI_IP6][SAFI_FLOWSPEC] = + peer->afc[AFI_IP6][SAFI_FLOWSPEC]; } /* When collision is detected and this peer is closed. Retrun diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 475a8ea746..a3c7994b1b 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -80,6 +80,8 @@ static enum node_type bgp_node_type(afi_t afi, safi_t safi) case SAFI_MPLS_VPN: return BGP_VPNV4_NODE; break; + case SAFI_FLOWSPEC: + return BGP_FLOWSPECV4_NODE; default: /* not expected */ return BGP_IPV4_NODE; @@ -100,6 +102,8 @@ static enum node_type bgp_node_type(afi_t afi, safi_t safi) case SAFI_MPLS_VPN: return BGP_VPNV6_NODE; break; + case SAFI_FLOWSPEC: + return BGP_FLOWSPECV6_NODE; default: /* not expected */ return BGP_IPV4_NODE; @@ -128,6 +132,7 @@ afi_t bgp_node_afi(struct vty *vty) case BGP_IPV6M_NODE: case BGP_IPV6L_NODE: case BGP_VPNV6_NODE: + case BGP_FLOWSPECV6_NODE: afi = AFI_IP6; break; case BGP_EVPN_NODE: @@ -161,6 +166,10 @@ safi_t bgp_node_safi(struct vty *vty) case BGP_IPV6L_NODE: safi = SAFI_LABELED_UNICAST; break; + case BGP_FLOWSPECV4_NODE: + case BGP_FLOWSPECV6_NODE: + safi = SAFI_FLOWSPEC; + break; default: safi = SAFI_UNICAST; break; @@ -214,6 +223,8 @@ safi_t bgp_vty_safi_from_str(const char *safi_str) safi = SAFI_MPLS_VPN; else if (strmatch(safi_str, "labeled-unicast")) safi = SAFI_LABELED_UNICAST; + else if (strmatch(safi_str, "flowspec")) + safi = SAFI_FLOWSPEC; return safi; } @@ -237,6 +248,10 @@ int argv_find_and_parse_safi(struct cmd_token **argv, int argc, int *index, ret = 1; if (safi) *safi = SAFI_MPLS_VPN; + } else if (argv_find(argv, argc, "flowspec", index)) { + ret = 1; + if (safi) + *safi = SAFI_FLOWSPEC; } return ret; } @@ -6645,11 +6660,11 @@ DEFPY (af_routetarget_import, } DEFUN_NOSH (address_family_ipv4_safi, - address_family_ipv4_safi_cmd, - "address-family ipv4 []", - "Enter Address Family command mode\n" - "Address Family\n" - BGP_SAFI_WITH_LABEL_HELP_STR) + address_family_ipv4_safi_cmd, + "address-family ipv4 []", + "Enter Address Family command mode\n" + "Address Family\n" + BGP_SAFI_WITH_LABEL_HELP_STR) { if (argc == 3) { @@ -6670,11 +6685,11 @@ DEFUN_NOSH (address_family_ipv4_safi, } DEFUN_NOSH (address_family_ipv6_safi, - address_family_ipv6_safi_cmd, - "address-family ipv6 []", - "Enter Address Family command mode\n" - "Address Family\n" - BGP_SAFI_WITH_LABEL_HELP_STR) + address_family_ipv6_safi_cmd, + "address-family ipv6 []", + "Enter Address Family command mode\n" + "Address Family\n" + BGP_SAFI_WITH_LABEL_HELP_STR) { if (argc == 3) { VTY_DECLVAR_CONTEXT(bgp, bgp); @@ -7943,6 +7958,8 @@ const char *afi_safi_print(afi_t afi, safi_t safi) return "IPv4 VPN"; else if (afi == AFI_IP && safi == SAFI_ENCAP) return "IPv4 Encap"; + else if (afi == AFI_IP && safi == SAFI_FLOWSPEC) + return "IPv4 Flowspec"; else if (afi == AFI_IP6 && safi == SAFI_UNICAST) return "IPv6 Unicast"; else if (afi == AFI_IP6 && safi == SAFI_MULTICAST) @@ -7953,6 +7970,8 @@ const char *afi_safi_print(afi_t afi, safi_t safi) return "IPv6 VPN"; else if (afi == AFI_IP6 && safi == SAFI_ENCAP) return "IPv6 Encap"; + else if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC) + return "IPv6 Flowspec"; else if (afi == AFI_L2VPN && safi == SAFI_EVPN) return "L2VPN EVPN"; else @@ -7977,6 +7996,8 @@ const char *afi_safi_json(afi_t afi, safi_t safi) return "ipv4Vpn"; else if (afi == AFI_IP && safi == SAFI_ENCAP) return "ipv4Encap"; + else if (afi == AFI_IP && safi == SAFI_FLOWSPEC) + return "ipv4Flowspec"; else if (afi == AFI_IP6 && safi == SAFI_UNICAST) return "ipv6Unicast"; else if (afi == AFI_IP6 && safi == SAFI_MULTICAST) @@ -7987,6 +8008,8 @@ const char *afi_safi_json(afi_t afi, safi_t safi) return "ipv6Vpn"; else if (afi == AFI_IP6 && safi == SAFI_ENCAP) return "ipv6Encap"; + else if (afi == AFI_IP6 && safi == SAFI_FLOWSPEC) + return "ipv6Flowspec"; else if (afi == AFI_L2VPN && safi == SAFI_EVPN) return "l2VpnEvpn"; else @@ -9001,8 +9024,12 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, uint8_t use_json, || p->afc_recv[AFI_IP6][SAFI_MPLS_VPN] || p->afc_adv[AFI_IP6][SAFI_ENCAP] || p->afc_recv[AFI_IP6][SAFI_ENCAP] + || p->afc_adv[AFI_IP6][SAFI_FLOWSPEC] + || p->afc_recv[AFI_IP6][SAFI_FLOWSPEC] || p->afc_adv[AFI_IP][SAFI_ENCAP] || p->afc_recv[AFI_IP][SAFI_ENCAP] + || p->afc_adv[AFI_IP][SAFI_FLOWSPEC] + || p->afc_recv[AFI_IP][SAFI_FLOWSPEC] || p->afc_adv[AFI_IP][SAFI_MPLS_VPN] || p->afc_recv[AFI_IP][SAFI_MPLS_VPN]) { if (use_json) { @@ -11795,6 +11822,12 @@ static struct cmd_node bgp_evpn_node = {BGP_EVPN_NODE, static struct cmd_node bgp_evpn_vni_node = {BGP_EVPN_VNI_NODE, "%s(config-router-af-vni)# ", 1}; +static struct cmd_node bgp_flowspecv4_node = {BGP_FLOWSPECV4_NODE, + "%s(config-router-af)# ", 1}; + +static struct cmd_node bgp_flowspecv6_node = {BGP_FLOWSPECV6_NODE, + "%s(config-router-af-vpnv6)# ", 1}; + static void community_list_vty(void); static void bgp_ac_neighbor(vector comps, struct cmd_token *token) @@ -11855,6 +11888,8 @@ void bgp_vty_init(void) install_node(&bgp_vpnv6_node, NULL); install_node(&bgp_evpn_node, NULL); install_node(&bgp_evpn_vni_node, NULL); + install_node(&bgp_flowspecv4_node, NULL); + install_node(&bgp_flowspecv6_node, NULL); /* Install default VTY commands to new nodes. */ install_default(BGP_NODE); @@ -11866,6 +11901,8 @@ void bgp_vty_init(void) install_default(BGP_IPV6L_NODE); install_default(BGP_VPNV4_NODE); install_default(BGP_VPNV6_NODE); + install_default(BGP_FLOWSPECV4_NODE); + install_default(BGP_FLOWSPECV6_NODE); install_default(BGP_EVPN_NODE); install_default(BGP_EVPN_VNI_NODE); @@ -12098,6 +12135,8 @@ void bgp_vty_init(void) install_element(BGP_IPV6L_NODE, &neighbor_activate_cmd); install_element(BGP_VPNV4_NODE, &neighbor_activate_cmd); install_element(BGP_VPNV6_NODE, &neighbor_activate_cmd); + install_element(BGP_FLOWSPECV4_NODE, &neighbor_activate_cmd); + install_element(BGP_FLOWSPECV6_NODE, &neighbor_activate_cmd); install_element(BGP_EVPN_NODE, &neighbor_activate_cmd); /* "no neighbor activate" commands. */ @@ -12110,6 +12149,8 @@ void bgp_vty_init(void) install_element(BGP_IPV6L_NODE, &no_neighbor_activate_cmd); install_element(BGP_VPNV4_NODE, &no_neighbor_activate_cmd); install_element(BGP_VPNV6_NODE, &no_neighbor_activate_cmd); + install_element(BGP_FLOWSPECV4_NODE, &no_neighbor_activate_cmd); + install_element(BGP_FLOWSPECV6_NODE, &no_neighbor_activate_cmd); install_element(BGP_EVPN_NODE, &no_neighbor_activate_cmd); /* "neighbor peer-group" set commands. */ @@ -12121,6 +12162,10 @@ void bgp_vty_init(void) install_element(BGP_IPV6L_NODE, &neighbor_set_peer_group_hidden_cmd); install_element(BGP_VPNV4_NODE, &neighbor_set_peer_group_hidden_cmd); install_element(BGP_VPNV6_NODE, &neighbor_set_peer_group_hidden_cmd); + install_element(BGP_FLOWSPECV4_NODE, + &neighbor_set_peer_group_hidden_cmd); + install_element(BGP_FLOWSPECV6_NODE, + &neighbor_set_peer_group_hidden_cmd); /* "no neighbor peer-group unset" commands. */ install_element(BGP_NODE, &no_neighbor_set_peer_group_cmd); @@ -12131,6 +12176,10 @@ void bgp_vty_init(void) install_element(BGP_IPV6L_NODE, &no_neighbor_set_peer_group_hidden_cmd); install_element(BGP_VPNV4_NODE, &no_neighbor_set_peer_group_hidden_cmd); install_element(BGP_VPNV6_NODE, &no_neighbor_set_peer_group_hidden_cmd); + install_element(BGP_FLOWSPECV4_NODE, + &no_neighbor_set_peer_group_hidden_cmd); + install_element(BGP_FLOWSPECV6_NODE, + &no_neighbor_set_peer_group_hidden_cmd); /* "neighbor softreconfiguration inbound" commands.*/ install_element(BGP_NODE, &neighbor_soft_reconfiguration_hidden_cmd); @@ -12151,6 +12200,14 @@ void bgp_vty_init(void) install_element(BGP_VPNV4_NODE, &no_neighbor_soft_reconfiguration_cmd); install_element(BGP_VPNV6_NODE, &neighbor_soft_reconfiguration_cmd); install_element(BGP_VPNV6_NODE, &no_neighbor_soft_reconfiguration_cmd); + install_element(BGP_FLOWSPECV4_NODE, + &neighbor_soft_reconfiguration_cmd); + install_element(BGP_FLOWSPECV4_NODE, + &no_neighbor_soft_reconfiguration_cmd); + install_element(BGP_FLOWSPECV6_NODE, + &neighbor_soft_reconfiguration_cmd); + install_element(BGP_FLOWSPECV6_NODE, + &no_neighbor_soft_reconfiguration_cmd); /* "neighbor attribute-unchanged" commands. */ install_element(BGP_NODE, &neighbor_attr_unchanged_hidden_cmd); @@ -12416,6 +12473,14 @@ void bgp_vty_init(void) install_element(BGP_VPNV6_NODE, &neighbor_route_reflector_client_cmd); install_element(BGP_VPNV6_NODE, &no_neighbor_route_reflector_client_cmd); + install_element(BGP_FLOWSPECV4_NODE, + &neighbor_route_reflector_client_cmd); + install_element(BGP_FLOWSPECV4_NODE, + &no_neighbor_route_reflector_client_cmd); + install_element(BGP_FLOWSPECV6_NODE, + &neighbor_route_reflector_client_cmd); + install_element(BGP_FLOWSPECV6_NODE, + &no_neighbor_route_reflector_client_cmd); install_element(BGP_EVPN_NODE, &neighbor_route_reflector_client_cmd); install_element(BGP_EVPN_NODE, &no_neighbor_route_reflector_client_cmd); @@ -12438,6 +12503,12 @@ void bgp_vty_init(void) install_element(BGP_VPNV4_NODE, &no_neighbor_route_server_client_cmd); install_element(BGP_VPNV6_NODE, &neighbor_route_server_client_cmd); install_element(BGP_VPNV6_NODE, &no_neighbor_route_server_client_cmd); + install_element(BGP_FLOWSPECV4_NODE, &neighbor_route_server_client_cmd); + install_element(BGP_FLOWSPECV4_NODE, + &no_neighbor_route_server_client_cmd); + install_element(BGP_FLOWSPECV6_NODE, &neighbor_route_server_client_cmd); + install_element(BGP_FLOWSPECV6_NODE, + &no_neighbor_route_server_client_cmd); /* "neighbor addpath-tx-all-paths" commands.*/ install_element(BGP_NODE, &neighbor_addpath_tx_all_paths_hidden_cmd); @@ -12665,6 +12736,10 @@ void bgp_vty_init(void) install_element(BGP_VPNV4_NODE, &no_neighbor_prefix_list_cmd); install_element(BGP_VPNV6_NODE, &neighbor_prefix_list_cmd); install_element(BGP_VPNV6_NODE, &no_neighbor_prefix_list_cmd); + install_element(BGP_FLOWSPECV4_NODE, &neighbor_prefix_list_cmd); + install_element(BGP_FLOWSPECV4_NODE, &no_neighbor_prefix_list_cmd); + install_element(BGP_FLOWSPECV6_NODE, &neighbor_prefix_list_cmd); + install_element(BGP_FLOWSPECV6_NODE, &no_neighbor_prefix_list_cmd); /* "neighbor filter-list" commands. */ install_element(BGP_NODE, &neighbor_filter_list_hidden_cmd); @@ -12685,6 +12760,10 @@ void bgp_vty_init(void) install_element(BGP_VPNV4_NODE, &no_neighbor_filter_list_cmd); install_element(BGP_VPNV6_NODE, &neighbor_filter_list_cmd); install_element(BGP_VPNV6_NODE, &no_neighbor_filter_list_cmd); + install_element(BGP_FLOWSPECV4_NODE, &neighbor_filter_list_cmd); + install_element(BGP_FLOWSPECV4_NODE, &no_neighbor_filter_list_cmd); + install_element(BGP_FLOWSPECV6_NODE, &neighbor_filter_list_cmd); + install_element(BGP_FLOWSPECV6_NODE, &no_neighbor_filter_list_cmd); /* "neighbor route-map" commands. */ install_element(BGP_NODE, &neighbor_route_map_hidden_cmd); @@ -12705,6 +12784,10 @@ void bgp_vty_init(void) install_element(BGP_VPNV4_NODE, &no_neighbor_route_map_cmd); install_element(BGP_VPNV6_NODE, &neighbor_route_map_cmd); install_element(BGP_VPNV6_NODE, &no_neighbor_route_map_cmd); + install_element(BGP_FLOWSPECV4_NODE, &neighbor_route_map_cmd); + install_element(BGP_FLOWSPECV4_NODE, &no_neighbor_route_map_cmd); + install_element(BGP_FLOWSPECV6_NODE, &neighbor_route_map_cmd); + install_element(BGP_FLOWSPECV6_NODE, &no_neighbor_route_map_cmd); install_element(BGP_EVPN_NODE, &neighbor_route_map_cmd); install_element(BGP_EVPN_NODE, &no_neighbor_route_map_cmd); @@ -12853,6 +12936,8 @@ void bgp_vty_init(void) install_element(BGP_IPV6L_NODE, &exit_address_family_cmd); install_element(BGP_VPNV4_NODE, &exit_address_family_cmd); install_element(BGP_VPNV6_NODE, &exit_address_family_cmd); + install_element(BGP_FLOWSPECV4_NODE, &exit_address_family_cmd); + install_element(BGP_FLOWSPECV6_NODE, &exit_address_family_cmd); install_element(BGP_EVPN_NODE, &exit_address_family_cmd); /* "clear ip bgp commands" */ diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h index 7a9546e3ef..afb85f112b 100644 --- a/bgpd/bgp_vty.h +++ b/bgpd/bgp_vty.h @@ -36,11 +36,12 @@ struct bgp; #define BGP_AFI_SAFI_CMD_STR BGP_AFI_CMD_STR" "BGP_SAFI_CMD_STR #define BGP_AFI_SAFI_HELP_STR BGP_AFI_HELP_STR BGP_SAFI_HELP_STR -#define BGP_SAFI_WITH_LABEL_CMD_STR "" +#define BGP_SAFI_WITH_LABEL_CMD_STR "" #define BGP_SAFI_WITH_LABEL_HELP_STR \ "Address Family modifier\n" \ "Address Family modifier\n" \ "Address Family modifier\n" \ + "Address Family modifier\n" \ "Address Family modifier\n" extern void bgp_vty_init(void); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 97f0ffcf2c..ad4e7dc34c 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -80,6 +80,8 @@ #include "bgpd/bgp_keepalives.h" #include "bgpd/bgp_io.h" #include "bgpd/bgp_ecommunity.h" +#include "bgpd/bgp_flowspec.h" + DEFINE_MTYPE_STATIC(BGPD, PEER_TX_SHUTDOWN_MSG, "Peer shutdown message (TX)"); DEFINE_QOBJ_TYPE(bgp_master) @@ -1626,6 +1628,8 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified) PEER_FLAG_REFLECTOR_CLIENT); UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_ENCAP], PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_FLOWSPEC], + PEER_FLAG_REFLECTOR_CLIENT); UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_UNICAST], PEER_FLAG_REFLECTOR_CLIENT); UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_MULTICAST], @@ -1636,6 +1640,8 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified) PEER_FLAG_REFLECTOR_CLIENT); UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_ENCAP], PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_FLOWSPEC], + PEER_FLAG_REFLECTOR_CLIENT); UNSET_FLAG(peer->af_flags[AFI_L2VPN][SAFI_EVPN], PEER_FLAG_REFLECTOR_CLIENT); } @@ -3641,11 +3647,13 @@ int peer_active(struct peer *peer) if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST] || peer->afc[AFI_IP][SAFI_LABELED_UNICAST] || peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_ENCAP] + || peer->afc[AFI_IP][SAFI_FLOWSPEC] || peer->afc[AFI_IP6][SAFI_UNICAST] || peer->afc[AFI_IP6][SAFI_MULTICAST] || peer->afc[AFI_IP6][SAFI_LABELED_UNICAST] || peer->afc[AFI_IP6][SAFI_MPLS_VPN] || peer->afc[AFI_IP6][SAFI_ENCAP] + || peer->afc[AFI_IP6][SAFI_FLOWSPEC] || peer->afc[AFI_L2VPN][SAFI_EVPN]) return 1; return 0; @@ -3659,11 +3667,13 @@ int peer_active_nego(struct peer *peer) || peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST] || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN] || peer->afc_nego[AFI_IP][SAFI_ENCAP] + || peer->afc_nego[AFI_IP][SAFI_FLOWSPEC] || peer->afc_nego[AFI_IP6][SAFI_UNICAST] || peer->afc_nego[AFI_IP6][SAFI_MULTICAST] || peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST] || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] || peer->afc_nego[AFI_IP6][SAFI_ENCAP] + || peer->afc_nego[AFI_IP6][SAFI_FLOWSPEC] || peer->afc_nego[AFI_L2VPN][SAFI_EVPN]) return 1; return 0; @@ -7100,6 +7110,8 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi, vty_frame(vty, "ipv4 vpn"); else if (safi == SAFI_ENCAP) vty_frame(vty, "ipv4 encap"); + else if (safi == SAFI_FLOWSPEC) + vty_frame(vty, "ipv4 flowspec"); } else if (afi == AFI_IP6) { if (safi == SAFI_UNICAST) vty_frame(vty, "ipv6 unicast"); @@ -7111,6 +7123,8 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi, vty_frame(vty, "ipv6 vpn"); else if (safi == SAFI_ENCAP) vty_frame(vty, "ipv6 encap"); + else if (safi == SAFI_FLOWSPEC) + vty_frame(vty, "ipv6 flowspec"); } else if (afi == AFI_L2VPN) { if (safi == SAFI_EVPN) vty_frame(vty, "l2vpn evpn"); @@ -7437,6 +7451,9 @@ int bgp_config_write(struct vty *vty) /* ENCAPv4 configuration. */ bgp_config_write_family(vty, bgp, AFI_IP, SAFI_ENCAP); + /* FLOWSPEC v4 configuration. */ + bgp_config_write_family(vty, bgp, AFI_IP, SAFI_FLOWSPEC); + /* IPv6 unicast configuration. */ bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_UNICAST); @@ -7453,6 +7470,9 @@ int bgp_config_write(struct vty *vty) /* ENCAPv6 configuration. */ bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_ENCAP); + /* FLOWSPEC v6 configuration. */ + bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_FLOWSPEC); + /* EVPN configuration. */ bgp_config_write_family(vty, bgp, AFI_L2VPN, SAFI_EVPN); @@ -7610,6 +7630,7 @@ void bgp_init(void) rfapi_init(); #endif bgp_ethernetvpn_init(); + bgp_flowspec_vty_init(); /* Access list initialize. */ access_list_init(); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 10d6e03976..40f887b86d 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -84,6 +84,8 @@ enum bgp_af_index { BGP_AF_L2VPN_EVPN, BGP_AF_IPV4_LBL_UNICAST, BGP_AF_IPV6_LBL_UNICAST, + BGP_AF_IPV4_FLOWSPEC, + BGP_AF_IPV6_FLOWSPEC, BGP_AF_MAX }; @@ -1558,6 +1560,8 @@ static inline int afindex(afi_t afi, safi_t safi) case SAFI_ENCAP: return BGP_AF_IPV4_ENCAP; break; + case SAFI_FLOWSPEC: + return BGP_AF_IPV4_FLOWSPEC; default: return BGP_AF_MAX; break; @@ -1580,6 +1584,8 @@ static inline int afindex(afi_t afi, safi_t safi) case SAFI_ENCAP: return BGP_AF_IPV6_ENCAP; break; + case SAFI_FLOWSPEC: + return BGP_AF_IPV6_FLOWSPEC; default: return BGP_AF_MAX; break; @@ -1616,6 +1622,7 @@ static inline int peer_afi_active_nego(const struct peer *peer, afi_t afi) || peer->afc_nego[afi][SAFI_LABELED_UNICAST] || peer->afc_nego[afi][SAFI_MPLS_VPN] || peer->afc_nego[afi][SAFI_ENCAP] + || peer->afc_nego[afi][SAFI_FLOWSPEC] || peer->afc_nego[afi][SAFI_EVPN]) return 1; return 0; @@ -1628,12 +1635,14 @@ static inline int peer_group_af_configured(struct peer_group *group) if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST] || peer->afc[AFI_IP][SAFI_LABELED_UNICAST] + || peer->afc[AFI_IP][SAFI_FLOWSPEC] || peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_ENCAP] || peer->afc[AFI_IP6][SAFI_UNICAST] || peer->afc[AFI_IP6][SAFI_MULTICAST] || peer->afc[AFI_IP6][SAFI_LABELED_UNICAST] || peer->afc[AFI_IP6][SAFI_MPLS_VPN] || peer->afc[AFI_IP6][SAFI_ENCAP] + || peer->afc[AFI_IP6][SAFI_FLOWSPEC] || peer->afc[AFI_L2VPN][SAFI_EVPN]) return 1; return 0; diff --git a/lib/command.c b/lib/command.c index 5697c1d812..7c7fddeea5 100644 --- a/lib/command.c +++ b/lib/command.c @@ -118,6 +118,10 @@ const char *node_names[] = { "link-params", // LINK_PARAMS_NODE, "bgp evpn vni", // BGP_EVPN_VNI_NODE, "rpki", // RPKI_NODE + "bgp ipv4 flowspec", /* BGP_FLOWSPECV4_NODE + */ + "bgp ipv6 flowspec", /* BGP_FLOWSPECV6_NODE + */ }; /* Command vector which includes some level of command lists. Normally @@ -948,6 +952,8 @@ enum node_type node_parent(enum node_type node) switch (node) { case BGP_VPNV4_NODE: case BGP_VPNV6_NODE: + case BGP_FLOWSPECV4_NODE: + case BGP_FLOWSPECV6_NODE: case BGP_VRF_POLICY_NODE: case BGP_VNC_DEFAULTS_NODE: case BGP_VNC_NVE_GROUP_NODE: @@ -1318,6 +1324,8 @@ void cmd_exit(struct vty *vty) case BGP_IPV4L_NODE: case BGP_VPNV4_NODE: case BGP_VPNV6_NODE: + case BGP_FLOWSPECV4_NODE: + case BGP_FLOWSPECV6_NODE: case BGP_VRF_POLICY_NODE: case BGP_VNC_DEFAULTS_NODE: case BGP_VNC_NVE_GROUP_NODE: @@ -1394,6 +1402,8 @@ DEFUN (config_end, case BGP_VNC_L2_GROUP_NODE: case BGP_VPNV4_NODE: case BGP_VPNV6_NODE: + case BGP_FLOWSPECV4_NODE: + case BGP_FLOWSPECV6_NODE: case BGP_IPV4_NODE: case BGP_IPV4M_NODE: case BGP_IPV4L_NODE: diff --git a/lib/command.h b/lib/command.h index 95d8ee99df..a7fa3a1692 100644 --- a/lib/command.h +++ b/lib/command.h @@ -142,6 +142,8 @@ enum node_type { BGP_EVPN_VNI_NODE, /* BGP EVPN VNI */ RPKI_NODE, /* RPKI node for configuration of RPKI cache server connections.*/ + BGP_FLOWSPECV4_NODE, /* BGP IPv4 FLOWSPEC Address-Family */ + BGP_FLOWSPECV6_NODE, /* BGP IPv6 FLOWSPEC Address-Family */ NODE_TYPE_MAX, /* maximum */ }; diff --git a/lib/prefix.c b/lib/prefix.c index 515b4dcb5e..ed55fac883 100644 --- a/lib/prefix.c +++ b/lib/prefix.c @@ -523,6 +523,8 @@ const char *safi2str(safi_t safi) return "evpn"; case SAFI_LABELED_UNICAST: return "labeled-unicast"; + case SAFI_FLOWSPEC: + return "flowspec"; default: return "unknown"; } diff --git a/lib/zebra.h b/lib/zebra.h index 3887602231..f4f104299d 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -462,7 +462,8 @@ typedef enum { IANA_SAFI_LABELED_UNICAST = 4, IANA_SAFI_ENCAP = 7, IANA_SAFI_EVPN = 70, - IANA_SAFI_MPLS_VPN = 128 + IANA_SAFI_MPLS_VPN = 128, + IANA_SAFI_FLOWSPEC = 133 } iana_safi_t; /* Default Administrative Distance of each protocol. */ @@ -548,6 +549,8 @@ static inline safi_t safi_iana2int(iana_safi_t safi) return SAFI_EVPN; case IANA_SAFI_LABELED_UNICAST: return SAFI_LABELED_UNICAST; + case IANA_SAFI_FLOWSPEC: + return SAFI_FLOWSPEC; default: return SAFI_MAX; } @@ -568,6 +571,8 @@ static inline iana_safi_t safi_int2iana(safi_t safi) return IANA_SAFI_EVPN; case SAFI_LABELED_UNICAST: return IANA_SAFI_LABELED_UNICAST; + case SAFI_FLOWSPEC: + return IANA_SAFI_FLOWSPEC; default: return IANA_SAFI_RESERVED; } -- 2.39.5