From 0168c289357c503f0b03fae84afa87a0b6c2464c Mon Sep 17 00:00:00 2001 From: Satoshi Fujimoto Date: Tue, 9 May 2017 16:09:59 +0900 Subject: BGPSpeaker: Support IPv6 Flow Spec update messages Signed-off-by: Satoshi Fujimoto Signed-off-by: FUJITA Tomonori --- ryu/services/protocols/bgp/api/prefix.py | 9 +++ ryu/services/protocols/bgp/base.py | 2 + ryu/services/protocols/bgp/bgp_sample_conf.py | 64 ++++++++++++++++++++++ ryu/services/protocols/bgp/bgpspeaker.py | 38 ++++++++++++- .../protocols/bgp/core_managers/table_manager.py | 52 ++++++++++++++++++ ryu/services/protocols/bgp/info_base/vrf.py | 11 ++-- ryu/services/protocols/bgp/model.py | 6 +- ryu/services/protocols/bgp/rtconf/base.py | 10 ++++ ryu/services/protocols/bgp/rtconf/neighbors.py | 15 +++++ ryu/services/protocols/bgp/rtconf/vrfs.py | 7 +++ ryu/services/protocols/bgp/utils/bgp.py | 31 +++++++++++ 11 files changed, 237 insertions(+), 8 deletions(-) diff --git a/ryu/services/protocols/bgp/api/prefix.py b/ryu/services/protocols/bgp/api/prefix.py index 1a4207a1..c3e42622 100644 --- a/ryu/services/protocols/bgp/api/prefix.py +++ b/ryu/services/protocols/bgp/api/prefix.py @@ -30,10 +30,13 @@ from ryu.lib.packet.bgp import FlowSpecIPv4NLRI from ryu.lib.packet.bgp import FlowSpecIPv6NLRI from ryu.lib.packet.bgp import FlowSpecVPNv4NLRI from ryu.lib.packet.bgp import FlowSpecVPNv6NLRI +from ryu.lib.packet.bgp import FlowSpecL2VPNNLRI from ryu.lib.packet.bgp import BGPFlowSpecTrafficRateCommunity from ryu.lib.packet.bgp import BGPFlowSpecTrafficActionCommunity from ryu.lib.packet.bgp import BGPFlowSpecRedirectCommunity from ryu.lib.packet.bgp import BGPFlowSpecTrafficMarkingCommunity +from ryu.lib.packet.bgp import BGPFlowSpecVlanActionCommunity +from ryu.lib.packet.bgp import BGPFlowSpecTPIDActionCommunity from ryu.services.protocols.bgp.api.base import EVPN_ROUTE_TYPE from ryu.services.protocols.bgp.api.base import EVPN_ESI @@ -108,11 +111,13 @@ FLOWSPEC_FAMILY_IPV4 = FlowSpecIPv4NLRI.FLOWSPEC_FAMILY FLOWSPEC_FAMILY_IPV6 = FlowSpecIPv6NLRI.FLOWSPEC_FAMILY FLOWSPEC_FAMILY_VPNV4 = FlowSpecVPNv4NLRI.FLOWSPEC_FAMILY FLOWSPEC_FAMILY_VPNV6 = FlowSpecVPNv6NLRI.FLOWSPEC_FAMILY +FLOWSPEC_FAMILY_L2VPN = FlowSpecL2VPNNLRI.FLOWSPEC_FAMILY SUPPORTED_FLOWSPEC_FAMILIES = ( FLOWSPEC_FAMILY_IPV4, FLOWSPEC_FAMILY_IPV6, FLOWSPEC_FAMILY_VPNV4, FLOWSPEC_FAMILY_VPNV6, + FLOWSPEC_FAMILY_L2VPN, ) # Constants for the Traffic Filtering Actions of Flow Specification @@ -121,12 +126,16 @@ FLOWSPEC_ACTION_TRAFFIC_RATE = BGPFlowSpecTrafficRateCommunity.ACTION_NAME FLOWSPEC_ACTION_TRAFFIC_ACTION = BGPFlowSpecTrafficActionCommunity.ACTION_NAME FLOWSPEC_ACTION_REDIRECT = BGPFlowSpecRedirectCommunity.ACTION_NAME FLOWSPEC_ACTION_TRAFFIC_MARKING = BGPFlowSpecTrafficMarkingCommunity.ACTION_NAME +FLOWSPEC_ACTION_VLAN = BGPFlowSpecVlanActionCommunity.ACTION_NAME +FLOWSPEC_ACTION_TPID = BGPFlowSpecTPIDActionCommunity.ACTION_NAME SUPPORTTED_FLOWSPEC_ACTIONS = ( FLOWSPEC_ACTION_TRAFFIC_RATE, FLOWSPEC_ACTION_TRAFFIC_ACTION, FLOWSPEC_ACTION_REDIRECT, FLOWSPEC_ACTION_TRAFFIC_MARKING, + FLOWSPEC_ACTION_VLAN, + FLOWSPEC_ACTION_TPID, ) diff --git a/ryu/services/protocols/bgp/base.py b/ryu/services/protocols/bgp/base.py index 0dc86079..6295ed9e 100644 --- a/ryu/services/protocols/bgp/base.py +++ b/ryu/services/protocols/bgp/base.py @@ -40,6 +40,7 @@ from ryu.lib.packet.bgp import RF_IPv4_FLOWSPEC from ryu.lib.packet.bgp import RF_IPv6_FLOWSPEC from ryu.lib.packet.bgp import RF_VPNv4_FLOWSPEC from ryu.lib.packet.bgp import RF_VPNv6_FLOWSPEC +from ryu.lib.packet.bgp import RF_L2VPN_FLOWSPEC from ryu.lib.packet.bgp import RF_RTC_UC from ryu.services.protocols.bgp.utils.circlist import CircularListType from ryu.services.protocols.bgp.utils.evtlet import LoopingCall @@ -64,6 +65,7 @@ SUPPORTED_GLOBAL_RF = { RF_IPv6_FLOWSPEC, RF_VPNv4_FLOWSPEC, RF_VPNv6_FLOWSPEC, + RF_L2VPN_FLOWSPEC, } diff --git a/ryu/services/protocols/bgp/bgp_sample_conf.py b/ryu/services/protocols/bgp/bgp_sample_conf.py index 3f34fbdc..f18f0f75 100644 --- a/ryu/services/protocols/bgp/bgp_sample_conf.py +++ b/ryu/services/protocols/bgp/bgp_sample_conf.py @@ -5,6 +5,7 @@ from ryu.services.protocols.bgp.bgpspeaker import RF_VPN_V6 from ryu.services.protocols.bgp.bgpspeaker import RF_L2_EVPN from ryu.services.protocols.bgp.bgpspeaker import RF_VPNV4_FLOWSPEC from ryu.services.protocols.bgp.bgpspeaker import RF_VPNV6_FLOWSPEC +from ryu.services.protocols.bgp.bgpspeaker import RF_L2VPN_FLOWSPEC from ryu.services.protocols.bgp.bgpspeaker import EVPN_MAX_ET from ryu.services.protocols.bgp.bgpspeaker import ESI_TYPE_LACP from ryu.services.protocols.bgp.bgpspeaker import ESI_TYPE_MAC_BASED @@ -18,8 +19,16 @@ from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_FAMILY_IPV4 from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_FAMILY_IPV6 from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_FAMILY_VPNV4 from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_FAMILY_VPNV6 +from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_FAMILY_L2VPN from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_TA_SAMPLE from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_TA_TERMINAL +from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_VLAN_POP +from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_VLAN_PUSH +from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_VLAN_SWAP +from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_VLAN_RW_INNER +from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_VLAN_RW_OUTER +from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_TPID_TI +from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_TPID_TO from ryu.services.protocols.bgp.bgpspeaker import REDUNDANCY_MODE_SINGLE_ACTIVE # ============================================================================= @@ -60,6 +69,7 @@ BGP = { 'enable_ipv6fs': True, 'enable_vpnv4fs': True, 'enable_vpnv6fs': True, + 'enable_l2vpnfs': True, }, ], @@ -102,6 +112,13 @@ BGP = { 'export_rts': ['65001:300'], 'route_family': RF_VPNV6_FLOWSPEC, }, + # Example of VRF for L2VPN FlowSpec + { + 'route_dist': '65001:350', + 'import_rts': ['65001:350'], + 'export_rts': ['65001:350'], + 'route_family': RF_L2VPN_FLOWSPEC, + }, ], # List of BGP routes. @@ -319,6 +336,53 @@ BGP = { } }, }, + # Example of Flow Specification L2VPN prefix + { + 'flowspec_family': FLOWSPEC_FAMILY_L2VPN, + 'route_dist': '65001:350', + 'rules': { + 'ether_type': 0x0800, + 'src_mac': '12:34:56:78:90:AB', + 'dst_mac': 'BE:EF:C0:FF:EE:DD', + 'llc_dsap': 0x42, + 'llc_ssap': 0x42, + 'llc_control': 100, + 'snap': 0x12345, + 'vlan_id': '>4000', + 'vlan_cos': '>=3', + 'inner_vlan_id': '<3000', + 'inner_vlan_cos': '<=5', + }, + 'actions': { + 'traffic_rate': { + 'as_number': 0, + 'rate_info': 100.0, + }, + 'traffic_action': { + 'action': FLOWSPEC_TA_SAMPLE | FLOWSPEC_TA_TERMINAL, + }, + 'redirect': { + 'as_number': 10, + 'local_administrator': 100, + }, + 'traffic_marking': { + 'dscp': 24, + }, + 'vlan_action': { + 'actions_1': FLOWSPEC_VLAN_POP | FLOWSPEC_VLAN_PUSH, + 'vlan_1': 3000, + 'cos_1': 3, + 'actions_2': FLOWSPEC_VLAN_SWAP, + 'vlan_2': 4000, + 'cos_2': 2, + }, + 'tpid_action': { + 'actions': FLOWSPEC_TPID_TI | FLOWSPEC_TPID_TO, + 'tpid_1': 200, + 'tpid_2': 300, + } + }, + } ], } diff --git a/ryu/services/protocols/bgp/bgpspeaker.py b/ryu/services/protocols/bgp/bgpspeaker.py index 3c8d6450..c93eacba 100644 --- a/ryu/services/protocols/bgp/bgpspeaker.py +++ b/ryu/services/protocols/bgp/bgpspeaker.py @@ -18,7 +18,11 @@ import netaddr from ryu.lib import hub -from ryu.lib.packet.bgp import BGPFlowSpecTrafficActionCommunity +from ryu.lib.packet.bgp import ( + BGPFlowSpecTrafficActionCommunity, + BGPFlowSpecVlanActionCommunity, + BGPFlowSpecTPIDActionCommunity, +) from ryu.services.protocols.bgp.core_manager import CORE_MANAGER from ryu.services.protocols.bgp.signals.emit import BgpSignalBus @@ -60,6 +64,7 @@ from ryu.services.protocols.bgp.api.prefix import ( FLOWSPEC_FAMILY_VPNV4, FLOWSPEC_FAMILY_IPV6, FLOWSPEC_FAMILY_VPNV6, + FLOWSPEC_FAMILY_L2VPN, FLOWSPEC_RULES, FLOWSPEC_ACTIONS) from ryu.services.protocols.bgp.rtconf.common import LOCAL_AS @@ -87,6 +92,7 @@ from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_IPV4FS from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_IPV6FS from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV4FS from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV6FS +from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_L2VPNFS from ryu.services.protocols.bgp.rtconf.base import CAP_ENHANCED_REFRESH from ryu.services.protocols.bgp.rtconf.base import CAP_FOUR_OCTET_AS_NUMBER from ryu.services.protocols.bgp.rtconf.base import MULTI_EXIT_DISC @@ -101,6 +107,7 @@ from ryu.services.protocols.bgp.rtconf.neighbors import ( DEFAULT_CAP_MBGP_IPV6FS, DEFAULT_CAP_MBGP_VPNV4FS, DEFAULT_CAP_MBGP_VPNV6FS, + DEFAULT_CAP_MBGP_L2VPNFS, ) from ryu.services.protocols.bgp.rtconf.neighbors import ( DEFAULT_CAP_ENHANCED_REFRESH, DEFAULT_CAP_FOUR_OCTET_AS_NUMBER) @@ -131,11 +138,23 @@ RF_VPN_V6 = vrfs.VRF_RF_IPV6 RF_L2_EVPN = vrfs.VRF_RF_L2_EVPN RF_VPNV4_FLOWSPEC = vrfs.VRF_RF_IPV4_FLOWSPEC RF_VPNV6_FLOWSPEC = vrfs.VRF_RF_IPV6_FLOWSPEC +RF_L2VPN_FLOWSPEC = vrfs.VRF_RF_L2VPN_FLOWSPEC # Constants for the Traffic Filtering Actions of Flow Specification. FLOWSPEC_TA_SAMPLE = BGPFlowSpecTrafficActionCommunity.SAMPLE FLOWSPEC_TA_TERMINAL = BGPFlowSpecTrafficActionCommunity.TERMINAL +# Constants for the VLAN Actions of Flow Specification. +FLOWSPEC_VLAN_POP = BGPFlowSpecVlanActionCommunity.POP +FLOWSPEC_VLAN_PUSH = BGPFlowSpecVlanActionCommunity.PUSH +FLOWSPEC_VLAN_SWAP = BGPFlowSpecVlanActionCommunity.SWAP +FLOWSPEC_VLAN_RW_INNER = BGPFlowSpecVlanActionCommunity.REWRITE_INNER +FLOWSPEC_VLAN_RW_OUTER = BGPFlowSpecVlanActionCommunity.REWRITE_OUTER + +# Constants for the TPID Actions of Flow Specification. +FLOWSPEC_TPID_TI = BGPFlowSpecTPIDActionCommunity.TI +FLOWSPEC_TPID_TO = BGPFlowSpecTPIDActionCommunity.TO + class EventPrefix(object): """ @@ -366,6 +385,7 @@ class BGPSpeaker(object): enable_ipv6fs=DEFAULT_CAP_MBGP_IPV6FS, enable_vpnv4fs=DEFAULT_CAP_MBGP_VPNV4FS, enable_vpnv6fs=DEFAULT_CAP_MBGP_VPNV6FS, + enable_l2vpnfs=DEFAULT_CAP_MBGP_L2VPNFS, enable_enhanced_refresh=DEFAULT_CAP_ENHANCED_REFRESH, enable_four_octet_as_number=DEFAULT_CAP_FOUR_OCTET_AS_NUMBER, next_hop=None, password=None, multi_exit_disc=None, @@ -414,6 +434,9 @@ class BGPSpeaker(object): ``enable_vpnv6fs`` enables VPNv6 Flow Specification address family for this neighbor. + ``enable_l2vpnfs`` enables L2VPN Flow Specification address family + for this neighbor. + ``enable_enhanced_refresh`` enables Enhanced Route Refresh for this neighbor. @@ -477,6 +500,7 @@ class BGPSpeaker(object): CAP_MBGP_IPV6FS: enable_ipv6fs, CAP_MBGP_VPNV4FS: enable_vpnv4fs, CAP_MBGP_VPNV6FS: enable_vpnv6fs, + CAP_MBGP_L2VPNFS: enable_l2vpnfs, } if multi_exit_disc: @@ -843,6 +867,7 @@ class BGPSpeaker(object): - FLOWSPEC_FAMILY_IPV6 = 'ipv6fs' - FLOWSPEC_FAMILY_VPNV4 = 'vpnv4fs' - FLOWSPEC_FAMILY_VPNV6 = 'vpnv6fs' + - FLOWSPEC_FAMILY_L2VPN = 'l2vpnfs' ``rules`` specifies NLRIs of Flow Specification as a dictionary type value. @@ -853,6 +878,7 @@ class BGPSpeaker(object): - :py:mod:`ryu.lib.packet.bgp.FlowSpecIPv6NLRI` - :py:mod:`ryu.lib.packet.bgp.FlowSpecVPNv4NLRI` - :py:mod:`ryu.lib.packet.bgp.FlowSpecVPNv6NLRI` + - :py:mod:`ryu.lib.packet.bgp.FlowSpecL2VPNNLRI` ``route_dist`` specifies a route distinguisher value. This parameter is required only if flowspec_family is one of the @@ -860,6 +886,7 @@ class BGPSpeaker(object): - FLOWSPEC_FAMILY_VPNV4 = 'vpnv4fs' - FLOWSPEC_FAMILY_VPNV6 = 'vpnv6fs' + - FLOWSPEC_FAMILY_L2VPN = 'l2vpnfs' ``actions`` specifies Traffic Filtering Actions of Flow Specification as a dictionary type value. @@ -875,6 +902,8 @@ class BGPSpeaker(object): traffic_action :py:mod:`ryu.lib.packet.bgp.BGPFlowSpecTrafficActionCommunity` redirect :py:mod:`ryu.lib.packet.bgp.BGPFlowSpecRedirectCommunity` traffic_marking :py:mod:`ryu.lib.packet.bgp.BGPFlowSpecTrafficMarkingCommunity` + vlan_action :py:mod:`ryu.lib.packet.bgp.BGPFlowSpecVlanActionCommunity` + tpid_action :py:mod:`ryu.lib.packet.bgp.BGPFlowSpecTPIDActionCommunity` =============== =============================================================== Example(IPv4):: @@ -927,7 +956,8 @@ class BGPSpeaker(object): FLOWSPEC_ACTIONS: actions or {}, } - if flowspec_family in [FLOWSPEC_FAMILY_VPNV4, FLOWSPEC_FAMILY_VPNV6]: + if flowspec_family in [FLOWSPEC_FAMILY_VPNV4, FLOWSPEC_FAMILY_VPNV6, + FLOWSPEC_FAMILY_L2VPN]: func_name = 'flowspec.add_local' kwargs.update({ROUTE_DISTINGUISHER: route_dist}) @@ -951,7 +981,8 @@ class BGPSpeaker(object): FLOWSPEC_RULES: rules, } - if flowspec_family in [FLOWSPEC_FAMILY_VPNV4, FLOWSPEC_FAMILY_VPNV6]: + if flowspec_family in [FLOWSPEC_FAMILY_VPNV4, FLOWSPEC_FAMILY_VPNV6, + FLOWSPEC_FAMILY_L2VPN]: func_name = 'flowspec.del_local' kwargs.update({ROUTE_DISTINGUISHER: route_dist}) @@ -978,6 +1009,7 @@ class BGPSpeaker(object): - RF_L2_EVPN = 'evpn' - RF_VPNV4_FLOWSPEC = 'ipv4fs' - RF_VPNV6_FLOWSPEC = 'ipv6fs' + - RF_L2VPN_FLOWSPEC = 'l2vpnfs' ``multi_exit_disc`` specifies multi exit discriminator (MED) value. It must be an integer. diff --git a/ryu/services/protocols/bgp/core_managers/table_manager.py b/ryu/services/protocols/bgp/core_managers/table_manager.py index 27e0bd31..40fe943f 100644 --- a/ryu/services/protocols/bgp/core_managers/table_manager.py +++ b/ryu/services/protocols/bgp/core_managers/table_manager.py @@ -23,14 +23,19 @@ from ryu.services.protocols.bgp.info_base.ipv6fs import IPv6FlowSpecPath from ryu.services.protocols.bgp.info_base.ipv6fs import IPv6FlowSpecTable from ryu.services.protocols.bgp.info_base.vpnv6fs import VPNv6FlowSpecTable from ryu.services.protocols.bgp.info_base.vrf6fs import Vrf6FlowSpecTable +from ryu.services.protocols.bgp.info_base.l2vpnfs import L2VPNFlowSpecTable +from ryu.services.protocols.bgp.info_base.vrfl2vpnfs import L2vpnFlowSpecPath +from ryu.services.protocols.bgp.info_base.vrfl2vpnfs import L2vpnFlowSpecTable from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_IPV4 from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_IPV6 from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_L2_EVPN from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_IPV4_FLOWSPEC from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_IPV6_FLOWSPEC +from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_L2VPN_FLOWSPEC from ryu.services.protocols.bgp.rtconf.vrfs import SUPPORTED_VRF_RF from ryu.services.protocols.bgp.utils.bgp import create_v4flowspec_actions from ryu.services.protocols.bgp.utils.bgp import create_v6flowspec_actions +from ryu.services.protocols.bgp.utils.bgp import create_l2vpnflowspec_actions from ryu.lib import type_desc from ryu.lib.packet.bgp import RF_IPv4_UC @@ -42,6 +47,7 @@ from ryu.lib.packet.bgp import RF_IPv4_FLOWSPEC from ryu.lib.packet.bgp import RF_IPv6_FLOWSPEC from ryu.lib.packet.bgp import RF_VPNv4_FLOWSPEC from ryu.lib.packet.bgp import RF_VPNv6_FLOWSPEC +from ryu.lib.packet.bgp import RF_L2VPN_FLOWSPEC from ryu.lib.packet.bgp import RF_RTC_UC from ryu.lib.packet.bgp import BGPPathAttributeOrigin from ryu.lib.packet.bgp import BGPPathAttributeAsPath @@ -59,6 +65,7 @@ from ryu.lib.packet.bgp import IPAddrPrefix from ryu.lib.packet.bgp import IP6AddrPrefix from ryu.lib.packet.bgp import FlowSpecIPv4NLRI from ryu.lib.packet.bgp import FlowSpecIPv6NLRI +from ryu.lib.packet.bgp import FlowSpecL2VPNNLRI from ryu.services.protocols.bgp.utils.validation import is_valid_ipv4 from ryu.services.protocols.bgp.utils.validation import is_valid_ipv4_prefix @@ -143,6 +150,8 @@ class TableCoreManager(object): vpn_table = self.get_vpnv4fs_table() elif vrf_table.route_family == Vrf6FlowSpecTable.ROUTE_FAMILY: vpn_table = self.get_vpnv6fs_table() + elif vrf_table.route_family == L2vpnFlowSpecTable.ROUTE_FAMILY: + vpn_table = self.get_l2vpnfs_table() else: raise ValueError('Invalid VRF table route family: %s' % vrf_table.route_family) @@ -217,6 +226,8 @@ class TableCoreManager(object): global_table = self.get_vpnv4fs_table() elif route_family == RF_VPNv6_FLOWSPEC: global_table = self.get_vpnv6fs_table() + elif route_family == RF_L2VPN_FLOWSPEC: + global_table = self.get_l2vpnfs_table() elif route_family == RF_RTC_UC: global_table = self.get_rtc_table() @@ -387,6 +398,21 @@ class TableCoreManager(object): return vpnv6fs_table + def get_l2vpnfs_table(self): + """Returns global L2VPN Flow Specification table. + + Creates the table if it does not exist. + """ + l2vpnfs_table = self._global_tables.get(RF_L2VPN_FLOWSPEC) + # Lazy initialization of the table. + if not l2vpnfs_table: + l2vpnfs_table = L2VPNFlowSpecTable(self._core_service, + self._signal_bus) + self._global_tables[RF_L2VPN_FLOWSPEC] = l2vpnfs_table + self._tables[(None, RF_L2VPN_FLOWSPEC)] = l2vpnfs_table + + return l2vpnfs_table + def get_nexthop_label(self, label_key): return self._next_hop_label.get(label_key, None) @@ -470,6 +496,8 @@ class TableCoreManager(object): vrf_table = Vrf4FlowSpecTable elif route_family == VRF_RF_IPV6_FLOWSPEC: vrf_table = Vrf6FlowSpecTable + elif route_family == VRF_RF_L2VPN_FLOWSPEC: + vrf_table = L2vpnFlowSpecTable else: raise ValueError('Unsupported route family for VRF: %s' % route_family) @@ -557,6 +585,8 @@ class TableCoreManager(object): route_family = RF_IPv4_FLOWSPEC elif vpn_path.route_family == RF_VPNv6_FLOWSPEC: route_family = RF_IPv6_FLOWSPEC + elif vpn_path.route_family == RF_L2VPN_FLOWSPEC: + route_family = RF_L2VPN_FLOWSPEC else: raise ValueError('Unsupported route family for VRF: %s' % vpn_path.route_family) @@ -702,6 +732,7 @@ class TableCoreManager(object): from ryu.services.protocols.bgp.api.prefix import ( FLOWSPEC_FAMILY_VPNV4, FLOWSPEC_FAMILY_VPNV6, + FLOWSPEC_FAMILY_L2VPN, ) if flowspec_family == FLOWSPEC_FAMILY_VPNV4: @@ -718,6 +749,13 @@ class TableCoreManager(object): communities = create_v6flowspec_actions(actions) except ValueError as e: raise BgpCoreError(desc=str(e)) + elif flowspec_family == FLOWSPEC_FAMILY_L2VPN: + vrf_table = self._tables.get((route_dist, VRF_RF_L2VPN_FLOWSPEC)) + prefix = FlowSpecL2VPNNLRI.from_user(route_dist, **rules) + try: + communities = create_l2vpnflowspec_actions(actions) + except ValueError as e: + raise BgpCoreError(desc=str(e)) else: raise BgpCoreError( desc='Unsupported flowspec_family %s' % flowspec_family) @@ -794,6 +832,7 @@ class TableCoreManager(object): from ryu.services.protocols.bgp.api.prefix import ( FLOWSPEC_FAMILY_IPV4, FLOWSPEC_FAMILY_IPV6, + FLOWSPEC_FAMILY_L2VPN, ) src_ver_num = 1 @@ -829,6 +868,19 @@ class TableCoreManager(object): except ValueError as e: raise BgpCoreError(desc=str(e)) + if communities: + pathattrs[BGP_ATTR_TYPE_EXTENDED_COMMUNITIES] = ( + BGPPathAttributeExtendedCommunities( + communities=communities)) + elif flowspec_family == FLOWSPEC_FAMILY_L2VPN: + _nlri = FlowSpecL2VPNNLRI.from_user(**rules) + p = L2vpnFlowSpecPath + + try: + communities = create_l2vpnflowspec_actions(actions) + except ValueError as e: + raise BgpCoreError(desc=str(e)) + if communities: pathattrs[BGP_ATTR_TYPE_EXTENDED_COMMUNITIES] = ( BGPPathAttributeExtendedCommunities( diff --git a/ryu/services/protocols/bgp/info_base/vrf.py b/ryu/services/protocols/bgp/info_base/vrf.py index 79940735..8b06c6a1 100644 --- a/ryu/services/protocols/bgp/info_base/vrf.py +++ b/ryu/services/protocols/bgp/info_base/vrf.py @@ -39,7 +39,10 @@ from ryu.lib.packet.bgp import PmsiTunnelIdIngressReplication from ryu.lib.packet.bgp import RF_L2_EVPN from ryu.lib.packet.bgp import EvpnMacIPAdvertisementNLRI from ryu.lib.packet.bgp import EvpnIpPrefixNLRI -from ryu.lib.packet.safi import IP_FLOWSPEC +from ryu.lib.packet.safi import ( + IP_FLOWSPEC, + VPN_FLOWSPEC, +) from ryu.services.protocols.bgp.base import OrderedDict from ryu.services.protocols.bgp.constants import VPN_TABLE @@ -168,7 +171,7 @@ class VrfTable(Table): # Because NLRI class is the same if the route family is EVPN, # we re-use the NLRI instance. vrf_nlri = vpn_path.nlri - elif self.ROUTE_FAMILY.safi == IP_FLOWSPEC: + elif self.ROUTE_FAMILY.safi in [IP_FLOWSPEC, VPN_FLOWSPEC]: vrf_nlri = self.NLRI_CLASS(rules=vpn_path.nlri.rules) else: # self.VPN_ROUTE_FAMILY in [RF_IPv4_VPN, RF_IPv6_VPN] # Copy NLRI instance @@ -526,7 +529,7 @@ class VrfPath(Path): - `label_list`: (list) List of labels for this path. Note: other parameters are as documented in super class. """ - if self.ROUTE_FAMILY.safi == IP_FLOWSPEC: + if self.ROUTE_FAMILY.safi in [IP_FLOWSPEC, VPN_FLOWSPEC]: nexthop = '0.0.0.0' Path.__init__(self, source, nlri, src_ver_num, pattrs, nexthop, @@ -584,7 +587,7 @@ class VrfPath(Path): # we re-use the NLRI instance. vpn_nlri = self._nlri - elif self.ROUTE_FAMILY.safi == IP_FLOWSPEC: + elif self.ROUTE_FAMILY.safi in [IP_FLOWSPEC, VPN_FLOWSPEC]: vpn_nlri = self.VPN_NLRI_CLASS(route_dist=route_dist, rules=self.nlri.rules) diff --git a/ryu/services/protocols/bgp/model.py b/ryu/services/protocols/bgp/model.py index faa33f04..db325580 100644 --- a/ryu/services/protocols/bgp/model.py +++ b/ryu/services/protocols/bgp/model.py @@ -101,11 +101,15 @@ class FlexinetOutgoingRoute(object): Vrf4FlowSpecPath) from ryu.services.protocols.bgp.info_base.vrf6fs import ( Vrf6FlowSpecPath) + from ryu.services.protocols.bgp.info_base.vrfl2vpnfs import ( + L2vpnFlowSpecPath) assert path.route_family in (Vrf4Path.ROUTE_FAMILY, Vrf6Path.ROUTE_FAMILY, VrfEvpnPath.ROUTE_FAMILY, Vrf4FlowSpecPath.ROUTE_FAMILY, - Vrf6FlowSpecPath.ROUTE_FAMILY) + Vrf6FlowSpecPath.ROUTE_FAMILY, + L2vpnFlowSpecPath.ROUTE_FAMILY, + ) self.sink = None self._path = path diff --git a/ryu/services/protocols/bgp/rtconf/base.py b/ryu/services/protocols/bgp/rtconf/base.py index d839d385..c445a87a 100644 --- a/ryu/services/protocols/bgp/rtconf/base.py +++ b/ryu/services/protocols/bgp/rtconf/base.py @@ -50,6 +50,7 @@ CAP_MBGP_IPV4FS = 'cap_mbgp_ipv4fs' CAP_MBGP_IPV6FS = 'cap_mbgp_ipv6fs' CAP_MBGP_VPNV4FS = 'cap_mbgp_vpnv4fs' CAP_MBGP_VPNV6FS = 'cap_mbgp_vpnv6fs' +CAP_MBGP_L2VPNFS = 'cap_mbgp_l2vpnfs' CAP_RTC = 'cap_rtc' RTC_AS = 'rtc_as' HOLD_TIME = 'hold_time' @@ -688,6 +689,15 @@ def validate_cap_mbgp_vpnv66fs(cmv6fs): return cmv6fs +@validate(name=CAP_MBGP_L2VPNFS) +def validate_cap_mbgp_l2vpnfs(cml2fs): + if not isinstance(cml2fs, bool): + raise ConfigTypeError(desc='Invalid MP-BGP ' + 'L2VPN Flow Specification capability ' + 'settings: %s. Boolean value expected' % cml2fs) + return cml2fs + + @validate(name=CAP_RTC) def validate_cap_rtc(cap_rtc): if not isinstance(cap_rtc, bool): diff --git a/ryu/services/protocols/bgp/rtconf/neighbors.py b/ryu/services/protocols/bgp/rtconf/neighbors.py index d99e509a..e4490c19 100644 --- a/ryu/services/protocols/bgp/rtconf/neighbors.py +++ b/ryu/services/protocols/bgp/rtconf/neighbors.py @@ -31,6 +31,7 @@ from ryu.lib.packet.bgp import RF_IPv4_FLOWSPEC from ryu.lib.packet.bgp import RF_IPv6_FLOWSPEC from ryu.lib.packet.bgp import RF_VPNv4_FLOWSPEC from ryu.lib.packet.bgp import RF_VPNv6_FLOWSPEC +from ryu.lib.packet.bgp import RF_L2VPN_FLOWSPEC from ryu.lib.packet.bgp import RF_RTC_UC from ryu.lib.packet.bgp import BGPOptParamCapabilityFourOctetAsNumber from ryu.lib.packet.bgp import BGPOptParamCapabilityEnhancedRouteRefresh @@ -56,6 +57,7 @@ from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_IPV4FS from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_IPV6FS from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV4FS from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV6FS +from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_L2VPNFS from ryu.services.protocols.bgp.rtconf.base import CAP_REFRESH from ryu.services.protocols.bgp.rtconf.base import CAP_RTC from ryu.services.protocols.bgp.rtconf.base import compute_optional_conf @@ -117,6 +119,7 @@ DEFAULT_CAP_MBGP_IPV4FS = False DEFAULT_CAP_MBGP_IPV6FS = False DEFAULT_CAP_MBGP_VPNV4FS = False DEFAULT_CAP_MBGP_VPNV6FS = False +DEFAULT_CAP_MBGP_L2VPNFS = False DEFAULT_HOLD_TIME = 40 DEFAULT_ENABLED = True DEFAULT_CAP_RTC = False @@ -332,6 +335,7 @@ class NeighborConf(ConfWithId, ConfWithStats): CAP_RTC, CAP_MBGP_EVPN, CAP_MBGP_IPV4FS, CAP_MBGP_VPNV4FS, CAP_MBGP_IPV6FS, CAP_MBGP_VPNV6FS, + CAP_MBGP_L2VPNFS, RTC_AS, HOLD_TIME, ENABLED, MULTI_EXIT_DISC, MAX_PREFIXES, ADVERTISE_PEER_AS, SITE_OF_ORIGINS, @@ -372,6 +376,8 @@ class NeighborConf(ConfWithId, ConfWithStats): CAP_MBGP_VPNV4FS, DEFAULT_CAP_MBGP_VPNV4FS, **kwargs) self._settings[CAP_MBGP_VPNV6FS] = compute_optional_conf( CAP_MBGP_VPNV6FS, DEFAULT_CAP_MBGP_VPNV6FS, **kwargs) + self._settings[CAP_MBGP_L2VPNFS] = compute_optional_conf( + CAP_MBGP_L2VPNFS, DEFAULT_CAP_MBGP_L2VPNFS, **kwargs) self._settings[HOLD_TIME] = compute_optional_conf( HOLD_TIME, DEFAULT_HOLD_TIME, **kwargs) self._settings[ENABLED] = compute_optional_conf( @@ -557,6 +563,10 @@ class NeighborConf(ConfWithId, ConfWithStats): def cap_mbgp_vpnv6fs(self): return self._settings[CAP_MBGP_VPNV6FS] + @property + def cap_mbgp_l2vpnfs(self): + return self._settings[CAP_MBGP_L2VPNFS] + @property def cap_rtc(self): return self._settings[CAP_RTC] @@ -701,6 +711,11 @@ class NeighborConf(ConfWithId, ConfWithStats): BGPOptParamCapabilityMultiprotocol( RF_VPNv6_FLOWSPEC.afi, RF_VPNv6_FLOWSPEC.safi)) + if self.cap_mbgp_l2vpnfs: + mbgp_caps.append( + BGPOptParamCapabilityMultiprotocol( + RF_L2VPN_FLOWSPEC.afi, RF_L2VPN_FLOWSPEC.safi)) + if mbgp_caps: capabilities[BGP_CAP_MULTIPROTOCOL] = mbgp_caps diff --git a/ryu/services/protocols/bgp/rtconf/vrfs.py b/ryu/services/protocols/bgp/rtconf/vrfs.py index a918c5b9..72958df2 100644 --- a/ryu/services/protocols/bgp/rtconf/vrfs.py +++ b/ryu/services/protocols/bgp/rtconf/vrfs.py @@ -25,6 +25,7 @@ from ryu.lib.packet.bgp import RF_IPv6_UC from ryu.lib.packet.bgp import RF_L2_EVPN from ryu.lib.packet.bgp import RF_IPv4_FLOWSPEC from ryu.lib.packet.bgp import RF_IPv6_FLOWSPEC +from ryu.lib.packet.bgp import RF_L2VPN_FLOWSPEC from ryu.services.protocols.bgp.utils import validation from ryu.services.protocols.bgp.base import get_validator @@ -63,12 +64,14 @@ VRF_RF_IPV6 = 'ipv6' VRF_RF_L2_EVPN = 'evpn' VRF_RF_IPV4_FLOWSPEC = 'ipv4fs' VRF_RF_IPV6_FLOWSPEC = 'ipv6fs' +VRF_RF_L2VPN_FLOWSPEC = 'l2vpnfs' SUPPORTED_VRF_RF = ( VRF_RF_IPV4, VRF_RF_IPV6, VRF_RF_L2_EVPN, VRF_RF_IPV4_FLOWSPEC, VRF_RF_IPV6_FLOWSPEC, + VRF_RF_L2VPN_FLOWSPEC, ) @@ -240,6 +243,8 @@ class VrfConf(ConfWithId, ConfWithStats): return RF_IPv4_FLOWSPEC elif vrf_rf == VRF_RF_IPV6_FLOWSPEC: return RF_IPv6_FLOWSPEC + elif vrf_rf == VRF_RF_L2VPN_FLOWSPEC: + return RF_L2VPN_FLOWSPEC else: raise ValueError('Unsupported VRF route family given %s' % vrf_rf) @@ -255,6 +260,8 @@ class VrfConf(ConfWithId, ConfWithStats): return VRF_RF_IPV4_FLOWSPEC elif route_family == RF_IPv6_FLOWSPEC: return VRF_RF_IPV6_FLOWSPEC + elif route_family == RF_L2VPN_FLOWSPEC: + return VRF_RF_L2VPN_FLOWSPEC else: raise ValueError('No supported mapping for route family ' 'to vrf_route_family exists for %s' % diff --git a/ryu/services/protocols/bgp/utils/bgp.py b/ryu/services/protocols/bgp/utils/bgp.py index 2d066944..5a9824d1 100644 --- a/ryu/services/protocols/bgp/utils/bgp.py +++ b/ryu/services/protocols/bgp/utils/bgp.py @@ -32,6 +32,7 @@ from ryu.lib.packet.bgp import ( RF_IPv6_FLOWSPEC, RF_VPNv4_FLOWSPEC, RF_VPNv6_FLOWSPEC, + RF_L2VPN_FLOWSPEC, RF_RTC_UC, RouteTargetMembershipNLRI, BGP_ATTR_TYPE_MULTI_EXIT_DISC, @@ -49,6 +50,8 @@ from ryu.lib.packet.bgp import ( BGPFlowSpecTrafficActionCommunity, BGPFlowSpecRedirectCommunity, BGPFlowSpecTrafficMarkingCommunity, + BGPFlowSpecVlanActionCommunity, + BGPFlowSpecTPIDActionCommunity, ) from ryu.services.protocols.bgp.info_base.rtc import RtcPath from ryu.services.protocols.bgp.info_base.ipv4 import Ipv4Path @@ -60,6 +63,7 @@ from ryu.services.protocols.bgp.info_base.ipv4fs import IPv4FlowSpecPath from ryu.services.protocols.bgp.info_base.ipv6fs import IPv6FlowSpecPath from ryu.services.protocols.bgp.info_base.vpnv4fs import VPNv4FlowSpecPath from ryu.services.protocols.bgp.info_base.vpnv6fs import VPNv6FlowSpecPath +from ryu.services.protocols.bgp.info_base.l2vpnfs import L2VPNFlowSpecPath LOG = logging.getLogger('utils.bgp') @@ -74,6 +78,7 @@ _ROUTE_FAMILY_TO_PATH_MAP = {RF_IPv4_UC: Ipv4Path, RF_IPv6_FLOWSPEC: IPv6FlowSpecPath, RF_VPNv4_FLOWSPEC: VPNv4FlowSpecPath, RF_VPNv6_FLOWSPEC: VPNv6FlowSpecPath, + RF_L2VPN_FLOWSPEC: L2VPNFlowSpecPath, RF_RTC_UC: RtcPath} @@ -249,6 +254,32 @@ def create_v6flowspec_actions(actions=None): return _create_actions(actions, action_types) +def create_l2vpnflowspec_actions(actions=None): + """ + Create list of traffic filtering actions for L2VPN Flow Specification. + """ + from ryu.services.protocols.bgp.api.prefix import ( + FLOWSPEC_ACTION_TRAFFIC_RATE, + FLOWSPEC_ACTION_TRAFFIC_ACTION, + FLOWSPEC_ACTION_REDIRECT, + FLOWSPEC_ACTION_TRAFFIC_MARKING, + FLOWSPEC_ACTION_VLAN, + FLOWSPEC_ACTION_TPID, + ) + + # Supported action type for L2VPN. + action_types = { + FLOWSPEC_ACTION_TRAFFIC_RATE: BGPFlowSpecTrafficRateCommunity, + FLOWSPEC_ACTION_TRAFFIC_ACTION: BGPFlowSpecTrafficActionCommunity, + FLOWSPEC_ACTION_REDIRECT: BGPFlowSpecRedirectCommunity, + FLOWSPEC_ACTION_TRAFFIC_MARKING: BGPFlowSpecTrafficMarkingCommunity, + FLOWSPEC_ACTION_VLAN: BGPFlowSpecVlanActionCommunity, + FLOWSPEC_ACTION_TPID: BGPFlowSpecTPIDActionCommunity, + } + + return _create_actions(actions, action_types) + + def _create_actions(actions, action_types): communities = [] -- cgit v1.2.3