Currently, BGPSpeaker supports only type 0 (Two-Octet AS-Specific) Route
Target (or Route Distinguisher).
This patch enables to advertise Type 1 (IPv4-Address-Specific) and Type
2 (Four-Octet AS-Specific) Route Targets.

Reported-by: Albert Siersema <[email protected]>
Signed-off-by: IWASE Yusuke <[email protected]>
---
 ryu/services/protocols/bgp/info_base/vrf.py | 16 +++---------
 ryu/services/protocols/bgp/utils/bgp.py     | 38 +++++++++++++++++++++++++++++
 2 files changed, 41 insertions(+), 13 deletions(-)

diff --git a/ryu/services/protocols/bgp/info_base/vrf.py 
b/ryu/services/protocols/bgp/info_base/vrf.py
index c4e41ef..4900e12 100644
--- a/ryu/services/protocols/bgp/info_base/vrf.py
+++ b/ryu/services/protocols/bgp/info_base/vrf.py
@@ -30,7 +30,6 @@ from ryu.lib.packet.bgp import BGPPathAttributeOrigin
 from ryu.lib.packet.bgp import BGPPathAttributeAsPath
 from ryu.lib.packet.bgp import EvpnEthernetSegmentNLRI
 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 BGPEvpnEsiLabelExtendedCommunity
@@ -47,6 +46,7 @@ from ryu.services.protocols.bgp.constants import VRF_TABLE
 from ryu.services.protocols.bgp.info_base.base import Destination
 from ryu.services.protocols.bgp.info_base.base import Path
 from ryu.services.protocols.bgp.info_base.base import Table
+from ryu.services.protocols.bgp.utils.bgp import create_rt_extended_community
 from ryu.services.protocols.bgp.utils.stats import LOCAL_ROUTES
 from ryu.services.protocols.bgp.utils.stats import REMOTE_ROUTES
 from ryu.services.protocols.bgp.utils.stats import RESOURCE_ID
@@ -267,19 +267,9 @@ class VrfTable(Table):
                                    es_import=es_import))
 
             for rt in vrf_conf.export_rts:
-                as_num, local_admin = rt.split(':')
-                subtype = 2
-                communities.append(BGPTwoOctetAsSpecificExtendedCommunity(
-                                   as_number=int(as_num),
-                                   local_administrator=int(local_admin),
-                                   subtype=subtype))
+                communities.append(create_rt_extended_community(rt, 2))
             for soo in vrf_conf.soo_list:
-                as_num, local_admin = soo.split(':')
-                subtype = 3
-                communities.append(BGPTwoOctetAsSpecificExtendedCommunity(
-                                   as_number=int(as_num),
-                                   local_administrator=int(local_admin),
-                                   subtype=subtype))
+                communities.append(create_rt_extended_community(soo, 3))
 
             # Set Tunnel Encapsulation Attribute
             tunnel_type = kwargs.get('tunnel_type', None)
diff --git a/ryu/services/protocols/bgp/utils/bgp.py 
b/ryu/services/protocols/bgp/utils/bgp.py
index 48ac3c6..4979e44 100644
--- a/ryu/services/protocols/bgp/utils/bgp.py
+++ b/ryu/services/protocols/bgp/utils/bgp.py
@@ -19,6 +19,8 @@
 import logging
 import socket
 
+import netaddr
+
 from ryu.lib.packet.bgp import (
     BGPUpdate,
     RF_IPv4_UC,
@@ -36,6 +38,9 @@ from ryu.lib.packet.bgp import (
     BGPPathAttributeUnknown,
     BGP_ATTR_FLAG_OPTIONAL,
     BGP_ATTR_FLAG_TRANSITIVE,
+    BGPTwoOctetAsSpecificExtendedCommunity,
+    BGPIPv4AddressSpecificExtendedCommunity,
+    BGPFourOctetAsSpecificExtendedCommunity,
 )
 from ryu.services.protocols.bgp.info_base.rtc import RtcPath
 from ryu.services.protocols.bgp.info_base.ipv4 import Ipv4Path
@@ -141,3 +146,36 @@ def create_end_of_rib_update():
 
 # Bgp update message instance that can used as End of RIB marker.
 UPDATE_EOR = create_end_of_rib_update()
+
+
+def create_rt_extended_community(value, subtype=2):
+    """
+    Creates an instance of the BGP Route Target Community (if "subtype=2")
+    or Route Origin Community ("subtype=3").
+
+    :param value: String of Route Target or Route Origin value.
+    :param subtype: Subtype of Extended Community.
+    :return: An instance of Route Target or Route Origin Community.
+    """
+    global_admin, local_admin = value.split(':')
+    local_admin = int(local_admin)
+    if global_admin.isdigit() and 0 <= int(global_admin) <= 0xffff:
+        ext_com = BGPTwoOctetAsSpecificExtendedCommunity(
+            subtype=subtype,
+            as_number=int(global_admin),
+            local_administrator=local_admin)
+    elif global_admin.isdigit() and 0xffff < int(global_admin) <= 0xffffffff:
+        ext_com = BGPFourOctetAsSpecificExtendedCommunity(
+            subtype=subtype,
+            as_number=int(global_admin),
+            local_administrator=local_admin)
+    elif netaddr.valid_ipv4(global_admin):
+        ext_com = BGPIPv4AddressSpecificExtendedCommunity(
+            subtype=subtype,
+            ipv4_address=global_admin,
+            local_administrator=local_admin)
+    else:
+        raise ValueError(
+            'Invalid Route Target or Route Origin value: %s' % value)
+
+    return ext_com
-- 
2.7.4


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to