Signed-off-by: Satoshi Fujimoto <[email protected]>
---
 ryu/services/protocols/bgp/api/prefix.py           |  6 ++
 ryu/services/protocols/bgp/base.py                 |  4 +
 ryu/services/protocols/bgp/bgp_sample_conf.py      | 85 +++++++++++++++++++++-
 ryu/services/protocols/bgp/bgpspeaker.py           | 43 ++++++++---
 .../protocols/bgp/core_managers/table_manager.py   | 79 +++++++++++++++++++-
 ryu/services/protocols/bgp/model.py                |  8 +-
 ryu/services/protocols/bgp/rtconf/base.py          | 20 +++++
 ryu/services/protocols/bgp/rtconf/neighbors.py     | 29 ++++++++
 ryu/services/protocols/bgp/rtconf/vrfs.py          |  7 ++
 ryu/services/protocols/bgp/utils/bgp.py            | 35 +++++++++
 10 files changed, 302 insertions(+), 14 deletions(-)

diff --git a/ryu/services/protocols/bgp/api/prefix.py 
b/ryu/services/protocols/bgp/api/prefix.py
index c169ed8..1a4207a 100644
--- a/ryu/services/protocols/bgp/api/prefix.py
+++ b/ryu/services/protocols/bgp/api/prefix.py
@@ -27,7 +27,9 @@ 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 FlowSpecIPv6NLRI
 from ryu.lib.packet.bgp import FlowSpecVPNv4NLRI
+from ryu.lib.packet.bgp import FlowSpecVPNv6NLRI
 from ryu.lib.packet.bgp import BGPFlowSpecTrafficRateCommunity
 from ryu.lib.packet.bgp import BGPFlowSpecTrafficActionCommunity
 from ryu.lib.packet.bgp import BGPFlowSpecRedirectCommunity
@@ -103,10 +105,14 @@ SUPPORTED_EVPN_ROUTE_TYPES = [
 
 # Constants used in API calls for Flow Specification
 FLOWSPEC_FAMILY_IPV4 = FlowSpecIPv4NLRI.FLOWSPEC_FAMILY
+FLOWSPEC_FAMILY_IPV6 = FlowSpecIPv6NLRI.FLOWSPEC_FAMILY
 FLOWSPEC_FAMILY_VPNV4 = FlowSpecVPNv4NLRI.FLOWSPEC_FAMILY
+FLOWSPEC_FAMILY_VPNV6 = FlowSpecVPNv6NLRI.FLOWSPEC_FAMILY
 SUPPORTED_FLOWSPEC_FAMILIES = (
     FLOWSPEC_FAMILY_IPV4,
+    FLOWSPEC_FAMILY_IPV6,
     FLOWSPEC_FAMILY_VPNV4,
+    FLOWSPEC_FAMILY_VPNV6,
 )
 
 # Constants for the Traffic Filtering Actions of Flow Specification
diff --git a/ryu/services/protocols/bgp/base.py 
b/ryu/services/protocols/bgp/base.py
index e546902..0dc8607 100644
--- a/ryu/services/protocols/bgp/base.py
+++ b/ryu/services/protocols/bgp/base.py
@@ -37,7 +37,9 @@ 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_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_RTC_UC
 from ryu.services.protocols.bgp.utils.circlist import CircularListType
 from ryu.services.protocols.bgp.utils.evtlet import LoopingCall
@@ -59,7 +61,9 @@ SUPPORTED_GLOBAL_RF = {
     RF_IPv6_VPN,
     RF_L2_EVPN,
     RF_IPv4_FLOWSPEC,
+    RF_IPv6_FLOWSPEC,
     RF_VPNv4_FLOWSPEC,
+    RF_VPNv6_FLOWSPEC,
 }
 
 
diff --git a/ryu/services/protocols/bgp/bgp_sample_conf.py 
b/ryu/services/protocols/bgp/bgp_sample_conf.py
index 01afd48..3f34fbd 100644
--- a/ryu/services/protocols/bgp/bgp_sample_conf.py
+++ b/ryu/services/protocols/bgp/bgp_sample_conf.py
@@ -4,6 +4,7 @@ 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 RF_VPNV6_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
@@ -14,7 +15,9 @@ 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_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_TA_SAMPLE
 from ryu.services.protocols.bgp.bgpspeaker import FLOWSPEC_TA_TERMINAL
 from ryu.services.protocols.bgp.bgpspeaker import REDUNDANCY_MODE_SINGLE_ACTIVE
@@ -54,7 +57,9 @@ BGP = {
             'address': '172.17.0.4',
             'remote_as': 65001,
             'enable_ipv4fs': True,
+            'enable_ipv6fs': True,
             'enable_vpnv4fs': True,
+            'enable_vpnv6fs': True,
         },
     ],
 
@@ -83,13 +88,20 @@ BGP = {
             'export_rts': ['65001:200'],
             'route_family': RF_L2_EVPN,
         },
-        # Example of VRF for FlowSpec
+        # Example of VRF for IPv4 FlowSpec
         {
             'route_dist': '65001:250',
             'import_rts': ['65001:250'],
             'export_rts': ['65001:250'],
             'route_family': RF_VPNV4_FLOWSPEC,
         },
+        # Example of VRF for IPv6 FlowSpec
+        {
+            'route_dist': '65001:300',
+            'import_rts': ['65001:300'],
+            'export_rts': ['65001:300'],
+            'route_family': RF_VPNV6_FLOWSPEC,
+        },
     ],
 
     # List of BGP routes.
@@ -236,6 +248,77 @@ BGP = {
                 }
             },
         },
+        # Example of Flow Specification IPv6 prefix
+        {
+            'flowspec_family': FLOWSPEC_FAMILY_IPV6,
+            'rules': {
+                'dst_prefix': '2001::1/128/32',
+                'src_prefix': '3001::2/128',
+                'next_header': 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',
+                'flow_label': 100,
+            },
+            '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 VPNv6 prefix
+        {
+            'flowspec_family': FLOWSPEC_FAMILY_VPNV6,
+            'route_dist': '65001:300',
+            'rules': {
+                'dst_prefix': '2001::1/128/32',
+                'src_prefix': '3001::2/128',
+                'next_header': 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',
+                'flow_label': 100,
+            },
+            '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,
+                }
+            },
+        },
     ],
 }
 
diff --git a/ryu/services/protocols/bgp/bgpspeaker.py 
b/ryu/services/protocols/bgp/bgpspeaker.py
index 4965da8..3c8d645 100644
--- a/ryu/services/protocols/bgp/bgpspeaker.py
+++ b/ryu/services/protocols/bgp/bgpspeaker.py
@@ -58,6 +58,8 @@ from ryu.services.protocols.bgp.api.prefix import (
     FLOWSPEC_FAMILY,
     FLOWSPEC_FAMILY_IPV4,
     FLOWSPEC_FAMILY_VPNV4,
+    FLOWSPEC_FAMILY_IPV6,
+    FLOWSPEC_FAMILY_VPNV6,
     FLOWSPEC_RULES,
     FLOWSPEC_ACTIONS)
 from ryu.services.protocols.bgp.rtconf.common import LOCAL_AS
@@ -82,18 +84,24 @@ 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_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_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
 from ryu.services.protocols.bgp.rtconf.base import SITE_OF_ORIGINS
-from ryu.services.protocols.bgp.rtconf.neighbors import DEFAULT_CAP_MBGP_IPV4
-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_MBGP_IPV4,
+    DEFAULT_CAP_MBGP_IPV6,
+    DEFAULT_CAP_MBGP_VPNV4,
+    DEFAULT_CAP_MBGP_VPNV6,
+    DEFAULT_CAP_MBGP_EVPN,
+    DEFAULT_CAP_MBGP_IPV4FS,
+    DEFAULT_CAP_MBGP_IPV6FS,
+    DEFAULT_CAP_MBGP_VPNV4FS,
+    DEFAULT_CAP_MBGP_VPNV6FS,
+)
 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
@@ -122,6 +130,7 @@ 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
+RF_VPNV6_FLOWSPEC = vrfs.VRF_RF_IPV6_FLOWSPEC
 
 # Constants for the Traffic Filtering Actions of Flow Specification.
 FLOWSPEC_TA_SAMPLE = BGPFlowSpecTrafficActionCommunity.SAMPLE
@@ -354,7 +363,9 @@ class BGPSpeaker(object):
                      enable_vpnv6=DEFAULT_CAP_MBGP_VPNV6,
                      enable_evpn=DEFAULT_CAP_MBGP_EVPN,
                      enable_ipv4fs=DEFAULT_CAP_MBGP_IPV4FS,
+                     enable_ipv6fs=DEFAULT_CAP_MBGP_IPV6FS,
                      enable_vpnv4fs=DEFAULT_CAP_MBGP_VPNV4FS,
+                     enable_vpnv6fs=DEFAULT_CAP_MBGP_VPNV6FS,
                      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,
@@ -394,9 +405,15 @@ class BGPSpeaker(object):
         ``enable_ipv4fs`` enables IPv4 Flow Specification address family
         for this neighbor.
 
+        ``enable_ipv6fs`` enables IPv6 Flow Specification address family
+        for this neighbor.
+
         ``enable_vpnv4fs`` enables VPNv4 Flow Specification address family
         for this neighbor.
 
+        ``enable_vpnv6fs`` enables VPNv6 Flow Specification address family
+        for this neighbor.
+
         ``enable_enhanced_refresh`` enables Enhanced Route Refresh for this
         neighbor.
 
@@ -457,7 +474,9 @@ class BGPSpeaker(object):
             CAP_MBGP_VPNV6: enable_vpnv6,
             CAP_MBGP_EVPN: enable_evpn,
             CAP_MBGP_IPV4FS: enable_ipv4fs,
+            CAP_MBGP_IPV6FS: enable_ipv6fs,
             CAP_MBGP_VPNV4FS: enable_vpnv4fs,
+            CAP_MBGP_VPNV6FS: enable_vpnv6fs,
         }
 
         if multi_exit_disc:
@@ -821,7 +840,9 @@ class BGPSpeaker(object):
         This parameter must be one of the following.
 
         - FLOWSPEC_FAMILY_IPV4  = 'ipv4fs'
+        - FLOWSPEC_FAMILY_IPV6  = 'ipv6fs'
         - FLOWSPEC_FAMILY_VPNV4 = 'vpnv4fs'
+        - FLOWSPEC_FAMILY_VPNV6 = 'vpnv6fs'
 
         ``rules`` specifies NLRIs of Flow Specification as
         a dictionary type value.
@@ -829,13 +850,16 @@ class BGPSpeaker(object):
         see `from_user()` method of the following classes.
 
         - :py:mod:`ryu.lib.packet.bgp.FlowSpecIPv4NLRI`
+        - :py:mod:`ryu.lib.packet.bgp.FlowSpecIPv6NLRI`
         - :py:mod:`ryu.lib.packet.bgp.FlowSpecVPNv4NLRI`
+        - :py:mod:`ryu.lib.packet.bgp.FlowSpecVPNv6NLRI`
 
         ``route_dist`` specifies a route distinguisher value.
         This parameter is required only if flowspec_family is one of the
         following address family.
 
         - FLOWSPEC_FAMILY_VPNV4 = 'vpnv4fs'
+        - FLOWSPEC_FAMILY_VPNV6 = 'vpnv6fs'
 
         ``actions`` specifies Traffic Filtering Actions of
         Flow Specification as a dictionary type value.
@@ -903,7 +927,7 @@ class BGPSpeaker(object):
             FLOWSPEC_ACTIONS: actions or {},
         }
 
-        if flowspec_family == FLOWSPEC_FAMILY_VPNV4:
+        if flowspec_family in [FLOWSPEC_FAMILY_VPNV4, FLOWSPEC_FAMILY_VPNV6]:
             func_name = 'flowspec.add_local'
             kwargs.update({ROUTE_DISTINGUISHER: route_dist})
 
@@ -927,7 +951,7 @@ class BGPSpeaker(object):
             FLOWSPEC_RULES: rules,
         }
 
-        if flowspec_family == FLOWSPEC_FAMILY_VPNV4:
+        if flowspec_family in [FLOWSPEC_FAMILY_VPNV4, FLOWSPEC_FAMILY_VPNV6]:
             func_name = 'flowspec.del_local'
             kwargs.update({ROUTE_DISTINGUISHER: route_dist})
 
@@ -953,6 +977,7 @@ class BGPSpeaker(object):
         - RF_VPN_V6           = 'ipv6'
         - RF_L2_EVPN          = 'evpn'
         - RF_VPNV4_FLOWSPEC   = 'ipv4fs'
+        - RF_VPNV6_FLOWSPEC   = 'ipv6fs'
 
         ``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 297b7a4..27e0bd3 100644
--- a/ryu/services/protocols/bgp/core_managers/table_manager.py
+++ b/ryu/services/protocols/bgp/core_managers/table_manager.py
@@ -19,12 +19,18 @@ 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.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.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 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.lib import type_desc
 from ryu.lib.packet.bgp import RF_IPv4_UC
@@ -33,7 +39,9 @@ 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_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_RTC_UC
 from ryu.lib.packet.bgp import BGPPathAttributeOrigin
 from ryu.lib.packet.bgp import BGPPathAttributeAsPath
@@ -50,6 +58,7 @@ 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.lib.packet.bgp import FlowSpecIPv6NLRI
 
 from ryu.services.protocols.bgp.utils.validation import is_valid_ipv4
 from ryu.services.protocols.bgp.utils.validation import is_valid_ipv4_prefix
@@ -132,6 +141,8 @@ class TableCoreManager(object):
             vpn_table = self.get_evpn_table()
         elif vrf_table.route_family == Vrf4FlowSpecTable.ROUTE_FAMILY:
             vpn_table = self.get_vpnv4fs_table()
+        elif vrf_table.route_family == Vrf6FlowSpecTable.ROUTE_FAMILY:
+            vpn_table = self.get_vpnv6fs_table()
         else:
             raise ValueError('Invalid VRF table route family: %s' %
                              vrf_table.route_family)
@@ -200,8 +211,12 @@ class TableCoreManager(object):
             global_table = self.get_evpn_table()
         elif route_family == RF_IPv4_FLOWSPEC:
             global_table = self.get_ipv4fs_table()
+        elif route_family == RF_IPv6_FLOWSPEC:
+            global_table = self.get_ipv6fs_table()
         elif route_family == RF_VPNv4_FLOWSPEC:
             global_table = self.get_vpnv4fs_table()
+        elif route_family == RF_VPNv6_FLOWSPEC:
+            global_table = self.get_vpnv6fs_table()
         elif route_family == RF_RTC_UC:
             global_table = self.get_rtc_table()
 
@@ -327,6 +342,21 @@ class TableCoreManager(object):
 
         return ipv4fs_table
 
+    def get_ipv6fs_table(self):
+        """Returns global IPv6 Flow Specification table.
+
+        Creates the table if it does not exist.
+        """
+        ipv6fs_table = self._global_tables.get(RF_IPv6_FLOWSPEC)
+        # Lazy initialization of the table.
+        if not ipv6fs_table:
+            ipv6fs_table = IPv6FlowSpecTable(self._core_service,
+                                             self._signal_bus)
+            self._global_tables[RF_IPv6_FLOWSPEC] = ipv6fs_table
+            self._tables[(None, RF_IPv6_FLOWSPEC)] = ipv6fs_table
+
+        return ipv6fs_table
+
     def get_vpnv4fs_table(self):
         """Returns global VPNv4 Flow Specification table.
 
@@ -342,6 +372,21 @@ class TableCoreManager(object):
 
         return vpnv4fs_table
 
+    def get_vpnv6fs_table(self):
+        """Returns global VPNv6 Flow Specification table.
+
+        Creates the table if it does not exist.
+        """
+        vpnv6fs_table = self._global_tables.get(RF_VPNv6_FLOWSPEC)
+        # Lazy initialization of the table.
+        if not vpnv6fs_table:
+            vpnv6fs_table = VPNv6FlowSpecTable(self._core_service,
+                                               self._signal_bus)
+            self._global_tables[RF_VPNv6_FLOWSPEC] = vpnv6fs_table
+            self._tables[(None, RF_VPNv6_FLOWSPEC)] = vpnv6fs_table
+
+        return vpnv6fs_table
+
     def get_nexthop_label(self, label_key):
         return self._next_hop_label.get(label_key, None)
 
@@ -423,6 +468,8 @@ class TableCoreManager(object):
             vrf_table = VrfEvpnTable
         elif route_family == VRF_RF_IPV4_FLOWSPEC:
             vrf_table = Vrf4FlowSpecTable
+        elif route_family == VRF_RF_IPV6_FLOWSPEC:
+            vrf_table = Vrf6FlowSpecTable
         else:
             raise ValueError('Unsupported route family for VRF: %s' %
                              route_family)
@@ -508,6 +555,8 @@ class TableCoreManager(object):
             route_family = RF_L2_EVPN
         elif vpn_path.route_family == RF_VPNv4_FLOWSPEC:
             route_family = RF_IPv4_FLOWSPEC
+        elif vpn_path.route_family == RF_VPNv6_FLOWSPEC:
+            route_family = RF_IPv6_FLOWSPEC
         else:
             raise ValueError('Unsupported route family for VRF: %s' %
                              vpn_path.route_family)
@@ -650,7 +699,10 @@ class TableCoreManager(object):
         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
+        from ryu.services.protocols.bgp.api.prefix import (
+            FLOWSPEC_FAMILY_VPNV4,
+            FLOWSPEC_FAMILY_VPNV6,
+        )
 
         if flowspec_family == FLOWSPEC_FAMILY_VPNV4:
             vrf_table = self._tables.get((route_dist, VRF_RF_IPV4_FLOWSPEC))
@@ -659,6 +711,13 @@ class TableCoreManager(object):
                 communities = create_v4flowspec_actions(actions)
             except ValueError as e:
                 raise BgpCoreError(desc=str(e))
+        elif flowspec_family == FLOWSPEC_FAMILY_VPNV6:
+            vrf_table = self._tables.get((route_dist, VRF_RF_IPV6_FLOWSPEC))
+            prefix = FlowSpecIPv6NLRI.from_user(**rules)
+            try:
+                communities = create_v6flowspec_actions(actions)
+            except ValueError as e:
+                raise BgpCoreError(desc=str(e))
         else:
             raise BgpCoreError(
                 desc='Unsupported flowspec_family %s' % flowspec_family)
@@ -732,7 +791,10 @@ class TableCoreManager(object):
         """
 
         from ryu.services.protocols.bgp.core import BgpCoreError
-        from ryu.services.protocols.bgp.api.prefix import FLOWSPEC_FAMILY_IPV4
+        from ryu.services.protocols.bgp.api.prefix import (
+            FLOWSPEC_FAMILY_IPV4,
+            FLOWSPEC_FAMILY_IPV6,
+        )
 
         src_ver_num = 1
         peer = None
@@ -758,6 +820,19 @@ class TableCoreManager(object):
                 pathattrs[BGP_ATTR_TYPE_EXTENDED_COMMUNITIES] = (
                     BGPPathAttributeExtendedCommunities(
                         communities=communities))
+        elif flowspec_family == FLOWSPEC_FAMILY_IPV6:
+            _nlri = FlowSpecIPv6NLRI.from_user(**rules)
+            p = IPv6FlowSpecPath
+
+            try:
+                communities = create_v6flowspec_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)
diff --git a/ryu/services/protocols/bgp/model.py 
b/ryu/services/protocols/bgp/model.py
index 6739139..faa33f0 100644
--- a/ryu/services/protocols/bgp/model.py
+++ b/ryu/services/protocols/bgp/model.py
@@ -97,11 +97,15 @@ 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
+        from ryu.services.protocols.bgp.info_base.vrf4fs import (
+            Vrf4FlowSpecPath)
+        from ryu.services.protocols.bgp.info_base.vrf6fs import (
+            Vrf6FlowSpecPath)
         assert path.route_family in (Vrf4Path.ROUTE_FAMILY,
                                      Vrf6Path.ROUTE_FAMILY,
                                      VrfEvpnPath.ROUTE_FAMILY,
-                                     Vrf4FlowSpecPath.ROUTE_FAMILY)
+                                     Vrf4FlowSpecPath.ROUTE_FAMILY,
+                                     Vrf6FlowSpecPath.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 bdd4309..d839d38 100644
--- a/ryu/services/protocols/bgp/rtconf/base.py
+++ b/ryu/services/protocols/bgp/rtconf/base.py
@@ -47,7 +47,9 @@ 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_IPV6FS = 'cap_mbgp_ipv6fs'
 CAP_MBGP_VPNV4FS = 'cap_mbgp_vpnv4fs'
+CAP_MBGP_VPNV6FS = 'cap_mbgp_vpnv6fs'
 CAP_RTC = 'cap_rtc'
 RTC_AS = 'rtc_as'
 HOLD_TIME = 'hold_time'
@@ -659,6 +661,15 @@ def validate_cap_mbgp_ipv4fs(cmv4fs):
     return cmv4fs
 
 
+@validate(name=CAP_MBGP_IPV6FS)
+def validate_cap_mbgp_ipv6fs(cmv6fs):
+    if not isinstance(cmv6fs, bool):
+        raise ConfigTypeError(desc='Invalid MP-BGP '
+                              'IPv6 Flow Specification capability '
+                              'settings: %s. Boolean value expected' % cmv6fs)
+    return cmv6fs
+
+
 @validate(name=CAP_MBGP_VPNV4FS)
 def validate_cap_mbgp_vpnv4fs(cmv4fs):
     if not isinstance(cmv4fs, bool):
@@ -668,6 +679,15 @@ def validate_cap_mbgp_vpnv4fs(cmv4fs):
     return cmv4fs
 
 
+@validate(name=CAP_MBGP_VPNV6FS)
+def validate_cap_mbgp_vpnv66fs(cmv6fs):
+    if not isinstance(cmv6fs, bool):
+        raise ConfigTypeError(desc='Invalid MP-BGP '
+                              'VPNv6 Flow Specification capability '
+                              'settings: %s. Boolean value expected' % cmv6fs)
+    return cmv6fs
+
+
 @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 987d4da..d99e509 100644
--- a/ryu/services/protocols/bgp/rtconf/neighbors.py
+++ b/ryu/services/protocols/bgp/rtconf/neighbors.py
@@ -28,7 +28,9 @@ 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_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_RTC_UC
 from ryu.lib.packet.bgp import BGPOptParamCapabilityFourOctetAsNumber
 from ryu.lib.packet.bgp import BGPOptParamCapabilityEnhancedRouteRefresh
@@ -51,7 +53,9 @@ 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_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_REFRESH
 from ryu.services.protocols.bgp.rtconf.base import CAP_RTC
 from ryu.services.protocols.bgp.rtconf.base import compute_optional_conf
@@ -110,7 +114,9 @@ DEFAULT_CAP_MBGP_VPNV4 = False
 DEFAULT_CAP_MBGP_VPNV6 = False
 DEFAULT_CAP_MBGP_EVPN = False
 DEFAULT_CAP_MBGP_IPV4FS = False
+DEFAULT_CAP_MBGP_IPV6FS = False
 DEFAULT_CAP_MBGP_VPNV4FS = False
+DEFAULT_CAP_MBGP_VPNV6FS = False
 DEFAULT_HOLD_TIME = 40
 DEFAULT_ENABLED = True
 DEFAULT_CAP_RTC = False
@@ -325,6 +331,7 @@ class NeighborConf(ConfWithId, ConfWithStats):
                                    CAP_MBGP_VPNV4, CAP_MBGP_VPNV6,
                                    CAP_RTC, CAP_MBGP_EVPN,
                                    CAP_MBGP_IPV4FS, CAP_MBGP_VPNV4FS,
+                                   CAP_MBGP_IPV6FS, CAP_MBGP_VPNV6FS,
                                    RTC_AS, HOLD_TIME,
                                    ENABLED, MULTI_EXIT_DISC, MAX_PREFIXES,
                                    ADVERTISE_PEER_AS, SITE_OF_ORIGINS,
@@ -359,8 +366,12 @@ class NeighborConf(ConfWithId, ConfWithStats):
             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_IPV6FS] = compute_optional_conf(
+            CAP_MBGP_IPV6FS, DEFAULT_CAP_MBGP_IPV6FS, **kwargs)
         self._settings[CAP_MBGP_VPNV4FS] = compute_optional_conf(
             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[HOLD_TIME] = compute_optional_conf(
             HOLD_TIME, DEFAULT_HOLD_TIME, **kwargs)
         self._settings[ENABLED] = compute_optional_conf(
@@ -535,10 +546,18 @@ class NeighborConf(ConfWithId, ConfWithStats):
         return self._settings[CAP_MBGP_IPV4FS]
 
     @property
+    def cap_mbgp_ipv6fs(self):
+        return self._settings[CAP_MBGP_IPV6FS]
+
+    @property
     def cap_mbgp_vpnv4fs(self):
         return self._settings[CAP_MBGP_VPNV4FS]
 
     @property
+    def cap_mbgp_vpnv6fs(self):
+        return self._settings[CAP_MBGP_VPNV6FS]
+
+    @property
     def cap_rtc(self):
         return self._settings[CAP_RTC]
 
@@ -667,11 +686,21 @@ class NeighborConf(ConfWithId, ConfWithStats):
                 BGPOptParamCapabilityMultiprotocol(
                     RF_IPv4_FLOWSPEC.afi, RF_IPv4_FLOWSPEC.safi))
 
+        if self.cap_mbgp_ipv6fs:
+            mbgp_caps.append(
+                BGPOptParamCapabilityMultiprotocol(
+                    RF_IPv6_FLOWSPEC.afi, RF_IPv6_FLOWSPEC.safi))
+
         if self.cap_mbgp_vpnv4fs:
             mbgp_caps.append(
                 BGPOptParamCapabilityMultiprotocol(
                     RF_VPNv4_FLOWSPEC.afi, RF_VPNv4_FLOWSPEC.safi))
 
+        if self.cap_mbgp_vpnv6fs:
+            mbgp_caps.append(
+                BGPOptParamCapabilityMultiprotocol(
+                    RF_VPNv6_FLOWSPEC.afi, RF_VPNv6_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 9106a0d..a918c5b 100644
--- a/ryu/services/protocols/bgp/rtconf/vrfs.py
+++ b/ryu/services/protocols/bgp/rtconf/vrfs.py
@@ -24,6 +24,7 @@ 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.lib.packet.bgp import RF_IPv6_FLOWSPEC
 
 from ryu.services.protocols.bgp.utils import validation
 from ryu.services.protocols.bgp.base import get_validator
@@ -61,11 +62,13 @@ VRF_RF_IPV4 = 'ipv4'
 VRF_RF_IPV6 = 'ipv6'
 VRF_RF_L2_EVPN = 'evpn'
 VRF_RF_IPV4_FLOWSPEC = 'ipv4fs'
+VRF_RF_IPV6_FLOWSPEC = 'ipv6fs'
 SUPPORTED_VRF_RF = (
     VRF_RF_IPV4,
     VRF_RF_IPV6,
     VRF_RF_L2_EVPN,
     VRF_RF_IPV4_FLOWSPEC,
+    VRF_RF_IPV6_FLOWSPEC,
 )
 
 
@@ -235,6 +238,8 @@ class VrfConf(ConfWithId, ConfWithStats):
             return RF_L2_EVPN
         elif vrf_rf == VRF_RF_IPV4_FLOWSPEC:
             return RF_IPv4_FLOWSPEC
+        elif vrf_rf == VRF_RF_IPV6_FLOWSPEC:
+            return RF_IPv6_FLOWSPEC
         else:
             raise ValueError('Unsupported VRF route family given %s' % vrf_rf)
 
@@ -248,6 +253,8 @@ class VrfConf(ConfWithId, ConfWithStats):
             return VRF_RF_L2_EVPN
         elif route_family == RF_IPv4_FLOWSPEC:
             return VRF_RF_IPV4_FLOWSPEC
+        elif route_family == RF_IPv6_FLOWSPEC:
+            return VRF_RF_IPV6_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 5aa2012..2d06694 100644
--- a/ryu/services/protocols/bgp/utils/bgp.py
+++ b/ryu/services/protocols/bgp/utils/bgp.py
@@ -29,7 +29,9 @@ from ryu.lib.packet.bgp import (
     RF_IPv6_VPN,
     RF_L2_EVPN,
     RF_IPv4_FLOWSPEC,
+    RF_IPv6_FLOWSPEC,
     RF_VPNv4_FLOWSPEC,
+    RF_VPNv6_FLOWSPEC,
     RF_RTC_UC,
     RouteTargetMembershipNLRI,
     BGP_ATTR_TYPE_MULTI_EXIT_DISC,
@@ -55,7 +57,9 @@ 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.ipv6fs import IPv6FlowSpecPath
 from ryu.services.protocols.bgp.info_base.vpnv4fs import VPNv4FlowSpecPath
+from ryu.services.protocols.bgp.info_base.vpnv6fs import VPNv6FlowSpecPath
 
 
 LOG = logging.getLogger('utils.bgp')
@@ -67,7 +71,9 @@ _ROUTE_FAMILY_TO_PATH_MAP = {RF_IPv4_UC: Ipv4Path,
                              RF_IPv6_VPN: Vpnv6Path,
                              RF_L2_EVPN: EvpnPath,
                              RF_IPv4_FLOWSPEC: IPv4FlowSpecPath,
+                             RF_IPv6_FLOWSPEC: IPv6FlowSpecPath,
                              RF_VPNv4_FLOWSPEC: VPNv4FlowSpecPath,
+                             RF_VPNv6_FLOWSPEC: VPNv6FlowSpecPath,
                              RF_RTC_UC: RtcPath}
 
 
@@ -215,6 +221,35 @@ def create_v4flowspec_actions(actions=None):
         FLOWSPEC_ACTION_TRAFFIC_MARKING: BGPFlowSpecTrafficMarkingCommunity,
     }
 
+    return _create_actions(actions, action_types)
+
+
+def create_v6flowspec_actions(actions=None):
+    """
+    Create list of traffic filtering actions
+    for Ipv6 Flow Specification and VPNv6 Flow Specification.
+
+    "FLOWSPEC_ACTION_REDIRECT_IPV6" is not implemented yet.
+    """
+    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 IPv6 and VPNv6.
+    action_types = {
+        FLOWSPEC_ACTION_TRAFFIC_RATE: BGPFlowSpecTrafficRateCommunity,
+        FLOWSPEC_ACTION_TRAFFIC_ACTION: BGPFlowSpecTrafficActionCommunity,
+        FLOWSPEC_ACTION_REDIRECT: BGPFlowSpecRedirectCommunity,
+        FLOWSPEC_ACTION_TRAFFIC_MARKING: BGPFlowSpecTrafficMarkingCommunity,
+    }
+
+    return _create_actions(actions, action_types)
+
+
+def _create_actions(actions, action_types):
     communities = []
 
     if actions is None:
-- 
2.7.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to