summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ryu/services/protocols/bgp/api/rtconf.py45
-rw-r--r--ryu/services/protocols/bgp/bgpspeaker.py29
-rw-r--r--ryu/services/protocols/bgp/constants.py6
-rw-r--r--ryu/services/protocols/bgp/core_managers/configuration_manager.py8
-rw-r--r--ryu/services/protocols/bgp/info_base/base.py8
-rw-r--r--ryu/services/protocols/bgp/peer.py60
6 files changed, 122 insertions, 34 deletions
diff --git a/ryu/services/protocols/bgp/api/rtconf.py b/ryu/services/protocols/bgp/api/rtconf.py
index ce989037..079a2f52 100644
--- a/ryu/services/protocols/bgp/api/rtconf.py
+++ b/ryu/services/protocols/bgp/api/rtconf.py
@@ -29,6 +29,7 @@ from ryu.services.protocols.bgp.rtconf.vrfs import ROUTE_DISTINGUISHER
from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF
from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_IPV4
from ryu.services.protocols.bgp.rtconf.vrfs import VrfConf
+from ryu.services.protocols.bgp import constants as const
LOG = logging.getLogger('bgpspeaker.api.rtconf')
@@ -152,22 +153,50 @@ def set_neighbor_in_filter(neigh_ip_address, filters):
@RegisterWithArgChecks(name='neighbor.attribute_map.set',
req_args=[neighbors.IP_ADDRESS,
- neighbors.ATTRIBUTE_MAP])
-def set_neighbor_attribute_map(neigh_ip_address, attribute_maps):
- """Returns a neighbor attribute_map for given ip address if exists."""
+ neighbors.ATTRIBUTE_MAP],
+ opt_args=[ROUTE_DISTINGUISHER, VRF_RF])
+def set_neighbor_attribute_map(neigh_ip_address, at_maps,
+ route_dist=None, route_family=VRF_RF_IPV4):
+ """set attribute_maps to the neighbor."""
core = CORE_MANAGER.get_core_service()
peer = core.peer_manager.get_by_addr(neigh_ip_address)
- peer.attribute_maps = attribute_maps
+
+ at_maps_key = const.ATTR_MAPS_LABEL_DEFAULT
+ at_maps_dict = {}
+
+ if route_dist is not None:
+ vrf_conf =\
+ CORE_MANAGER.vrfs_conf.get_vrf_conf(route_dist, route_family)
+ if vrf_conf:
+ at_maps_key = ':'.join([route_dist, route_family])
+ else:
+ raise RuntimeConfigError(desc='No VrfConf with rd %s' %
+ route_dist)
+
+ at_maps_dict[const.ATTR_MAPS_LABEL_KEY] = at_maps_key
+ at_maps_dict[const.ATTR_MAPS_VALUE] = at_maps
+ peer.attribute_maps = at_maps_dict
+
return True
@RegisterWithArgChecks(name='neighbor.attribute_map.get',
- req_args=[neighbors.IP_ADDRESS])
-def get_neighbor_attribute_map(neigh_ip_address):
+ req_args=[neighbors.IP_ADDRESS],
+ opt_args=[ROUTE_DISTINGUISHER, VRF_RF])
+def get_neighbor_attribute_map(neigh_ip_address, route_dist=None,
+ route_family=VRF_RF_IPV4):
"""Returns a neighbor attribute_map for given ip address if exists."""
core = CORE_MANAGER.get_core_service()
- ret = core.peer_manager.get_by_addr(neigh_ip_address).attribute_maps
- return ret
+ peer = core.peer_manager.get_by_addr(neigh_ip_address)
+ at_maps_key = const.ATTR_MAPS_LABEL_DEFAULT
+
+ if route_dist is not None:
+ at_maps_key = ':'.join([route_dist, route_family])
+ at_maps = peer.attribute_maps.get(at_maps_key)
+ if at_maps:
+ return at_maps.get(const.ATTR_MAPS_ORG_KEY)
+ else:
+ return []
# =============================================================================
# VRF configuration related APIs
diff --git a/ryu/services/protocols/bgp/bgpspeaker.py b/ryu/services/protocols/bgp/bgpspeaker.py
index 9844e087..59e781ce 100644
--- a/ryu/services/protocols/bgp/bgpspeaker.py
+++ b/ryu/services/protocols/bgp/bgpspeaker.py
@@ -526,7 +526,8 @@ class BGPSpeaker(object):
param['port'] = port
call(func_name, **param)
- def attribute_map_set(self, address, attribute_maps):
+ def attribute_map_set(self, address, attribute_maps,
+ route_dist=None, route_family=RF_VPN_V4):
"""This method sets attribute mapping to a neighbor.
attribute mapping can be used when you want to apply
attribute to BGPUpdate under specific conditions.
@@ -537,6 +538,12 @@ class BGPSpeaker(object):
before paths are advertised. All the items in the list must
be an instance of AttributeMap class
+ ``route_dist`` specifies route dist in which attribute_maps
+ are added.
+
+ ``route_family`` specifies route family of the VRF.
+ This parameter must be RF_VPN_V4 or RF_VPN_V6.
+
We can set AttributeMap to a neighbor as follows;
pref_filter = PrefixFilter('192.168.103.0/30',
@@ -549,24 +556,42 @@ class BGPSpeaker(object):
"""
+ assert route_family in (RF_VPN_V4, RF_VPN_V6),\
+ 'route_family must be RF_VPN_V4 or RF_VPN_V6'
+
func_name = 'neighbor.attribute_map.set'
param = {}
param[neighbors.IP_ADDRESS] = address
param[neighbors.ATTRIBUTE_MAP] = attribute_maps
+ if route_dist is not None:
+ param[vrfs.ROUTE_DISTINGUISHER] = route_dist
+ param[vrfs.VRF_RF] = route_family
call(func_name, **param)
- def attribute_map_get(self, address):
+ def attribute_map_get(self, address, route_dist=None,
+ route_family=RF_VPN_V4):
"""This method gets in-bound filters of the specified neighbor.
``address`` specifies the IP address of the neighbor.
+ ``route_dist`` specifies route distinguisher that has attribute_maps.
+
+ ``route_family`` specifies route family of the VRF.
+ This parameter must be RF_VPN_V4 or RF_VPN_V6.
+
Returns a list object containing an instance of AttributeMap
"""
+ assert route_family in (RF_VPN_V4, RF_VPN_V6),\
+ 'route_family must be RF_VPN_V4 or RF_VPN_V6'
+
func_name = 'neighbor.attribute_map.get'
param = {}
param[neighbors.IP_ADDRESS] = address
+ if route_dist is not None:
+ param[vrfs.ROUTE_DISTINGUISHER] = route_dist
+ param[vrfs.VRF_RF] = route_family
attribute_maps = call(func_name, **param)
return attribute_maps
diff --git a/ryu/services/protocols/bgp/constants.py b/ryu/services/protocols/bgp/constants.py
index b1af9b0a..bda55f05 100644
--- a/ryu/services/protocols/bgp/constants.py
+++ b/ryu/services/protocols/bgp/constants.py
@@ -48,3 +48,9 @@ VRF_TABLE = 'vrf_table'
# RTC EOR timer default value
# Time to wait for RTC-EOR, before we can send initial UPDATE as per RFC
RTC_EOR_DEFAULT_TIME = 60
+
+# Constants for AttributeMaps
+ATTR_MAPS_ORG_KEY = '__orig'
+ATTR_MAPS_LABEL_KEY = 'at_maps_key'
+ATTR_MAPS_LABEL_DEFAULT = 'default'
+ATTR_MAPS_VALUE = 'at_maps'
diff --git a/ryu/services/protocols/bgp/core_managers/configuration_manager.py b/ryu/services/protocols/bgp/core_managers/configuration_manager.py
index ffac9bcd..ff3dd3be 100644
--- a/ryu/services/protocols/bgp/core_managers/configuration_manager.py
+++ b/ryu/services/protocols/bgp/core_managers/configuration_manager.py
@@ -94,6 +94,14 @@ class ConfigurationManager(CommonConfListener, VrfsConfListener,
self._signal_bus.vrf_removed(vrf_conf.route_dist)
+ # Remove AttributeMaps under the removed vrf
+ rd = vrf_conf.route_dist
+ rf = vrf_conf.route_family
+ peers = self._peer_manager.iterpeers
+ for peer in peers:
+ key = ':'.join([rd, rf])
+ peer.attribute_maps.pop(key, None)
+
def on_add_vrf_conf(self, evt):
"""Event handler for new VrfConf.
diff --git a/ryu/services/protocols/bgp/info_base/base.py b/ryu/services/protocols/bgp/info_base/base.py
index 13f02caf..0e56bd07 100644
--- a/ryu/services/protocols/bgp/info_base/base.py
+++ b/ryu/services/protocols/bgp/info_base/base.py
@@ -947,14 +947,14 @@ class PrefixFilter(Filter):
ge and le condition,
this method returns True as the matching result.
- ``prefix`` specifies the prefix. prefix must be string.
+ ``path`` specifies the path that has prefix.
"""
- prefix = path.nlri
+ nlri = path.nlri
result = False
- length = prefix.length
- net = netaddr.IPNetwork(prefix.formatted_nlri_str)
+ length = nlri.length
+ net = netaddr.IPNetwork(nlri.prefix)
if net in self._network:
if self._ge is None and self._le is None:
diff --git a/ryu/services/protocols/bgp/peer.py b/ryu/services/protocols/bgp/peer.py
index 14618521..598e5936 100644
--- a/ryu/services/protocols/bgp/peer.py
+++ b/ryu/services/protocols/bgp/peer.py
@@ -37,6 +37,9 @@ from ryu.services.protocols.bgp.rtconf.neighbors import NeighborConfListener
from ryu.services.protocols.bgp.signals.emit import BgpSignalBus
from ryu.services.protocols.bgp.speaker import BgpProtocol
from ryu.services.protocols.bgp.info_base.ipv4 import Ipv4Path
+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.rtconf.vrfs import VRF_RF_IPV4, VRF_RF_IPV6
from ryu.services.protocols.bgp.utils import bgp as bgp_utils
from ryu.services.protocols.bgp.utils.evtlet import EventletIOFactory
from ryu.services.protocols.bgp.utils import stats
@@ -415,15 +418,18 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
@property
def attribute_maps(self):
- return self._attribute_maps['__orig']\
- if '__orig' in self._attribute_maps else []
+ return self._attribute_maps
@attribute_maps.setter
def attribute_maps(self, attribute_maps):
_attr_maps = {}
- _attr_maps.setdefault('__orig', [])
+ _attr_maps.setdefault(const.ATTR_MAPS_ORG_KEY, [])
- for a in attribute_maps:
+ # key is 'default' or rd_rf that represents RD and route_family
+ key = attribute_maps[const.ATTR_MAPS_LABEL_KEY]
+ at_maps = attribute_maps[const.ATTR_MAPS_VALUE]
+
+ for a in at_maps:
cloned = a.clone()
LOG.debug("AttributeMap attr_type: %s, attr_value: %s",
cloned.attr_type, cloned.attr_value)
@@ -431,9 +437,9 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
attr_list.append(cloned)
# preserve original order of attribute_maps
- _attr_maps['__orig'].append(cloned)
+ _attr_maps[const.ATTR_MAPS_ORG_KEY].append(cloned)
- self._attribute_maps = _attr_maps
+ self._attribute_maps[key] = _attr_maps
self.on_update_attribute_maps()
def is_mpbgp_cap_valid(self, route_family):
@@ -908,20 +914,19 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
# attribute_maps and set local-pref value.
# If the path doesn't match, we set default local-pref 100.
localpref_attr = BGPPathAttributeLocalPref(100)
- # TODO handle VPNv4Path
- if isinstance(path, Ipv4Path):
- if AttributeMap.ATTR_LOCAL_PREF in self._attribute_maps:
- maps = \
- self._attribute_maps[AttributeMap.ATTR_LOCAL_PREF]
- for m in maps:
- cause, result = m.evaluate(path)
- LOG.debug(
- "local_pref evaluation result:%s, cause:%s",
- result, cause)
-
- if result:
- localpref_attr = m.get_attribute()
- break
+ key = const.ATTR_MAPS_LABEL_DEFAULT
+
+ if isinstance(path, (Vpnv4Path, Vpnv6Path)):
+ nlri = nlri_list[0]
+ rf = VRF_RF_IPV4 if isinstance(path, Vpnv4Path)\
+ else VRF_RF_IPV6
+ key = ':'.join([nlri.route_dist, rf])
+
+ attr_type = AttributeMap.ATTR_LOCAL_PREF
+ at_maps = self._attribute_maps.get(key, {})
+ result = self._lookup_attribute_map(at_maps, attr_type, path)
+ if result:
+ localpref_attr = result
# COMMUNITY Attribute.
community_attr = pathattr_map.get(BGP_ATTR_TYPE_COMMUNITIES)
@@ -1972,3 +1977,18 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
if self._neigh_conf.enabled:
if not self._connect_retry_event.is_set():
self._connect_retry_event.set()
+
+ @staticmethod
+ def _lookup_attribute_map(attribute_map, attr_type, path):
+ result_attr = None
+ if attr_type in attribute_map:
+ maps = attribute_map[attr_type]
+ for m in maps:
+ cause, result = m.evaluate(path)
+ LOG.debug(
+ "local_pref evaluation result:%s, cause:%s",
+ result, cause)
+ if result:
+ result_attr = m.get_attribute()
+ break
+ return result_attr