summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ryu/services/protocols/bgp/bgpspeaker.py7
-rw-r--r--ryu/services/protocols/bgp/peer.py29
-rw-r--r--ryu/services/protocols/bgp/rtconf/neighbors.py38
3 files changed, 65 insertions, 9 deletions
diff --git a/ryu/services/protocols/bgp/bgpspeaker.py b/ryu/services/protocols/bgp/bgpspeaker.py
index 615bf756..8e290150 100644
--- a/ryu/services/protocols/bgp/bgpspeaker.py
+++ b/ryu/services/protocols/bgp/bgpspeaker.py
@@ -57,6 +57,7 @@ from ryu.services.protocols.bgp.rtconf.neighbors import PEER_NEXT_HOP
from ryu.services.protocols.bgp.rtconf.neighbors import PASSWORD
from ryu.services.protocols.bgp.rtconf.neighbors import IN_FILTER
from ryu.services.protocols.bgp.rtconf.neighbors import OUT_FILTER
+from ryu.services.protocols.bgp.rtconf.neighbors import IS_ROUTE_SERVER_CLIENT
from ryu.services.protocols.bgp.info_base.base import Filter
@@ -180,7 +181,7 @@ class BGPSpeaker(object):
enable_vpnv4=DEFAULT_CAP_MBGP_VPNV4,
enable_vpnv6=DEFAULT_CAP_MBGP_VPNV6,
next_hop=None, password=None, multi_exit_disc=None,
- site_of_origins=None):
+ site_of_origins=None, is_route_server_client=False):
""" This method registers a new neighbor. The BGP speaker tries to
establish a bgp session with the peer (accepts a connection
from the peer and also tries to connect to it).
@@ -213,12 +214,16 @@ class BGPSpeaker(object):
``site_of_origins`` specifies site_of_origin values.
This parameter must be a list of string.
+
+ ``is_route_server_client`` specifies whether this neighbor is a
+ router server's client or not.
"""
bgp_neighbor = {}
bgp_neighbor[neighbors.IP_ADDRESS] = address
bgp_neighbor[neighbors.REMOTE_AS] = remote_as
bgp_neighbor[PEER_NEXT_HOP] = next_hop
bgp_neighbor[PASSWORD] = password
+ bgp_neighbor[IS_ROUTE_SERVER_CLIENT] = is_route_server_client
# v6 advertizement is available with only v6 peering
if netaddr.valid_ipv4(address):
bgp_neighbor[CAP_MBGP_IPV4] = enable_ipv4
diff --git a/ryu/services/protocols/bgp/peer.py b/ryu/services/protocols/bgp/peer.py
index d8eec52d..23b1a235 100644
--- a/ryu/services/protocols/bgp/peer.py
+++ b/ryu/services/protocols/bgp/peer.py
@@ -400,6 +400,14 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
LOG.debug('set out-filter : %s' % filters)
self.on_update_out_filter()
+ @property
+ def is_route_server_client(self):
+ return self._neigh_conf.is_route_server_client
+
+ @property
+ def check_first_as(self):
+ return self._neigh_conf.check_first_as
+
def is_mpbgp_cap_valid(self, route_family):
if not self.in_established:
raise ValueError('Invalid request: Peer not in established state')
@@ -761,6 +769,10 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
path.route_family.afi, path.route_family.safi, [path.nlri]
)
new_pathattr.append(mpunreach_attr)
+ elif self.is_route_server_client:
+ nlri_list = [path.nlri]
+ for pathattr in path.pathattr_map.itervalues():
+ new_pathattr.append(pathattr)
else:
# Supported and un-supported/unknown attributes.
origin_attr = None
@@ -1140,9 +1152,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
raise bgp.MissingWellKnown(
BGP_ATTR_TYPE_AS_PATH)
- # We do not have a setting to enable/disable first-as check.
- # We by default do first-as check below.
- if (self.is_ebgp_peer() and
+ if (self.check_first_as and self.is_ebgp_peer() and
not aspath.has_matching_leftmost(self.remote_as)):
LOG.error('First AS check fails. Raise appropriate'
' exception.')
@@ -1180,9 +1190,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
if not aspath:
raise bgp.MissingWellKnown(BGP_ATTR_TYPE_AS_PATH)
- # We do not have a setting to enable/disable first-as check.
- # We by default do first-as check below.
- if (self.is_ebgp_peer() and
+ if (self.check_first_as and self.is_ebgp_peer() and
not aspath.has_matching_leftmost(self.remote_as)):
LOG.error('First AS check fails. Raise appropriate exception.')
raise bgp.MalformedAsPath()
@@ -1382,7 +1390,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
processing.
"""
umsg_pattrs = update_msg.pathattr_map
- mpreach_nlri_attr = umsg_pattrs.pop(BGP_ATTR_TYPE_MP_REACH_NLRI)
+ mpreach_nlri_attr = umsg_pattrs.get(BGP_ATTR_TYPE_MP_REACH_NLRI)
assert mpreach_nlri_attr
msg_rf = mpreach_nlri_attr.route_family
@@ -1792,6 +1800,13 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
self.remote_as)
return
+ # If this peer is a route server client, we forward the path
+ # regardless of AS PATH loop, whether the connction is iBGP or eBGP,
+ # or path's communities.
+ if self.is_route_server_client:
+ outgoing_route = OutgoingRoute(path)
+ self.enque_outgoing_msg(outgoing_route)
+
if self._neigh_conf.multi_exit_disc:
med_attr = path.get_pattr(BGP_ATTR_TYPE_MULTI_EXIT_DISC)
if not med_attr:
diff --git a/ryu/services/protocols/bgp/rtconf/neighbors.py b/ryu/services/protocols/bgp/rtconf/neighbors.py
index 0ca6f685..3f8957ca 100644
--- a/ryu/services/protocols/bgp/rtconf/neighbors.py
+++ b/ryu/services/protocols/bgp/rtconf/neighbors.py
@@ -77,6 +77,8 @@ PEER_NEXT_HOP = 'peer_next_hop'
PASSWORD = 'password'
IN_FILTER = 'in_filter'
OUT_FILTER = 'out_filter'
+IS_ROUTE_SERVER_CLIENT = 'is_route_server_client'
+CHECK_FIRST_AS = 'check_first_as'
# Default value constants.
DEFAULT_CAP_GR_NULL = True
@@ -91,6 +93,8 @@ DEFAULT_ENABLED = True
DEFAULT_CAP_RTC = False
DEFAULT_IN_FILTER = []
DEFAULT_OUT_FILTER = []
+DEFAULT_IS_ROUTE_SERVER_CLIENT = False
+DEFAULT_CHECK_FIRST_AS = False
# Default value for *MAX_PREFIXES* setting is set to 0.
DEFAULT_MAX_PREFIXES = 0
@@ -218,6 +222,24 @@ def validate_out_filters(filters):
return [valid_filter(filter_) for filter_ in filters]
+@validate(name=IS_ROUTE_SERVER_CLIENT)
+def validate_is_route_server_client(is_route_server_client):
+ if is_route_server_client not in (True, False):
+ raise ConfigValueError(desc='Invalid is_route_server_client(%s)' %
+ is_route_server_client)
+
+ return is_route_server_client
+
+
+@validate(name=CHECK_FIRST_AS)
+def validate_check_first_as(check_first_as):
+ if check_first_as not in (True, False):
+ raise ConfigValueError(desc='Invalid check_first_as(%s)' %
+ check_first_as)
+
+ return check_first_as
+
+
class NeighborConf(ConfWithId, ConfWithStats):
"""Class that encapsulates one neighbors' configuration."""
@@ -235,7 +257,8 @@ class NeighborConf(ConfWithId, ConfWithStats):
ADVERTISE_PEER_AS, SITE_OF_ORIGINS,
LOCAL_ADDRESS, LOCAL_PORT,
PEER_NEXT_HOP, PASSWORD,
- IN_FILTER, OUT_FILTER])
+ IN_FILTER, OUT_FILTER,
+ IS_ROUTE_SERVER_CLIENT, CHECK_FIRST_AS])
def __init__(self, **kwargs):
super(NeighborConf, self).__init__(**kwargs)
@@ -265,6 +288,11 @@ class NeighborConf(ConfWithId, ConfWithStats):
IN_FILTER, DEFAULT_IN_FILTER, **kwargs)
self._settings[OUT_FILTER] = compute_optional_conf(
OUT_FILTER, DEFAULT_OUT_FILTER, **kwargs)
+ self._settings[IS_ROUTE_SERVER_CLIENT] = compute_optional_conf(
+ IS_ROUTE_SERVER_CLIENT,
+ DEFAULT_IS_ROUTE_SERVER_CLIENT, **kwargs)
+ self._settings[CHECK_FIRST_AS] = compute_optional_conf(
+ CHECK_FIRST_AS, DEFAULT_CHECK_FIRST_AS, **kwargs)
# We do not have valid default MED value.
# If no MED attribute is provided then we do not have to use MED.
@@ -439,6 +467,14 @@ class NeighborConf(ConfWithId, ConfWithStats):
def out_filter(self):
return self._settings[OUT_FILTER]
+ @property
+ def is_route_server_client(self):
+ return self._settings[IS_ROUTE_SERVER_CLIENT]
+
+ @property
+ def check_first_as(self):
+ return self._settings[CHECK_FIRST_AS]
+
def exceeds_max_prefix_allowed(self, prefix_count):
allowed_max = self._settings[MAX_PREFIXES]
does_exceed = False