diff options
author | Shinpei Muraoka <shinpei.muraoka@gmail.com> | 2017-03-24 17:10:46 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2017-03-28 10:00:10 +0900 |
commit | 880bd4ab8547c9d3cd3592aad1f81d894823ed3e (patch) | |
tree | 324b9708e231303ee146b2aed85d788452a47cb6 | |
parent | 765a723fe6c846473ced0f909cf839db8a61dbb8 (diff) |
BGPSpeaker/info_base: Add tables for Flow Specification
Signed-off-by: Shinpei Muraoka <shinpei.muraoka@gmail.com>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r-- | ryu/services/protocols/bgp/info_base/ipv4fs.py | 93 | ||||
-rw-r--r-- | ryu/services/protocols/bgp/info_base/vpnv4fs.py | 66 | ||||
-rw-r--r-- | ryu/services/protocols/bgp/info_base/vrf.py | 11 | ||||
-rw-r--r-- | ryu/services/protocols/bgp/info_base/vrf4fs.py | 60 | ||||
-rw-r--r-- | ryu/services/protocols/bgp/info_base/vrffs.py | 91 |
5 files changed, 321 insertions, 0 deletions
diff --git a/ryu/services/protocols/bgp/info_base/ipv4fs.py b/ryu/services/protocols/bgp/info_base/ipv4fs.py new file mode 100644 index 00000000..5d1a03c0 --- /dev/null +++ b/ryu/services/protocols/bgp/info_base/ipv4fs.py @@ -0,0 +1,93 @@ +# Copyright (C) 2017 Nippon Telegraph and Telephone Corporation. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" + Defines data types and models required specifically + for Ipv4 Flow Specification support. +""" + +import logging + +from ryu.lib.packet.bgp import FlowSpecIPv4NLRI +from ryu.lib.packet.bgp import RF_IPv4_FLOWSPEC + +from ryu.services.protocols.bgp.info_base.base import Path +from ryu.services.protocols.bgp.info_base.base import Table +from ryu.services.protocols.bgp.info_base.base import Destination +from ryu.services.protocols.bgp.info_base.base import NonVrfPathProcessingMixin + +LOG = logging.getLogger('bgpspeaker.info_base.ipv4fs') + + +class IPv4FlowSpecDest(Destination, NonVrfPathProcessingMixin): + """IPv4 Flow Specification Destination + + Store Flow Specification Paths. + """ + ROUTE_FAMILY = RF_IPv4_FLOWSPEC + + def _best_path_lost(self): + old_best_path = self._best_path + NonVrfPathProcessingMixin._best_path_lost(self) + self._core_service._signal_bus.best_path_changed(old_best_path, True) + + def _new_best_path(self, best_path): + NonVrfPathProcessingMixin._new_best_path(self, best_path) + self._core_service._signal_bus.best_path_changed(best_path, False) + + +class IPv4FlowSpecTable(Table): + """Global table to store IPv4 Flow Specification routing information. + + Uses `FlowSpecIpv4Dest` to store destination information for each known + Flow Specification paths. + """ + ROUTE_FAMILY = RF_IPv4_FLOWSPEC + VPN_DEST_CLASS = IPv4FlowSpecDest + + def __init__(self, core_service, signal_bus): + super(IPv4FlowSpecTable, self).__init__(None, core_service, signal_bus) + + def _table_key(self, nlri): + """Return a key that will uniquely identify this NLRI inside + this table. + """ + return nlri.prefix + + def _create_dest(self, nlri): + return self.VPN_DEST_CLASS(self, nlri) + + def __str__(self): + return '%s(scope_id: %s, rf: %s)' % ( + self.__class__.__name__, self.scope_id, self.route_family + ) + + +class IPv4FlowSpecPath(Path): + """Represents a way of reaching an IPv4 Flow Specification destination.""" + ROUTE_FAMILY = RF_IPv4_FLOWSPEC + VRF_PATH_CLASS = None # defined in init - anti cyclic import hack + NLRI_CLASS = FlowSpecIPv4NLRI + + def __init__(self, *args, **kwargs): + # Set dummy IP address. + kwargs['nexthop'] = '0.0.0.0' + super(IPv4FlowSpecPath, self).__init__(*args, **kwargs) + from ryu.services.protocols.bgp.info_base.vrf4fs import ( + Vrf4FlowSpecPath) + self.VRF_PATH_CLASS = Vrf4FlowSpecPath + # Because the IPv4 Flow Specification does not require nexthop, + # initialize with None. + self._nexthop = None diff --git a/ryu/services/protocols/bgp/info_base/vpnv4fs.py b/ryu/services/protocols/bgp/info_base/vpnv4fs.py new file mode 100644 index 00000000..e87196c2 --- /dev/null +++ b/ryu/services/protocols/bgp/info_base/vpnv4fs.py @@ -0,0 +1,66 @@ +# Copyright (C) 2017 Nippon Telegraph and Telephone Corporation. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" + Defines data types and models required specifically for + VPNv4 Flow Specification support. +""" + +import logging + +from ryu.lib.packet.bgp import FlowSpecVPNv4NLRI +from ryu.lib.packet.bgp import RF_VPNv4_FLOWSPEC + +from ryu.services.protocols.bgp.info_base.vpn import VpnDest +from ryu.services.protocols.bgp.info_base.vpn import VpnPath +from ryu.services.protocols.bgp.info_base.vpn import VpnTable + +LOG = logging.getLogger('bgpspeaker.info_base.vpnv4fs') + + +class VPNv4FlowSpecDest(VpnDest): + """VPNv4 Flow Specification Destination + + Store Flow Specification Paths. + """ + ROUTE_FAMILY = RF_VPNv4_FLOWSPEC + + +class VPNv4FlowSpecTable(VpnTable): + """Global table to store VPNv4 Flow Specification routing information. + + Uses `VPNv4FlowSpecDest` to store destination information for each known + Flow Specification paths. + """ + ROUTE_FAMILY = RF_VPNv4_FLOWSPEC + VPN_DEST_CLASS = VPNv4FlowSpecDest + + +class VPNv4FlowSpecPath(VpnPath): + """Represents a way of reaching an VPNv4 Flow Specification destination.""" + ROUTE_FAMILY = RF_VPNv4_FLOWSPEC + VRF_PATH_CLASS = None # defined in init - anti cyclic import hack + NLRI_CLASS = FlowSpecVPNv4NLRI + + def __init__(self, *args, **kwargs): + # Set dummy IP address. + kwargs['nexthop'] = '0.0.0.0' + super(VPNv4FlowSpecPath, self).__init__(*args, **kwargs) + from ryu.services.protocols.bgp.info_base.vrf4fs import( + Vrf4FlowSpecPath) + self.VRF_PATH_CLASS = Vrf4FlowSpecPath + # Because the IPv4 Flow Specification does not require nexthop, + # initialize with None. + self._nexthop = None diff --git a/ryu/services/protocols/bgp/info_base/vrf.py b/ryu/services/protocols/bgp/info_base/vrf.py index dec6b198..79940735 100644 --- a/ryu/services/protocols/bgp/info_base/vrf.py +++ b/ryu/services/protocols/bgp/info_base/vrf.py @@ -39,6 +39,7 @@ 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.services.protocols.bgp.base import OrderedDict from ryu.services.protocols.bgp.constants import VPN_TABLE @@ -167,6 +168,8 @@ 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: + 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 ip, masklen = vpn_path.nlri.prefix.split('/') @@ -523,6 +526,9 @@ 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: + nexthop = '0.0.0.0' + Path.__init__(self, source, nlri, src_ver_num, pattrs, nexthop, is_withdraw) if label_list is None: @@ -577,6 +583,11 @@ class VrfPath(Path): # Because NLRI class is the same if the route family is EVPN, # we re-use the NLRI instance. vpn_nlri = self._nlri + + elif self.ROUTE_FAMILY.safi == IP_FLOWSPEC: + vpn_nlri = self.VPN_NLRI_CLASS(route_dist=route_dist, + rules=self.nlri.rules) + else: # self.ROUTE_FAMILY in [RF_IPv4_UC, RF_IPv6_UC] ip, masklen = self._nlri.prefix.split('/') vpn_nlri = self.VPN_NLRI_CLASS(length=int(masklen), diff --git a/ryu/services/protocols/bgp/info_base/vrf4fs.py b/ryu/services/protocols/bgp/info_base/vrf4fs.py new file mode 100644 index 00000000..cfa87d9d --- /dev/null +++ b/ryu/services/protocols/bgp/info_base/vrf4fs.py @@ -0,0 +1,60 @@ +# Copyright (C) 2017 Nippon Telegraph and Telephone Corporation. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" + Defines data types and models required specifically + for VRF (for IPv4 Flow Specification) support. + Represents data structures for VRF not VPN/global. + (Inside VRF you have IPv4 Flow Specification prefixes + and inside VPN you have VPNv4 Flow Specification prefixes) +""" + +import logging + +from ryu.lib.packet.bgp import RF_IPv4_FLOWSPEC +from ryu.lib.packet.bgp import RF_VPNv4_FLOWSPEC +from ryu.lib.packet.bgp import FlowSpecIPv4NLRI +from ryu.lib.packet.bgp import FlowSpecVPNv4NLRI + +from ryu.services.protocols.bgp.info_base.vpnv4fs import VPNv4FlowSpecPath +from ryu.services.protocols.bgp.info_base.vrffs import VRFFlowSpecDest +from ryu.services.protocols.bgp.info_base.vrffs import VRFFlowSpecPath +from ryu.services.protocols.bgp.info_base.vrffs import VRFFlowSpecTable + +LOG = logging.getLogger('bgpspeaker.info_base.vrf4fs') + + +class Vrf4FlowSpecPath(VRFFlowSpecPath): + """Represents a way of reaching an IP destination with + a VPN Flow Specification. + """ + ROUTE_FAMILY = RF_IPv4_FLOWSPEC + VPN_PATH_CLASS = VPNv4FlowSpecPath + VPN_NLRI_CLASS = FlowSpecVPNv4NLRI + + +class Vrf4FlowSpecDest(VRFFlowSpecDest): + ROUTE_FAMILY = RF_IPv4_FLOWSPEC + + +class Vrf4FlowSpecTable(VRFFlowSpecTable): + """Virtual Routing and Forwarding information base + for IPv4 Flow Specification. + """ + ROUTE_FAMILY = RF_IPv4_FLOWSPEC + VPN_ROUTE_FAMILY = RF_VPNv4_FLOWSPEC + NLRI_CLASS = FlowSpecIPv4NLRI + VRF_PATH_CLASS = Vrf4FlowSpecPath + VRF_DEST_CLASS = Vrf4FlowSpecDest diff --git a/ryu/services/protocols/bgp/info_base/vrffs.py b/ryu/services/protocols/bgp/info_base/vrffs.py new file mode 100644 index 00000000..f8054a73 --- /dev/null +++ b/ryu/services/protocols/bgp/info_base/vrffs.py @@ -0,0 +1,91 @@ +# Copyright (C) 2017 Nippon Telegraph and Telephone Corporation. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" + Defines base data types and models required specifically + for VRF Flow Specification support. +""" + +import abc +import logging +import six + +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_TYPE_EXTENDED_COMMUNITIES +from ryu.lib.packet.bgp import BGPPathAttributeOrigin +from ryu.lib.packet.bgp import BGPPathAttributeAsPath +from ryu.lib.packet.bgp import BGPPathAttributeExtendedCommunities + +from ryu.services.protocols.bgp.base import OrderedDict +from ryu.services.protocols.bgp.info_base.vrf import VrfTable +from ryu.services.protocols.bgp.info_base.vrf import VrfDest +from ryu.services.protocols.bgp.info_base.vrf import VrfPath + +from ryu.services.protocols.bgp.utils.bgp import create_rt_extended_community + +LOG = logging.getLogger('bgpspeaker.info_base.vrffs') + + +@six.add_metaclass(abc.ABCMeta) +class VRFFlowSpecTable(VrfTable): + """Virtual Routing and Forwarding information base. + Keeps destination imported to given VRF Flow Specification + in represents. + """ + def insert_vrffs_path(self, nlri, communities, is_withdraw=False): + assert nlri + assert isinstance(communities, list) + vrf_conf = self.vrf_conf + + from ryu.services.protocols.bgp.core import EXPECTED_ORIGIN + pattrs = OrderedDict() + pattrs[BGP_ATTR_TYPE_ORIGIN] = BGPPathAttributeOrigin( + EXPECTED_ORIGIN) + pattrs[BGP_ATTR_TYPE_AS_PATH] = BGPPathAttributeAsPath([]) + + for rt in vrf_conf.export_rts: + communities.append(create_rt_extended_community(rt, 2)) + for soo in vrf_conf.soo_list: + communities.append(create_rt_extended_community(soo, 3)) + + pattrs[BGP_ATTR_TYPE_EXTENDED_COMMUNITIES] = ( + BGPPathAttributeExtendedCommunities(communities=communities)) + + puid = self.VRF_PATH_CLASS.create_puid( + vrf_conf.route_dist, nlri.prefix) + + path = self.VRF_PATH_CLASS( + puid, None, nlri, 0, + pattrs=pattrs, is_withdraw=is_withdraw + ) + + # Insert the path into VRF table, get affected destination so that we + # can process it further. + eff_dest = self.insert(path) + # Enqueue the eff_dest for further processing. + self._signal_bus.dest_changed(eff_dest) + + +@six.add_metaclass(abc.ABCMeta) +class VRFFlowSpecDest(VrfDest): + """Base class for VRF Flow Specification.""" + + +@six.add_metaclass(abc.ABCMeta) +class VRFFlowSpecPath(VrfPath): + """Represents a way of reaching an IP destination with + a VPN Flow Specification. + """ |