implemented draft-ietf-idr-ix-bgp-route-server-05 partially.

you can enable this function like below

>    speaker = BGPSpeaker(as_number=64512, router_id='10.10.0.1')
>    speaker.neighbor_add('10.0.0.1', 64514, is_route_server_client=True)
>    speaker.neighbor_add('10.10.0.2', 64513, is_route_server_client=True)

add multiple rib function is a future work

Signed-off-by: ISHIDA Wataru <[email protected]>
---
 ryu/lib/packet/bgp.py                          |    4 +--
 ryu/services/protocols/bgp/bgpspeaker.py       |    7 ++++-
 ryu/services/protocols/bgp/peer.py             |   29 +++++++++++++-----
 ryu/services/protocols/bgp/rtconf/neighbors.py |   38 +++++++++++++++++++++++-
 4 files changed, 67 insertions(+), 11 deletions(-)

diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py
index 3cace68..ef23c6e 100644
--- a/ryu/lib/packet/bgp.py
+++ b/ryu/lib/packet/bgp.py
@@ -932,7 +932,7 @@ class LabelledVPNIPAddrPrefix(_LabelledAddrPrefix, 
_VPNAddrPrefix,
 
     @property
     def label_list(self):
-        return self.addr[:-2]
+        return self.addr[-3]
 
     @property
     def formatted_nlri_str(self):
@@ -955,7 +955,7 @@ class LabelledVPNIP6AddrPrefix(_LabelledAddrPrefix, 
_VPNAddrPrefix,
 
     @property
     def label_list(self):
-        return self.addr[:-2]
+        return self.addr[-3]
 
     @property
     def formatted_nlri_str(self):
diff --git a/ryu/services/protocols/bgp/bgpspeaker.py 
b/ryu/services/protocols/bgp/bgpspeaker.py
index 615bf75..8e29015 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 d8eec52..23b1a23 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 0ca6f68..3f8957c 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
-- 
1.7.10.4


------------------------------------------------------------------------------
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to