bgp: local preference support IPv6, VPNv4/v6 route family
local preference supports IPv6 and VPNv4/v6 route family. sorry, previous patch contains pep8 warnings, so I cleaned them. Please discard previous one. Signed-off-by: Hiroshi Yokoi <yokoi.hiroshi@po.ntts.co.jp> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
parent
0fff3fa73c
commit
594fb6a191
@ -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
|
||||||
from ryu.services.protocols.bgp.rtconf.vrfs import VRF_RF_IPV4
|
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.rtconf.vrfs import VrfConf
|
||||||
|
from ryu.services.protocols.bgp import constants as const
|
||||||
|
|
||||||
LOG = logging.getLogger('bgpspeaker.api.rtconf')
|
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',
|
@RegisterWithArgChecks(name='neighbor.attribute_map.set',
|
||||||
req_args=[neighbors.IP_ADDRESS,
|
req_args=[neighbors.IP_ADDRESS,
|
||||||
neighbors.ATTRIBUTE_MAP])
|
neighbors.ATTRIBUTE_MAP],
|
||||||
def set_neighbor_attribute_map(neigh_ip_address, attribute_maps):
|
opt_args=[ROUTE_DISTINGUISHER, VRF_RF])
|
||||||
"""Returns a neighbor attribute_map for given ip address if exists."""
|
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()
|
core = CORE_MANAGER.get_core_service()
|
||||||
peer = core.peer_manager.get_by_addr(neigh_ip_address)
|
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
|
return True
|
||||||
|
|
||||||
|
|
||||||
@RegisterWithArgChecks(name='neighbor.attribute_map.get',
|
@RegisterWithArgChecks(name='neighbor.attribute_map.get',
|
||||||
req_args=[neighbors.IP_ADDRESS])
|
req_args=[neighbors.IP_ADDRESS],
|
||||||
def get_neighbor_attribute_map(neigh_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."""
|
"""Returns a neighbor attribute_map for given ip address if exists."""
|
||||||
core = CORE_MANAGER.get_core_service()
|
core = CORE_MANAGER.get_core_service()
|
||||||
ret = core.peer_manager.get_by_addr(neigh_ip_address).attribute_maps
|
peer = core.peer_manager.get_by_addr(neigh_ip_address)
|
||||||
return ret
|
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
|
# VRF configuration related APIs
|
||||||
|
@ -526,7 +526,8 @@ class BGPSpeaker(object):
|
|||||||
param['port'] = port
|
param['port'] = port
|
||||||
call(func_name, **param)
|
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.
|
"""This method sets attribute mapping to a neighbor.
|
||||||
attribute mapping can be used when you want to apply
|
attribute mapping can be used when you want to apply
|
||||||
attribute to BGPUpdate under specific conditions.
|
attribute to BGPUpdate under specific conditions.
|
||||||
@ -537,6 +538,12 @@ class BGPSpeaker(object):
|
|||||||
before paths are advertised. All the items in the list must
|
before paths are advertised. All the items in the list must
|
||||||
be an instance of AttributeMap class
|
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;
|
We can set AttributeMap to a neighbor as follows;
|
||||||
|
|
||||||
pref_filter = PrefixFilter('192.168.103.0/30',
|
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'
|
func_name = 'neighbor.attribute_map.set'
|
||||||
param = {}
|
param = {}
|
||||||
param[neighbors.IP_ADDRESS] = address
|
param[neighbors.IP_ADDRESS] = address
|
||||||
param[neighbors.ATTRIBUTE_MAP] = attribute_maps
|
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)
|
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.
|
"""This method gets in-bound filters of the specified neighbor.
|
||||||
|
|
||||||
``address`` specifies the IP address of the 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
|
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'
|
func_name = 'neighbor.attribute_map.get'
|
||||||
param = {}
|
param = {}
|
||||||
param[neighbors.IP_ADDRESS] = address
|
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)
|
attribute_maps = call(func_name, **param)
|
||||||
return attribute_maps
|
return attribute_maps
|
||||||
|
|
||||||
|
@ -48,3 +48,9 @@ VRF_TABLE = 'vrf_table'
|
|||||||
# RTC EOR timer default value
|
# RTC EOR timer default value
|
||||||
# Time to wait for RTC-EOR, before we can send initial UPDATE as per RFC
|
# Time to wait for RTC-EOR, before we can send initial UPDATE as per RFC
|
||||||
RTC_EOR_DEFAULT_TIME = 60
|
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'
|
||||||
|
@ -94,6 +94,14 @@ class ConfigurationManager(CommonConfListener, VrfsConfListener,
|
|||||||
|
|
||||||
self._signal_bus.vrf_removed(vrf_conf.route_dist)
|
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):
|
def on_add_vrf_conf(self, evt):
|
||||||
"""Event handler for new VrfConf.
|
"""Event handler for new VrfConf.
|
||||||
|
|
||||||
|
@ -947,14 +947,14 @@ class PrefixFilter(Filter):
|
|||||||
ge and le condition,
|
ge and le condition,
|
||||||
this method returns True as the matching result.
|
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
|
result = False
|
||||||
length = prefix.length
|
length = nlri.length
|
||||||
net = netaddr.IPNetwork(prefix.formatted_nlri_str)
|
net = netaddr.IPNetwork(nlri.prefix)
|
||||||
|
|
||||||
if net in self._network:
|
if net in self._network:
|
||||||
if self._ge is None and self._le is None:
|
if self._ge is None and self._le is None:
|
||||||
|
@ -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.signals.emit import BgpSignalBus
|
||||||
from ryu.services.protocols.bgp.speaker import BgpProtocol
|
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.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 import bgp as bgp_utils
|
||||||
from ryu.services.protocols.bgp.utils.evtlet import EventletIOFactory
|
from ryu.services.protocols.bgp.utils.evtlet import EventletIOFactory
|
||||||
from ryu.services.protocols.bgp.utils import stats
|
from ryu.services.protocols.bgp.utils import stats
|
||||||
@ -415,15 +418,18 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def attribute_maps(self):
|
def attribute_maps(self):
|
||||||
return self._attribute_maps['__orig']\
|
return self._attribute_maps
|
||||||
if '__orig' in self._attribute_maps else []
|
|
||||||
|
|
||||||
@attribute_maps.setter
|
@attribute_maps.setter
|
||||||
def attribute_maps(self, attribute_maps):
|
def attribute_maps(self, attribute_maps):
|
||||||
_attr_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()
|
cloned = a.clone()
|
||||||
LOG.debug("AttributeMap attr_type: %s, attr_value: %s",
|
LOG.debug("AttributeMap attr_type: %s, attr_value: %s",
|
||||||
cloned.attr_type, cloned.attr_value)
|
cloned.attr_type, cloned.attr_value)
|
||||||
@ -431,9 +437,9 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
|
|||||||
attr_list.append(cloned)
|
attr_list.append(cloned)
|
||||||
|
|
||||||
# preserve original order of attribute_maps
|
# 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()
|
self.on_update_attribute_maps()
|
||||||
|
|
||||||
def is_mpbgp_cap_valid(self, route_family):
|
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.
|
# attribute_maps and set local-pref value.
|
||||||
# If the path doesn't match, we set default local-pref 100.
|
# If the path doesn't match, we set default local-pref 100.
|
||||||
localpref_attr = BGPPathAttributeLocalPref(100)
|
localpref_attr = BGPPathAttributeLocalPref(100)
|
||||||
# TODO handle VPNv4Path
|
key = const.ATTR_MAPS_LABEL_DEFAULT
|
||||||
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:
|
if isinstance(path, (Vpnv4Path, Vpnv6Path)):
|
||||||
localpref_attr = m.get_attribute()
|
nlri = nlri_list[0]
|
||||||
break
|
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 Attribute.
|
||||||
community_attr = pathattr_map.get(BGP_ATTR_TYPE_COMMUNITIES)
|
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 self._neigh_conf.enabled:
|
||||||
if not self._connect_retry_event.is_set():
|
if not self._connect_retry_event.is_set():
|
||||||
self._connect_retry_event.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
|
||||||
|
Loading…
Reference in New Issue
Block a user