This patch adds support to advertise the BGP Tunnel Encapsulation
Attribute for the Ethernet VPN Routes.

Signed-off-by: IWASE Yusuke <[email protected]>
---
 ryu/lib/packet/bgp.py                              | 20 ++++++++++++++++++
 ryu/services/protocols/bgp/api/base.py             |  1 +
 ryu/services/protocols/bgp/api/prefix.py           | 24 +++++++++++++++++++++-
 ryu/services/protocols/bgp/bgpspeaker.py           | 11 +++++++++-
 .../protocols/bgp/core_managers/table_manager.py   |  4 ++--
 ryu/services/protocols/bgp/info_base/vrf.py        | 11 ++++++++--
 6 files changed, 65 insertions(+), 6 deletions(-)

diff --git a/ryu/lib/packet/bgp.py b/ryu/lib/packet/bgp.py
index 6b39f2d..6d7cf3f 100644
--- a/ryu/lib/packet/bgp.py
+++ b/ryu/lib/packet/bgp.py
@@ -2795,6 +2795,26 @@ class 
BGPEncapsulationExtendedCommunity(_ExtendedCommunity):
         super(BGPEncapsulationExtendedCommunity, self).__init__()
         self.do_init(BGPEncapsulationExtendedCommunity, self, kwargs)
 
+    @classmethod
+    def from_str(cls, tunnel_type):
+        """
+        Returns an instance identified with the given `tunnel_type`.
+
+        `tunnel_type` should be a str type value and corresponding to
+        BGP Tunnel Encapsulation Attribute Tunnel Type constants name
+        omitting `TUNNEL_TYPE_` prefix.
+
+        Example:
+            - `gre` means TUNNEL_TYPE_GRE
+            - `vxlan` means TUNNEL_TYPE_VXLAN
+
+        And raises AttributeError when the corresponding Tunnel Type
+        is not found to the given `tunnel_type`.
+        """
+        return cls(subtype=_ExtendedCommunity.SUBTYPE_ENCAPSULATION,
+                   tunnel_type=getattr(cls,
+                                       'TUNNEL_TYPE_' + tunnel_type.upper()))
+
 
 @_ExtendedCommunity.register_type(_ExtendedCommunity.EVPN_MAC_MOBILITY)
 class BGPEvpnMacMobilityExtendedCommunity(_ExtendedCommunity):
diff --git a/ryu/services/protocols/bgp/api/base.py 
b/ryu/services/protocols/bgp/api/base.py
index 9624e7b..49e7806 100644
--- a/ryu/services/protocols/bgp/api/base.py
+++ b/ryu/services/protocols/bgp/api/base.py
@@ -49,6 +49,7 @@ EVPN_ETHERNET_TAG_ID = 'ethernet_tag_id'
 MAC_ADDR = 'mac_addr'
 IP_ADDR = 'ip_addr'
 MPLS_LABELS = 'mpls_labels'
+TUNNEL_TYPE = 'tunnel_type'
 
 # API call registry
 _CALL_REGISTRY = {}
diff --git a/ryu/services/protocols/bgp/api/prefix.py 
b/ryu/services/protocols/bgp/api/prefix.py
index f047b6a..2bcb4e0 100644
--- a/ryu/services/protocols/bgp/api/prefix.py
+++ b/ryu/services/protocols/bgp/api/prefix.py
@@ -31,6 +31,7 @@ from ryu.services.protocols.bgp.api.base import PREFIX
 from ryu.services.protocols.bgp.api.base import RegisterWithArgChecks
 from ryu.services.protocols.bgp.api.base import ROUTE_DISTINGUISHER
 from ryu.services.protocols.bgp.api.base import VPN_LABEL
+from ryu.services.protocols.bgp.api.base import TUNNEL_TYPE
 from ryu.services.protocols.bgp.base import add_bgp_error_metadata
 from ryu.services.protocols.bgp.base import PREFIX_ERROR_CODE
 from ryu.services.protocols.bgp.base import validate
@@ -54,6 +55,20 @@ SUPPORTED_EVPN_ROUTE_TYPES = [
     EVPN_MULTICAST_ETAG_ROUTE,
 ]
 
+# Constants for BGP Tunnel Encapsulation Attribute
+TUNNEL_TYPE_VXLAN = 'vxlan'
+TUNNEL_TYPE_NVGRE = 'nvgre'
+TUNNEL_TYPE_MPLS = 'mpls'
+TUNNEL_TYPE_MPLS_IN_GRE = 'mpls_in_gre'
+TUNNEL_TYPE_VXLAN_GRE = 'vxlan_gre'
+SUPPORTED_TUNNEL_TYPES = [
+    TUNNEL_TYPE_VXLAN,
+    TUNNEL_TYPE_NVGRE,
+    TUNNEL_TYPE_MPLS,
+    TUNNEL_TYPE_MPLS_IN_GRE,
+    TUNNEL_TYPE_VXLAN_GRE,
+]
+
 
 @add_bgp_error_metadata(code=PREFIX_ERROR_CODE,
                         sub_code=1,
@@ -122,6 +137,13 @@ def is_valid_mpls_labels(labels):
                                conf_value=labels)
 
 
+@validate(name=TUNNEL_TYPE)
+def is_valid_tunnel_type(tunnel_type):
+    if tunnel_type not in SUPPORTED_TUNNEL_TYPES:
+        raise ConfigValueError(conf_name=TUNNEL_TYPE,
+                               conf_value=tunnel_type)
+
+
 @RegisterWithArgChecks(name='prefix.add_local',
                        req_args=[ROUTE_DISTINGUISHER, PREFIX, NEXT_HOP],
                        opt_args=[VRF_RF])
@@ -171,7 +193,7 @@ def delete_local(route_dist, prefix, 
route_family=VRF_RF_IPV4):
                        req_args=[EVPN_ROUTE_TYPE, ROUTE_DISTINGUISHER,
                                  NEXT_HOP],
                        opt_args=[EVPN_ESI, EVPN_ETHERNET_TAG_ID, MAC_ADDR,
-                                 IP_ADDR])
+                                 IP_ADDR, TUNNEL_TYPE])
 def add_evpn_local(route_type, route_dist, next_hop, **kwargs):
     """Adds EVPN route from VRF identified by *route_dist*.
     """
diff --git a/ryu/services/protocols/bgp/bgpspeaker.py 
b/ryu/services/protocols/bgp/bgpspeaker.py
index 582e38d..879eaf2 100644
--- a/ryu/services/protocols/bgp/bgpspeaker.py
+++ b/ryu/services/protocols/bgp/bgpspeaker.py
@@ -31,8 +31,10 @@ from ryu.services.protocols.bgp.api.base import MAC_ADDR
 from ryu.services.protocols.bgp.api.base import NEXT_HOP
 from ryu.services.protocols.bgp.api.base import ROUTE_DISTINGUISHER
 from ryu.services.protocols.bgp.api.base import ROUTE_FAMILY
+from ryu.services.protocols.bgp.api.base import TUNNEL_TYPE
 from ryu.services.protocols.bgp.api.prefix import EVPN_MAC_IP_ADV_ROUTE
 from ryu.services.protocols.bgp.api.prefix import EVPN_MULTICAST_ETAG_ROUTE
+from ryu.services.protocols.bgp.api.prefix import TUNNEL_TYPE_MPLS
 from ryu.services.protocols.bgp.rtconf.common import LOCAL_AS
 from ryu.services.protocols.bgp.rtconf.common import ROUTER_ID
 from ryu.services.protocols.bgp.rtconf.common import BGP_SERVER_PORT
@@ -490,7 +492,7 @@ class BGPSpeaker(object):
 
     def evpn_prefix_add(self, route_type, route_dist, esi=0,
                         ethernet_tag_id=None, mac_addr=None, ip_addr=None,
-                        next_hop=None):
+                        next_hop=None, tunnel_type=TUNNEL_TYPE_MPLS):
         """ This method adds a new EVPN route to be advertised.
 
         ``route_type`` specifies one of the EVPN route type name. The
@@ -509,6 +511,9 @@ class BGPSpeaker(object):
         ``ip_addr`` specifies an IPv4 or IPv6 address to advertise.
 
         ``next_hop`` specifies the next hop address for this prefix.
+
+        ``tunnel_type`` specifies the data plane encapsulation type
+        to advertise. The default is the MPLS encapsulation type.
         """
         func_name = 'evpn_prefix.add_local'
 
@@ -521,6 +526,10 @@ class BGPSpeaker(object):
                   ROUTE_DISTINGUISHER: route_dist,
                   NEXT_HOP: next_hop}
 
+        # Set optional arguments
+        if tunnel_type:
+            kwargs[TUNNEL_TYPE] = tunnel_type
+
         # Set route type specific arguments
         if route_type == EVPN_MAC_IP_ADV_ROUTE:
             kwargs.update({
diff --git a/ryu/services/protocols/bgp/core_managers/table_manager.py 
b/ryu/services/protocols/bgp/core_managers/table_manager.py
index b8285ca..5320dbf 100644
--- a/ryu/services/protocols/bgp/core_managers/table_manager.py
+++ b/ryu/services/protocols/bgp/core_managers/table_manager.py
@@ -482,7 +482,7 @@ class TableCoreManager(object):
             LOG.debug('No VRF table found that imports RTs: %s', path_rts)
 
     def update_vrf_table(self, route_dist, prefix=None, next_hop=None,
-                         route_family=None, route_type=None,
+                         route_family=None, route_type=None, tunnel_type=None,
                          is_withdraw=False, **kwargs):
         """Update a BGP route in the VRF table identified by `route_dist`
         with the given `next_hop`.
@@ -547,7 +547,7 @@ class TableCoreManager(object):
         # withdrawal. Hence multiple withdrawals have not side effect.
         return vrf_table.insert_vrf_path(
             nlri=prefix, next_hop=next_hop, gen_lbl=gen_lbl,
-            is_withdraw=is_withdraw)
+            is_withdraw=is_withdraw, tunnel_type=tunnel_type)
 
     def update_global_table(self, prefix, next_hop=None, is_withdraw=False):
         """Update a BGP route in the Global table for the given `prefix`
diff --git a/ryu/services/protocols/bgp/info_base/vrf.py 
b/ryu/services/protocols/bgp/info_base/vrf.py
index 620d522..6a60fc8 100644
--- a/ryu/services/protocols/bgp/info_base/vrf.py
+++ b/ryu/services/protocols/bgp/info_base/vrf.py
@@ -30,6 +30,7 @@ from ryu.lib.packet.bgp import BGPPathAttributeAsPath
 from ryu.lib.packet.bgp import BGPPathAttributeExtendedCommunities
 from ryu.lib.packet.bgp import BGPTwoOctetAsSpecificExtendedCommunity
 from ryu.lib.packet.bgp import BGPPathAttributeMultiExitDisc
+from ryu.lib.packet.bgp import BGPEncapsulationExtendedCommunity
 from ryu.lib.packet.bgp import RF_L2_EVPN
 from ryu.lib.packet.bgp import EvpnMacIPAdvertisementNLRI
 
@@ -211,7 +212,7 @@ class VrfTable(Table):
         return changed_dests
 
     def insert_vrf_path(self, nlri, next_hop=None,
-                        gen_lbl=False, is_withdraw=False):
+                        gen_lbl=False, is_withdraw=False, **kwargs):
         assert nlri
         pattrs = None
         label_list = []
@@ -243,6 +244,12 @@ class VrfTable(Table):
                                    local_administrator=int(local_admin),
                                    subtype=subtype))
 
+            # Set Tunnel Encapsulation Attribute
+            tunnel_type = kwargs.get('tunnel_type', None)
+            if tunnel_type:
+                communities.append(
+                    BGPEncapsulationExtendedCommunity.from_str(tunnel_type))
+
             pattrs[BGP_ATTR_TYPE_EXTENDED_COMMUNITIES] = \
                 BGPPathAttributeExtendedCommunities(communities=communities)
             if vrf_conf.multi_exit_disc:
@@ -266,7 +273,7 @@ class VrfTable(Table):
                 label_list.append(table_manager.get_next_vpnv4_label())
 
             # Set MPLS labels with the generated labels
-            if isinstance(nlri, EvpnMacIPAdvertisementNLRI):
+            if gen_lbl and isinstance(nlri, EvpnMacIPAdvertisementNLRI):
                 nlri.mpls_labels = label_list[:2]
 
         puid = self.VRF_PATH_CLASS.create_puid(
-- 
2.7.4


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

Reply via email to