diff options
-rw-r--r-- | ryu/services/protocols/bgp/bgpspeaker.py | 7 | ||||
-rw-r--r-- | ryu/services/protocols/bgp/peer.py | 29 | ||||
-rw-r--r-- | ryu/services/protocols/bgp/rtconf/neighbors.py | 38 |
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 |