BGPSpeaker: Support Flow Specification update messages

This patch enables BGPSpeaker to store FlowSpec routes into
the global table and VRF tables and to provide the API
for advertising routes.

Signed-off-by: Shinpei Muraoka <shinpei.muraoka@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
Shinpei Muraoka 2017-03-24 17:10:48 +09:00 committed by FUJITA Tomonori
parent a486539400
commit b3a83ef185
15 changed files with 666 additions and 13 deletions

View File

@ -54,6 +54,9 @@ MPLS_LABELS = 'mpls_labels'
TUNNEL_TYPE = 'tunnel_type'
EVPN_VNI = 'vni'
PMSI_TUNNEL_TYPE = 'pmsi_tunnel_type'
FLOWSPEC_FAMILY = 'flowspec_family'
FLOWSPEC_RULES = 'rules'
FLOWSPEC_ACTIONS = 'actions'
# API call registry
_CALL_REGISTRY = {}

View File

@ -26,6 +26,13 @@ from ryu.lib.packet.bgp import EvpnInclusiveMulticastEthernetTagNLRI
from ryu.lib.packet.bgp import EvpnEthernetSegmentNLRI
from ryu.lib.packet.bgp import EvpnIpPrefixNLRI
from ryu.lib.packet.bgp import BGPPathAttributePmsiTunnel
from ryu.lib.packet.bgp import FlowSpecIPv4NLRI
from ryu.lib.packet.bgp import FlowSpecVPNv4NLRI
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.services.protocols.bgp.api.base import EVPN_ROUTE_TYPE
from ryu.services.protocols.bgp.api.base import EVPN_ESI
from ryu.services.protocols.bgp.api.base import EVPN_ETHERNET_TAG_ID
@ -43,6 +50,9 @@ from ryu.services.protocols.bgp.api.base import VPN_LABEL
from ryu.services.protocols.bgp.api.base import EVPN_VNI
from ryu.services.protocols.bgp.api.base import TUNNEL_TYPE
from ryu.services.protocols.bgp.api.base import PMSI_TUNNEL_TYPE
from ryu.services.protocols.bgp.api.base import FLOWSPEC_FAMILY
from ryu.services.protocols.bgp.api.base import FLOWSPEC_RULES
from ryu.services.protocols.bgp.api.base import FLOWSPEC_ACTIONS
from ryu.services.protocols.bgp.base import add_bgp_error_metadata
from ryu.services.protocols.bgp.base import PREFIX_ERROR_CODE
from ryu.services.protocols.bgp.base import validate
@ -55,7 +65,6 @@ from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_IPV4
from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_L2_EVPN
from ryu.services.protocols.bgp.utils import validation
LOG = logging.getLogger('bgpspeaker.api.prefix')
# Maximum value of the Ethernet Tag ID
@ -92,6 +101,29 @@ SUPPORTED_EVPN_ROUTE_TYPES = [
EVPN_IP_PREFIX_ROUTE,
]
# Constants used in API calls for Flow Specification
FLOWSPEC_FAMILY_IPV4 = FlowSpecIPv4NLRI.FLOWSPEC_FAMILY
FLOWSPEC_FAMILY_VPNV4 = FlowSpecVPNv4NLRI.FLOWSPEC_FAMILY
SUPPORTED_FLOWSPEC_FAMILIES = (
FLOWSPEC_FAMILY_IPV4,
FLOWSPEC_FAMILY_VPNV4,
)
# Constants for the Traffic Filtering Actions of Flow Specification
# Constants for the Traffic Filtering Actions of Flow Specification.
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
SUPPORTTED_FLOWSPEC_ACTIONS = (
FLOWSPEC_ACTION_TRAFFIC_RATE,
FLOWSPEC_ACTION_TRAFFIC_ACTION,
FLOWSPEC_ACTION_REDIRECT,
FLOWSPEC_ACTION_TRAFFIC_MARKING,
)
# Constants for ESI Label extended community
REDUNDANCY_MODE_ALL_ACTIVE = 'all_active'
REDUNDANCY_MODE_SINGLE_ACTIVE = 'single_active'
@ -241,6 +273,28 @@ def is_valid_pmsi_tunnel_type(pmsi_tunnel_type):
conf_value=pmsi_tunnel_type)
@validate(name=FLOWSPEC_FAMILY)
def is_valid_flowspec_family(flowspec_family):
if flowspec_family not in SUPPORTED_FLOWSPEC_FAMILIES:
raise ConfigValueError(conf_name=FLOWSPEC_FAMILY,
conf_value=flowspec_family)
@validate(name=FLOWSPEC_RULES)
def is_valid_flowspec_rules(rules):
if not isinstance(rules, dict):
raise ConfigValueError(conf_name=FLOWSPEC_RULES,
conf_value=rules)
@validate(name=FLOWSPEC_ACTIONS)
def is_valid_flowspec_actions(actions):
for k in actions:
if k not in SUPPORTTED_FLOWSPEC_ACTIONS:
raise ConfigValueError(conf_name=FLOWSPEC_ACTIONS,
conf_value=actions)
@RegisterWithArgChecks(name='prefix.add_local',
req_args=[ROUTE_DISTINGUISHER, PREFIX, NEXT_HOP],
opt_args=[VRF_RF])
@ -340,3 +394,52 @@ def delete_evpn_local(route_type, route_dist, **kwargs):
VRF_RF: VRF_RF_L2_EVPN}.update(kwargs)]
except BgpCoreError as e:
raise PrefixError(desc=e)
# =============================================================================
# BGP Flow Specification Routes related APIs
# =============================================================================
@RegisterWithArgChecks(
name='flowspec.add_local',
req_args=[FLOWSPEC_FAMILY, ROUTE_DISTINGUISHER, FLOWSPEC_RULES],
opt_args=[FLOWSPEC_ACTIONS])
def add_flowspec_local(flowspec_family, route_dist, rules, **kwargs):
"""Adds Flow Specification route from VRF identified by *route_dist*.
"""
try:
# Create new path and insert into appropriate VRF table.
tm = CORE_MANAGER.get_core_service().table_manager
tm.update_flowspec_vrf_table(
flowspec_family=flowspec_family, route_dist=route_dist,
rules=rules, **kwargs)
# Send success response.
return [{FLOWSPEC_FAMILY: flowspec_family,
ROUTE_DISTINGUISHER: route_dist,
FLOWSPEC_RULES: rules}.update(kwargs)]
except BgpCoreError as e:
raise PrefixError(desc=e)
@RegisterWithArgChecks(
name='flowspec.del_local',
req_args=[FLOWSPEC_FAMILY, ROUTE_DISTINGUISHER, FLOWSPEC_RULES])
def del_flowspec_local(flowspec_family, route_dist, rules):
"""Deletes/withdraws Flow Specification route from VRF identified
by *route_dist*.
"""
try:
tm = CORE_MANAGER.get_core_service().table_manager
tm.update_flowspec_vrf_table(
flowspec_family=flowspec_family, route_dist=route_dist,
rules=rules, is_withdraw=True)
# Send success response.
return [{FLOWSPEC_FAMILY: flowspec_family,
ROUTE_DISTINGUISHER: route_dist,
FLOWSPEC_RULES: rules}]
except BgpCoreError as e:
raise PrefixError(desc=e)

View File

@ -20,6 +20,9 @@ import logging
from ryu.services.protocols.bgp.api.base import register
from ryu.services.protocols.bgp.api.base import RegisterWithArgChecks
from ryu.services.protocols.bgp.api.base import FLOWSPEC_FAMILY
from ryu.services.protocols.bgp.api.base import FLOWSPEC_RULES
from ryu.services.protocols.bgp.api.base import FLOWSPEC_ACTIONS
from ryu.services.protocols.bgp.core_manager import CORE_MANAGER
from ryu.services.protocols.bgp.rtconf.base import ConfWithId
from ryu.services.protocols.bgp.rtconf.base import RuntimeConfigError
@ -297,3 +300,26 @@ def bmp_start(host, port):
def bmp_stop(host, port):
core = CORE_MANAGER.get_core_service()
return core.stop_bmp(host, port)
# =============================================================================
# BGP Flow Specification Routes related APIs
# =============================================================================
@RegisterWithArgChecks(
name='flowspec.add',
req_args=[FLOWSPEC_FAMILY, FLOWSPEC_RULES],
opt_args=[FLOWSPEC_ACTIONS])
def add_flowspec(flowspec_family, rules, **kwargs):
tm = CORE_MANAGER.get_core_service().table_manager
tm.update_flowspec_global_table(flowspec_family, rules, **kwargs)
return True
@RegisterWithArgChecks(
name='flowspec.del',
req_args=[FLOWSPEC_FAMILY, FLOWSPEC_RULES])
def del_flowspec(flowspec_family, rules):
tm = CORE_MANAGER.get_core_service().table_manager
tm.update_flowspec_global_table(flowspec_family, rules, is_withdraw=True)
return True

View File

@ -331,6 +331,8 @@ class RyuBGPSpeaker(RyuApp):
prefix_add = self.speaker.prefix_add
elif 'route_type' in route_settings:
prefix_add = self.speaker.evpn_prefix_add
elif 'flowspec_family' in route_settings:
prefix_add = self.speaker.flowspec_prefix_add
else:
LOG.debug('Skip invalid route settings: %s', route_settings)
continue

View File

@ -36,6 +36,8 @@ from ryu.lib.packet.bgp import RF_IPv6_UC
from ryu.lib.packet.bgp import RF_IPv4_VPN
from ryu.lib.packet.bgp import RF_IPv6_VPN
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_VPNv4_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
@ -56,6 +58,8 @@ SUPPORTED_GLOBAL_RF = {
RF_RTC_UC,
RF_IPv6_VPN,
RF_L2_EVPN,
RF_IPv4_FLOWSPEC,
RF_VPNv4_FLOWSPEC,
}

View File

@ -3,6 +3,7 @@ import os
from ryu.services.protocols.bgp.bgpspeaker import RF_VPN_V4
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 EVPN_MAX_ET
from ryu.services.protocols.bgp.bgpspeaker import ESI_TYPE_LACP
from ryu.services.protocols.bgp.bgpspeaker import ESI_TYPE_MAC_BASED
@ -12,6 +13,10 @@ from ryu.services.protocols.bgp.bgpspeaker import TUNNEL_TYPE_VXLAN
from ryu.services.protocols.bgp.bgpspeaker import EVPN_MULTICAST_ETAG_ROUTE
from ryu.services.protocols.bgp.bgpspeaker import EVPN_ETH_SEGMENT
from ryu.services.protocols.bgp.bgpspeaker import EVPN_IP_PREFIX_ROUTE
from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_FAMILY_IPV4
from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_FAMILY_VPNV4
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 REDUNDANCY_MODE_SINGLE_ACTIVE
# =============================================================================
@ -42,6 +47,12 @@ BGP = {
'remote_as': 65001,
'enable_evpn': True,
},
{
'address': '172.17.0.4',
'remote_as': 65001,
'enable_ipv4fs': True,
'enable_vpnv4fs': True,
},
],
# List of BGP VRF tables.
@ -69,11 +80,21 @@ BGP = {
'export_rts': ['65001:200'],
'route_family': RF_L2_EVPN,
},
# Example of VRF for FlowSpec
{
'route_dist': '65001:250',
'import_rts': ['65001:250'],
'export_rts': ['65001:250'],
'route_family': RF_VPNV4_FLOWSPEC,
},
],
# List of BGP routes.
# The parameters for each route are the same as the arguments of
# BGPSpeaker.prefix_add() or BGPSpeaker.evpn_prefix_add() method.
# the following methods:
# - BGPSpeaker.prefix_add()
# - BGPSpeaker.evpn_prefix_add()
# - BGPSpeaker.flowspec_prefix_add()
'routes': [
# Example of IPv4 prefix
{
@ -143,6 +164,75 @@ BGP = {
'ip_prefix': '10.50.1.0/24',
'gw_ip_addr': '172.16.0.1',
},
# Example of Flow Specification IPv4 prefix
{
'flowspec_family': FLOWSPEC_FAMILY_IPV4,
'rules': {
'dst_prefix': '10.60.1.0/24',
'src_prefix': '172.17.0.0/24',
'ip_proto': 6,
'port': '80 | 8000',
'dst_port': '>9000 & <9050',
'src_port': '>=8500 & <=9000',
'icmp_type': 0,
'icmp_code': 6,
'tcp_flags': 'SYN+ACK & !=URGENT',
'packet_len': 1000,
'dscp': '22 | 24',
'fragment': 'LF | ==FF',
},
'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,
}
},
},
# Example of Flow Specification VPNv4 prefix
{
'flowspec_family': FLOWSPEC_FAMILY_VPNV4,
'route_dist': '65001:250',
'rules': {
'dst_prefix': '10.70.1.0/24',
'src_prefix': '172.18.0.0/24',
'ip_proto': 6,
'port': '80 | 8000',
'dst_port': '>9000 & <9050',
'src_port': '>=8500 & <=9000',
'icmp_type': 0,
'icmp_code': 6,
'tcp_flags': 'SYN+ACK & !=URGENT',
'packet_len': 1000,
'dscp': '22 | 24',
'fragment': 'LF | ==FF',
},
'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,
}
},
},
],
}

View File

@ -18,6 +18,7 @@
import netaddr
from ryu.lib import hub
from ryu.lib.packet.bgp import BGPFlowSpecTrafficActionCommunity
from ryu.services.protocols.bgp.core_manager import CORE_MANAGER
from ryu.services.protocols.bgp.signals.emit import BgpSignalBus
@ -53,6 +54,12 @@ from ryu.services.protocols.bgp.api.prefix import TUNNEL_TYPE_NVGRE
from ryu.services.protocols.bgp.api.prefix import (
PMSI_TYPE_NO_TUNNEL_INFO,
PMSI_TYPE_INGRESS_REP)
from ryu.services.protocols.bgp.api.prefix import (
FLOWSPEC_FAMILY,
FLOWSPEC_FAMILY_IPV4,
FLOWSPEC_FAMILY_VPNV4,
FLOWSPEC_RULES,
FLOWSPEC_ACTIONS)
from ryu.services.protocols.bgp.rtconf.common import LOCAL_AS
from ryu.services.protocols.bgp.rtconf.common import ROUTER_ID
from ryu.services.protocols.bgp.rtconf.common import CLUSTER_ID
@ -72,6 +79,8 @@ from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_IPV6
from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV4
from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV6
from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_EVPN
from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_IPV4FS
from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV4FS
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
@ -81,6 +90,8 @@ from ryu.services.protocols.bgp.rtconf.neighbors import DEFAULT_CAP_MBGP_IPV6
from ryu.services.protocols.bgp.rtconf.neighbors import DEFAULT_CAP_MBGP_VPNV4
from ryu.services.protocols.bgp.rtconf.neighbors import DEFAULT_CAP_MBGP_VPNV6
from ryu.services.protocols.bgp.rtconf.neighbors import DEFAULT_CAP_MBGP_EVPN
from ryu.services.protocols.bgp.rtconf.neighbors import DEFAULT_CAP_MBGP_IPV4FS
from ryu.services.protocols.bgp.rtconf.neighbors import DEFAULT_CAP_MBGP_VPNV4FS
from ryu.services.protocols.bgp.rtconf.neighbors import (
DEFAULT_CAP_ENHANCED_REFRESH, DEFAULT_CAP_FOUR_OCTET_AS_NUMBER)
from ryu.services.protocols.bgp.rtconf.neighbors import DEFAULT_CONNECT_MODE
@ -108,6 +119,11 @@ NEIGHBOR_CONF_MED = MULTI_EXIT_DISC # for backward compatibility
RF_VPN_V4 = vrfs.VRF_RF_IPV4
RF_VPN_V6 = vrfs.VRF_RF_IPV6
RF_L2_EVPN = vrfs.VRF_RF_L2_EVPN
RF_VPNV4_FLOWSPEC = vrfs.VRF_RF_IPV4_FLOWSPEC
# Constants for the Traffic Filtering Actions of Flow Specification.
FLOWSPEC_TA_SAMPLE = BGPFlowSpecTrafficActionCommunity.SAMPLE
FLOWSPEC_TA_TERMINAL = BGPFlowSpecTrafficActionCommunity.TERMINAL
class EventPrefix(object):
@ -330,6 +346,8 @@ class BGPSpeaker(object):
enable_vpnv4=DEFAULT_CAP_MBGP_VPNV4,
enable_vpnv6=DEFAULT_CAP_MBGP_VPNV6,
enable_evpn=DEFAULT_CAP_MBGP_EVPN,
enable_ipv4fs=DEFAULT_CAP_MBGP_IPV4FS,
enable_vpnv4fs=DEFAULT_CAP_MBGP_VPNV4FS,
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,
@ -366,6 +384,12 @@ class BGPSpeaker(object):
``enable_evpn`` enables Ethernet VPN address family for this
neighbor. The default is False.
``enable_ipv4fs`` enables IPv4 Flow Specification address family
for this neighbor. The default is False.
``enable_vpnv4fs`` enables VPNv4 Flow Specification address family
for this neighbor. The default is False.
``enable_enhanced_refresh`` enables Enhanced Route Refresh for this
neighbor. The default is False.
@ -424,6 +448,8 @@ class BGPSpeaker(object):
CAP_MBGP_VPNV4: enable_vpnv4,
CAP_MBGP_VPNV6: enable_vpnv6,
CAP_MBGP_EVPN: enable_evpn,
CAP_MBGP_IPV4FS: enable_ipv4fs,
CAP_MBGP_VPNV4FS: enable_vpnv4fs,
}
if multi_exit_disc:
@ -761,6 +787,126 @@ class BGPSpeaker(object):
call(func_name, **kwargs)
def flowspec_prefix_add(self, flowspec_family, rules, route_dist=None,
actions=None):
""" This method adds a new Flow Specification prefix to be advertised.
``flowspec_family`` specifies one of the flowspec family name.
The supported flowspec families are FLOWSPEC_FAMILY_IPV4 and
FLOWSPEC_FAMILY_VPNV4.
``route_dist`` specifies a route distinguisher value.
This parameter is necessary for only VPNv4 Flow Specification
address family.
``rules`` specifies NLRIs of Flow Specification as
a dictionary type value.
For the supported NLRI types and arguments,
see `from_user()` method of the following classes.
- :py:mod:`ryu.lib.packet.bgp.FlowSpecIPv4NLRI`
- :py:mod:`ryu.lib.packet.bgp.FlowSpecVPNv4NLRI`
`` actions`` specifies Traffic Filtering Actions of
Flow Specification as a dictionary type value.
The keys are "ACTION_NAME" for each action class and
values are used for the arguments to that class.
For the supported "ACTION_NAME" and arguments,
see the following table.
=============== ===============================================================
ACTION_NAME Action Class
=============== ===============================================================
traffic_rate :py:mod:`ryu.lib.packet.bgp.BGPFlowSpecTrafficRateCommunity`
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`
=============== ===============================================================
Example(IPv4)::
>>> speaker = BGPSpeaker(as_number=65001, router_id='172.17.0.1')
>>> speaker.neighbor_add(address='172.17.0.2',
... remote_as=65002,
... enable_ipv4fs=True)
>>> speaker.flowspec_prefix_add(
... flowspec_family=FLOWSPEC_FAMILY_IPV4,
... rules={
... 'dst_prefix': '10.60.1.0/24'
... },
... actions={
... 'traffic_marking': {
... 'dscp': 24
... }
... }
... )
Example(VPNv4)::
>>> speaker = BGPSpeaker(as_number=65001, router_id='172.17.0.1')
>>> speaker.neighbor_add(address='172.17.0.2',
... remote_as=65002,
... enable_vpnv4fs=True)
>>> speaker.vrf_add(route_dist='65001:100',
... import_rts=['65001:100'],
... export_rts=['65001:100'],
... route_family=RF_VPNV4_FLOWSPEC)
>>> speaker.flowspec_prefix_add(
... flowspec_family=FLOWSPEC_FAMILY_VPNV4,
... route_dist='65000:100',
... rules={
... 'dst_prefix': '10.60.1.0/24'
... },
... actions={
... 'traffic_marking': {
... 'dscp': 24
... }
... }
... )
"""
func_name = 'flowspec.add'
# Set required arguments
kwargs = {
FLOWSPEC_FAMILY: flowspec_family,
FLOWSPEC_RULES: rules,
FLOWSPEC_ACTIONS: actions or {},
}
if flowspec_family == FLOWSPEC_FAMILY_VPNV4:
func_name = 'flowspec.add_local'
kwargs.update({ROUTE_DISTINGUISHER: route_dist})
call(func_name, **kwargs)
def flowspec_prefix_del(self, flowspec_family, rules, route_dist=None):
""" This method deletes an advertised Flow Specification route.
``flowspec_family`` specifies one of the flowspec family name.
``route_dist`` specifies a route distinguisher value.
``rules`` specifies NLRIs of Flow Specification as
a dictionary type value.
See the following method for details of each parameter and usages.
- :py:mod:`ryu.services.protocols.bgp.bgpspeaker.BGPSpeaker.flowspec_prefix_add`
"""
func_name = 'flowspec.del'
# Set required arguments
kwargs = {
FLOWSPEC_FAMILY: flowspec_family,
FLOWSPEC_RULES: rules,
}
if flowspec_family == FLOWSPEC_FAMILY_VPNV4:
func_name = 'flowspec.del_local'
kwargs.update({ROUTE_DISTINGUISHER: route_dist})
call(func_name, **kwargs)
def vrf_add(self, route_dist, import_rts, export_rts, site_of_origins=None,
route_family=RF_VPN_V4, multi_exit_disc=None):
""" This method adds a new vrf used for VPN.

View File

@ -15,10 +15,16 @@ from ryu.services.protocols.bgp.info_base.vrf4 import Vrf4Table
from ryu.services.protocols.bgp.info_base.vrf6 import Vrf6Table
from ryu.services.protocols.bgp.info_base.vrfevpn import VrfEvpnTable
from ryu.services.protocols.bgp.info_base.evpn import EvpnTable
from ryu.services.protocols.bgp.info_base.ipv4fs import IPv4FlowSpecPath
from ryu.services.protocols.bgp.info_base.ipv4fs import IPv4FlowSpecTable
from ryu.services.protocols.bgp.info_base.vpnv4fs import VPNv4FlowSpecTable
from ryu.services.protocols.bgp.info_base.vrf4fs import Vrf4FlowSpecTable
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 SUPPORTED_VRF_RF
from ryu.services.protocols.bgp.utils.bgp import create_v4flowspec_actions
from ryu.lib import type_desc
from ryu.lib.packet.bgp import RF_IPv4_UC
@ -26,12 +32,16 @@ from ryu.lib.packet.bgp import RF_IPv6_UC
from ryu.lib.packet.bgp import RF_IPv4_VPN
from ryu.lib.packet.bgp import RF_IPv6_VPN
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_VPNv4_FLOWSPEC
from ryu.lib.packet.bgp import RF_RTC_UC
from ryu.lib.packet.bgp import BGPPathAttributeOrigin
from ryu.lib.packet.bgp import BGPPathAttributeAsPath
from ryu.lib.packet.bgp import BGPPathAttributeExtendedCommunities
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_ORIGIN
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_AS_PATH
from ryu.lib.packet.bgp import BGP_ATTR_ORIGIN_IGP
from ryu.lib.packet.bgp import BGP_ATTR_TYPE_EXTENDED_COMMUNITIES
from ryu.lib.packet.bgp import EvpnEsi
from ryu.lib.packet.bgp import EvpnArbitraryEsi
from ryu.lib.packet.bgp import EvpnNLRI
@ -39,6 +49,7 @@ from ryu.lib.packet.bgp import EvpnMacIPAdvertisementNLRI
from ryu.lib.packet.bgp import EvpnInclusiveMulticastEthernetTagNLRI
from ryu.lib.packet.bgp import IPAddrPrefix
from ryu.lib.packet.bgp import IP6AddrPrefix
from ryu.lib.packet.bgp import FlowSpecIPv4NLRI
from ryu.services.protocols.bgp.utils.validation import is_valid_ipv4
from ryu.services.protocols.bgp.utils.validation import is_valid_ipv4_prefix
@ -119,6 +130,8 @@ class TableCoreManager(object):
vpn_table = self.get_vpn6_table()
elif vrf_table.route_family == VrfEvpnTable.ROUTE_FAMILY:
vpn_table = self.get_evpn_table()
elif vrf_table.route_family == Vrf4FlowSpecTable.ROUTE_FAMILY:
vpn_table = self.get_vpnv4fs_table()
else:
raise ValueError('Invalid VRF table route family: %s' %
vrf_table.route_family)
@ -185,6 +198,10 @@ class TableCoreManager(object):
global_table = self.get_vpn6_table()
elif route_family == RF_L2_EVPN:
global_table = self.get_evpn_table()
elif route_family == RF_IPv4_FLOWSPEC:
global_table = self.get_ipv4fs_table()
elif route_family == RF_VPNv4_FLOWSPEC:
global_table = self.get_vpnv4fs_table()
elif route_family == RF_RTC_UC:
global_table = self.get_rtc_table()
@ -295,6 +312,36 @@ class TableCoreManager(object):
self._next_vpnv4_label += 1
return lbl
def get_ipv4fs_table(self):
"""Returns global IPv4 Flow Specification table.
Creates the table if it does not exist.
"""
ipv4fs_table = self._global_tables.get(RF_IPv4_FLOWSPEC)
# Lazy initialization of the table.
if not ipv4fs_table:
ipv4fs_table = IPv4FlowSpecTable(self._core_service,
self._signal_bus)
self._global_tables[RF_IPv4_FLOWSPEC] = ipv4fs_table
self._tables[(None, RF_IPv4_FLOWSPEC)] = ipv4fs_table
return ipv4fs_table
def get_vpnv4fs_table(self):
"""Returns global VPNv4 Flow Specification table.
Creates the table if it does not exist.
"""
vpnv4fs_table = self._global_tables.get(RF_VPNv4_FLOWSPEC)
# Lazy initialization of the table.
if not vpnv4fs_table:
vpnv4fs_table = VPNv4FlowSpecTable(self._core_service,
self._signal_bus)
self._global_tables[RF_VPNv4_FLOWSPEC] = vpnv4fs_table
self._tables[(None, RF_VPNv4_FLOWSPEC)] = vpnv4fs_table
return vpnv4fs_table
def get_nexthop_label(self, label_key):
return self._next_hop_label.get(label_key, None)
@ -374,6 +421,8 @@ class TableCoreManager(object):
vrf_table = Vrf6Table
elif route_family == VRF_RF_L2_EVPN:
vrf_table = VrfEvpnTable
elif route_family == VRF_RF_IPV4_FLOWSPEC:
vrf_table = Vrf4FlowSpecTable
else:
raise ValueError('Unsupported route family for VRF: %s' %
route_family)
@ -457,6 +506,8 @@ class TableCoreManager(object):
route_family = RF_IPv6_UC
elif vpn_path.route_family == RF_L2_EVPN:
route_family = RF_L2_EVPN
elif vpn_path.route_family == RF_VPNv4_FLOWSPEC:
route_family = RF_IPv4_FLOWSPEC
else:
raise ValueError('Unsupported route family for VRF: %s' %
vpn_path.route_family)
@ -580,6 +631,49 @@ class TableCoreManager(object):
vni=vni, tunnel_type=tunnel_type,
pmsi_tunnel_type=pmsi_tunnel_type)
def update_flowspec_vrf_table(self, flowspec_family, route_dist, rules,
actions=None, is_withdraw=False):
"""Update a BGP route in the VRF table for Flow Specification.
``flowspec_family`` specifies one of the flowspec family name.
``route_dist`` specifies a route distinguisher value.
``rules`` specifies NLRIs of Flow Specification as
a dictionary type value.
`` actions`` specifies Traffic Filtering Actions of
Flow Specification as a dictionary type value.
If `is_withdraw` is False, which is the default, add a BGP route
to the VRF table identified by `route_dist`.
If `is_withdraw` is True, remove a BGP route from the VRF table.
"""
from ryu.services.protocols.bgp.core import BgpCoreError
from ryu.services.protocols.bgp.api.prefix import FLOWSPEC_FAMILY_VPNV4
if flowspec_family == FLOWSPEC_FAMILY_VPNV4:
vrf_table = self._tables.get((route_dist, VRF_RF_IPV4_FLOWSPEC))
prefix = FlowSpecIPv4NLRI.from_user(**rules)
try:
communities = create_v4flowspec_actions(actions)
except ValueError as e:
raise BgpCoreError(desc=str(e))
else:
raise BgpCoreError(
desc='Unsupported flowspec_family %s' % flowspec_family)
if vrf_table is None:
raise BgpCoreError(
desc='VRF table does not exist: route_dist=%s, '
'flowspec_family=%s' % (route_dist, flowspec_family))
# We do not check if we have a path to given prefix, we issue
# withdrawal. Hence multiple withdrawals have not side effect.
vrf_table.insert_vrffs_path(
nlri=prefix, communities=communities,
is_withdraw=is_withdraw)
def update_global_table(self, prefix, next_hop=None, is_withdraw=False):
"""Update a BGP route in the Global table for the given `prefix`
with the given `next_hop`.
@ -616,7 +710,62 @@ class TableCoreManager(object):
pattrs=pathattrs, nexthop=next_hop,
is_withdraw=is_withdraw)
# add to global ipv4 table and propagates to neighbors
# add to global table and propagates to neighbors
self.learn_path(new_path)
def update_flowspec_global_table(self, flowspec_family, rules,
actions=None, is_withdraw=False):
"""Update a BGP route in the Global table for Flow Specification.
``flowspec_family`` specifies one of the Flow Specification
family name.
``rules`` specifies NLRIs of Flow Specification as
a dictionary type value.
`` actions`` specifies Traffic Filtering Actions of
Flow Specification as a dictionary type value.
If `is_withdraw` is False, which is the default, add a BGP route
to the Global table.
If `is_withdraw` is True, remove a BGP route from the Global table.
"""
from ryu.services.protocols.bgp.core import BgpCoreError
from ryu.services.protocols.bgp.api.prefix import FLOWSPEC_FAMILY_IPV4
src_ver_num = 1
peer = None
# set mandatory path attributes
origin = BGPPathAttributeOrigin(BGP_ATTR_ORIGIN_IGP)
aspath = BGPPathAttributeAsPath([[]])
pathattrs = OrderedDict()
pathattrs[BGP_ATTR_TYPE_ORIGIN] = origin
pathattrs[BGP_ATTR_TYPE_AS_PATH] = aspath
if flowspec_family == FLOWSPEC_FAMILY_IPV4:
_nlri = FlowSpecIPv4NLRI.from_user(**rules)
p = IPv4FlowSpecPath
try:
communities = create_v4flowspec_actions(actions)
except ValueError as e:
raise BgpCoreError(desc=str(e))
if communities:
pathattrs[BGP_ATTR_TYPE_EXTENDED_COMMUNITIES] = (
BGPPathAttributeExtendedCommunities(
communities=communities))
else:
raise BgpCoreError(
desc='Unsupported flowspec family %s' % flowspec_family)
new_path = p(peer, _nlri, src_ver_num,
pattrs=pathattrs, is_withdraw=is_withdraw)
# add to global table and propagates to neighbors
self.learn_path(new_path)
def clean_stale_routes(self, peer, route_family=None):

View File

@ -97,9 +97,11 @@ class FlexinetOutgoingRoute(object):
from ryu.services.protocols.bgp.info_base.vrf4 import Vrf4Path
from ryu.services.protocols.bgp.info_base.vrf6 import Vrf6Path
from ryu.services.protocols.bgp.info_base.vrfevpn import VrfEvpnPath
from ryu.services.protocols.bgp.info_base.vrf4fs import Vrf4FlowSpecPath
assert path.route_family in (Vrf4Path.ROUTE_FAMILY,
Vrf6Path.ROUTE_FAMILY,
VrfEvpnPath.ROUTE_FAMILY)
VrfEvpnPath.ROUTE_FAMILY,
Vrf4FlowSpecPath.ROUTE_FAMILY)
self.sink = None
self._path = path

View File

@ -25,6 +25,8 @@ import traceback
import msgpack
from ryu.lib.packet import safi as subaddr_family
from ryu.services.protocols.bgp import api
from ryu.services.protocols.bgp.api.base import ApiException
from ryu.services.protocols.bgp.api.base import NEXT_HOP
@ -268,8 +270,11 @@ def _create_prefix_notification(outgoing_msg, rpc_session):
params = [{ROUTE_DISTINGUISHER: outgoing_msg.route_dist,
PREFIX: vpn_nlri.prefix,
NEXT_HOP: path.nexthop,
VPN_LABEL: path.label_list[0],
VRF_RF: VrfConf.rf_2_vrf_rf(path.route_family)}]
if path.nlri.ROUTE_FAMILY.safi not in (subaddr_family.IP_FLOWSPEC,
subaddr_family.VPN_FLOWSPEC):
params[VPN_LABEL] = path.label_list[0]
if not path.is_withdraw:
# Create notification to NetworkController.
rpc_msg = rpc_session.create_notification(

View File

@ -54,6 +54,8 @@ from ryu.lib.packet.bgp import RF_IPv4_UC
from ryu.lib.packet.bgp import RF_IPv6_UC
from ryu.lib.packet.bgp import RF_IPv4_VPN
from ryu.lib.packet.bgp import RF_IPv6_VPN
from ryu.lib.packet.bgp import RF_IPv4_FLOWSPEC
from ryu.lib.packet.bgp import RF_VPNv4_FLOWSPEC
from ryu.lib.packet.bgp import RF_RTC_UC
from ryu.lib.packet.bgp import get_rf
@ -100,6 +102,8 @@ from ryu.lib.packet.bgp import BGP_ATTR_TYEP_PMSI_TUNNEL_ATTRIBUTE
from ryu.lib.packet.bgp import BGPTwoOctetAsSpecificExtendedCommunity
from ryu.lib.packet.bgp import BGPIPv4AddressSpecificExtendedCommunity
from ryu.lib.packet import safi as subaddr_family
LOG = logging.getLogger('bgpspeaker.peer')
@ -1030,9 +1034,11 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
unknown_opttrans_attrs = None
nlri_list = [path.nlri]
# By default, we use BGPSpeaker's interface IP with this peer
# as next_hop.
if self.is_ebgp_peer():
if path.route_family.safi in (subaddr_family.IP_FLOWSPEC,
subaddr_family.VPN_FLOWSPEC):
# Flow Specification does not have next_hop.
next_hop = []
elif self.is_ebgp_peer():
next_hop = self._session_next_hop(path)
if path.is_local() and path.has_nexthop():
next_hop = path.nexthop
@ -1518,9 +1524,14 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
raise bgp.MissingWellKnown(BGP_ATTR_TYPE_ORIGIN)
# Validate Next hop.
# TODO(PH): Currently ignore other cases.
if (not mp_reach_attr.next_hop or
(mp_reach_attr.next_hop == self.host_bind_ip)):
if mp_reach_attr.route_family.safi in (
subaddr_family.IP_FLOWSPEC,
subaddr_family.VPN_FLOWSPEC):
# Because the Flow Specification does not have nexthop,
# skips check.
pass
elif (not mp_reach_attr.next_hop or
mp_reach_attr.next_hop == self.host_bind_ip):
LOG.error('Nexthop of received UPDATE msg. (%s) same as local'
' interface address %s.',
mp_reach_attr.next_hop,

View File

@ -46,6 +46,8 @@ CAP_MBGP_IPV6 = 'cap_mbgp_ipv6'
CAP_MBGP_VPNV4 = 'cap_mbgp_vpnv4'
CAP_MBGP_VPNV6 = 'cap_mbgp_vpnv6'
CAP_MBGP_EVPN = 'cap_mbgp_evpn'
CAP_MBGP_IPV4FS = 'cap_mbgp_ipv4fs'
CAP_MBGP_VPNV4FS = 'cap_mbgp_vpnv4fs'
CAP_RTC = 'cap_rtc'
RTC_AS = 'rtc_as'
HOLD_TIME = 'hold_time'
@ -648,6 +650,24 @@ def validate_cap_mbgp_evpn(cmevpn):
return cmevpn
@validate(name=CAP_MBGP_IPV4FS)
def validate_cap_mbgp_ipv4fs(cmv4fs):
if not isinstance(cmv4fs, bool):
raise ConfigTypeError(desc='Invalid MP-BGP '
'IPv4 Flow Specification capability '
'settings: %s. Boolean value expected' % cmv4fs)
return cmv4fs
@validate(name=CAP_MBGP_VPNV4FS)
def validate_cap_mbgp_vpnv4fs(cmv4fs):
if not isinstance(cmv4fs, bool):
raise ConfigTypeError(desc='Invalid MP-BGP '
'VPNv4 Flow Specification capability '
'settings: %s. Boolean value expected' % cmv4fs)
return cmv4fs
@validate(name=CAP_RTC)
def validate_cap_rtc(cap_rtc):
if not isinstance(cap_rtc, bool):

View File

@ -27,6 +27,8 @@ from ryu.lib.packet.bgp import RF_IPv6_UC
from ryu.lib.packet.bgp import RF_IPv4_VPN
from ryu.lib.packet.bgp import RF_IPv6_VPN
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_VPNv4_FLOWSPEC
from ryu.lib.packet.bgp import RF_RTC_UC
from ryu.lib.packet.bgp import BGPOptParamCapabilityFourOctetAsNumber
from ryu.lib.packet.bgp import BGPOptParamCapabilityEnhancedRouteRefresh
@ -48,6 +50,8 @@ from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_IPV6
from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV4
from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV6
from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_EVPN
from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_IPV4FS
from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV4FS
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
@ -105,6 +109,8 @@ DEFAULT_CAP_MBGP_IPV6 = False
DEFAULT_CAP_MBGP_VPNV4 = False
DEFAULT_CAP_MBGP_VPNV6 = False
DEFAULT_CAP_MBGP_EVPN = False
DEFAULT_CAP_MBGP_IPV4FS = False
DEFAULT_CAP_MBGP_VPNV4FS = False
DEFAULT_HOLD_TIME = 40
DEFAULT_ENABLED = True
DEFAULT_CAP_RTC = False
@ -317,7 +323,9 @@ class NeighborConf(ConfWithId, ConfWithStats):
CAP_FOUR_OCTET_AS_NUMBER,
CAP_MBGP_IPV4, CAP_MBGP_IPV6,
CAP_MBGP_VPNV4, CAP_MBGP_VPNV6,
CAP_RTC, CAP_MBGP_EVPN, RTC_AS, HOLD_TIME,
CAP_RTC, CAP_MBGP_EVPN,
CAP_MBGP_IPV4FS, CAP_MBGP_VPNV4FS,
RTC_AS, HOLD_TIME,
ENABLED, MULTI_EXIT_DISC, MAX_PREFIXES,
ADVERTISE_PEER_AS, SITE_OF_ORIGINS,
LOCAL_ADDRESS, LOCAL_PORT, LOCAL_AS,
@ -349,6 +357,10 @@ class NeighborConf(ConfWithId, ConfWithStats):
CAP_MBGP_EVPN, DEFAULT_CAP_MBGP_EVPN, **kwargs)
self._settings[CAP_MBGP_VPNV6] = compute_optional_conf(
CAP_MBGP_VPNV6, DEFAULT_CAP_MBGP_VPNV6, **kwargs)
self._settings[CAP_MBGP_IPV4FS] = compute_optional_conf(
CAP_MBGP_IPV4FS, DEFAULT_CAP_MBGP_IPV4FS, **kwargs)
self._settings[CAP_MBGP_VPNV4FS] = compute_optional_conf(
CAP_MBGP_VPNV4FS, DEFAULT_CAP_MBGP_VPNV4FS, **kwargs)
self._settings[HOLD_TIME] = compute_optional_conf(
HOLD_TIME, DEFAULT_HOLD_TIME, **kwargs)
self._settings[ENABLED] = compute_optional_conf(
@ -518,6 +530,14 @@ class NeighborConf(ConfWithId, ConfWithStats):
def cap_mbgp_evpn(self):
return self._settings[CAP_MBGP_EVPN]
@property
def cap_mbgp_ipv4fs(self):
return self._settings[CAP_MBGP_IPV4FS]
@property
def cap_mbgp_vpnv4fs(self):
return self._settings[CAP_MBGP_VPNV4FS]
@property
def cap_rtc(self):
return self._settings[CAP_RTC]
@ -642,6 +662,16 @@ class NeighborConf(ConfWithId, ConfWithStats):
BGPOptParamCapabilityMultiprotocol(
RF_L2_EVPN.afi, RF_L2_EVPN.safi))
if self.cap_mbgp_ipv4fs:
mbgp_caps.append(
BGPOptParamCapabilityMultiprotocol(
RF_IPv4_FLOWSPEC.afi, RF_IPv4_FLOWSPEC.safi))
if self.cap_mbgp_vpnv4fs:
mbgp_caps.append(
BGPOptParamCapabilityMultiprotocol(
RF_VPNv4_FLOWSPEC.afi, RF_VPNv4_FLOWSPEC.safi))
if mbgp_caps:
capabilities[BGP_CAP_MULTIPROTOCOL] = mbgp_caps

View File

@ -23,6 +23,7 @@ import logging
from ryu.lib.packet.bgp import RF_IPv4_UC
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.services.protocols.bgp.utils import validation
from ryu.services.protocols.bgp.base import get_validator
@ -59,7 +60,13 @@ IMPORT_MAPS = 'import_maps'
VRF_RF_IPV4 = 'ipv4'
VRF_RF_IPV6 = 'ipv6'
VRF_RF_L2_EVPN = 'evpn'
SUPPORTED_VRF_RF = (VRF_RF_IPV4, VRF_RF_IPV6, VRF_RF_L2_EVPN)
VRF_RF_IPV4_FLOWSPEC = 'ipv4fs'
SUPPORTED_VRF_RF = (
VRF_RF_IPV4,
VRF_RF_IPV6,
VRF_RF_L2_EVPN,
VRF_RF_IPV4_FLOWSPEC,
)
# Default configuration values.
@ -226,6 +233,8 @@ class VrfConf(ConfWithId, ConfWithStats):
return RF_IPv6_UC
elif vrf_rf == VRF_RF_L2_EVPN:
return RF_L2_EVPN
elif vrf_rf == VRF_RF_IPV4_FLOWSPEC:
return RF_IPv4_FLOWSPEC
else:
raise ValueError('Unsupported VRF route family given %s' % vrf_rf)
@ -237,6 +246,8 @@ class VrfConf(ConfWithId, ConfWithStats):
return VRF_RF_IPV6
elif route_family == RF_L2_EVPN:
return VRF_RF_L2_EVPN
elif route_family == RF_IPv4_FLOWSPEC:
return VRF_RF_IPV4_FLOWSPEC
else:
raise ValueError('No supported mapping for route family '
'to vrf_route_family exists for %s' %

View File

@ -28,6 +28,8 @@ from ryu.lib.packet.bgp import (
RF_IPv4_VPN,
RF_IPv6_VPN,
RF_L2_EVPN,
RF_IPv4_FLOWSPEC,
RF_VPNv4_FLOWSPEC,
RF_RTC_UC,
RouteTargetMembershipNLRI,
BGP_ATTR_TYPE_MULTI_EXIT_DISC,
@ -41,6 +43,10 @@ from ryu.lib.packet.bgp import (
BGPTwoOctetAsSpecificExtendedCommunity,
BGPIPv4AddressSpecificExtendedCommunity,
BGPFourOctetAsSpecificExtendedCommunity,
BGPFlowSpecTrafficRateCommunity,
BGPFlowSpecTrafficActionCommunity,
BGPFlowSpecRedirectCommunity,
BGPFlowSpecTrafficMarkingCommunity,
)
from ryu.services.protocols.bgp.info_base.rtc import RtcPath
from ryu.services.protocols.bgp.info_base.ipv4 import Ipv4Path
@ -48,6 +54,8 @@ from ryu.services.protocols.bgp.info_base.ipv6 import Ipv6Path
from ryu.services.protocols.bgp.info_base.vpnv4 import Vpnv4Path
from ryu.services.protocols.bgp.info_base.vpnv6 import Vpnv6Path
from ryu.services.protocols.bgp.info_base.evpn import EvpnPath
from ryu.services.protocols.bgp.info_base.ipv4fs import IPv4FlowSpecPath
from ryu.services.protocols.bgp.info_base.vpnv4fs import VPNv4FlowSpecPath
LOG = logging.getLogger('utils.bgp')
@ -58,6 +66,8 @@ _ROUTE_FAMILY_TO_PATH_MAP = {RF_IPv4_UC: Ipv4Path,
RF_IPv4_VPN: Vpnv4Path,
RF_IPv6_VPN: Vpnv6Path,
RF_L2_EVPN: EvpnPath,
RF_IPv4_FLOWSPEC: IPv4FlowSpecPath,
RF_VPNv4_FLOWSPEC: VPNv4FlowSpecPath,
RF_RTC_UC: RtcPath}
@ -178,3 +188,44 @@ def create_rt_extended_community(value, subtype=2):
'Invalid Route Target or Route Origin value: %s' % value)
return ext_com
def create_v4flowspec_actions(actions=None):
"""
Create list of traffic filtering actions
for Ipv4 Flow Specification and VPNv4 Flow Specification.
`` actions`` specifies Traffic Filtering Actions of
Flow Specification as a dictionary type value.
Returns a list of extended community values.
"""
from ryu.services.protocols.bgp.api.prefix import (
FLOWSPEC_ACTION_TRAFFIC_RATE,
FLOWSPEC_ACTION_TRAFFIC_ACTION,
FLOWSPEC_ACTION_REDIRECT,
FLOWSPEC_ACTION_TRAFFIC_MARKING,
)
# Supported action type for IPv4 and VPNv4.
action_types = {
FLOWSPEC_ACTION_TRAFFIC_RATE: BGPFlowSpecTrafficRateCommunity,
FLOWSPEC_ACTION_TRAFFIC_ACTION: BGPFlowSpecTrafficActionCommunity,
FLOWSPEC_ACTION_REDIRECT: BGPFlowSpecRedirectCommunity,
FLOWSPEC_ACTION_TRAFFIC_MARKING: BGPFlowSpecTrafficMarkingCommunity,
}
communities = []
if actions is None:
return communities
for name, action in actions.items():
cls_ = action_types.get(name, None)
if cls_:
communities.append(cls_(**action))
else:
raise ValueError(
'Unsupported flowspec action %s' % name)
return communities