You can advertize IPv6 addresses to IPv6 neighbors.

Signed-off-by: FUJITA Tomonori <[email protected]>
---
 ryu/services/protocols/bgp/api/rtconf.py           |  4 +-
 ryu/services/protocols/bgp/base.py                 |  1 +
 ryu/services/protocols/bgp/bgpspeaker.py           | 19 ++++-
 .../protocols/bgp/core_managers/table_manager.py   | 38 ++++++++--
 ryu/services/protocols/bgp/info_base/ipv6.py       | 85 ++++++++++++++++++++++
 .../protocols/bgp/operator/commands/show/rib.py    |  2 +-
 ryu/services/protocols/bgp/peer.py                 |  2 +-
 ryu/services/protocols/bgp/rtconf/base.py          | 10 +++
 ryu/services/protocols/bgp/rtconf/neighbors.py     | 18 ++++-
 ryu/services/protocols/bgp/utils/bgp.py            |  3 +
 10 files changed, 165 insertions(+), 17 deletions(-)
 create mode 100644 ryu/services/protocols/bgp/info_base/ipv6.py

diff --git a/ryu/services/protocols/bgp/api/rtconf.py 
b/ryu/services/protocols/bgp/api/rtconf.py
index 2869da5..93eeb18 100644
--- a/ryu/services/protocols/bgp/api/rtconf.py
+++ b/ryu/services/protocols/bgp/api/rtconf.py
@@ -176,12 +176,12 @@ def get_vrfs_conf():
 @register(name='network.add')
 def add_network(prefix):
     tm = CORE_MANAGER.get_core_service().table_manager
-    tm.add_to_ipv4_global_table(prefix)
+    tm.add_to_global_table(prefix)
     return True
 
 
 @register(name='network.del')
 def del_network(prefix):
     tm = CORE_MANAGER.get_core_service().table_manager
-    tm.add_to_ipv4_global_table(prefix, is_withdraw=True)
+    tm.add_to_global_table(prefix, is_withdraw=True)
     return True
diff --git a/ryu/services/protocols/bgp/base.py 
b/ryu/services/protocols/bgp/base.py
index 28ae286..e0338c2 100644
--- a/ryu/services/protocols/bgp/base.py
+++ b/ryu/services/protocols/bgp/base.py
@@ -49,6 +49,7 @@ OrderedDict = OrderedDict
 
 # Currently supported address families.
 SUPPORTED_GLOBAL_RF = set([RF_IPv4_UC,
+                           RF_IPv6_UC,
                            RF_IPv4_VPN,
                            RF_RTC_UC,
                            RF_IPv6_VPN
diff --git a/ryu/services/protocols/bgp/bgpspeaker.py 
b/ryu/services/protocols/bgp/bgpspeaker.py
index 8e33e85..5b5cb96 100644
--- a/ryu/services/protocols/bgp/bgpspeaker.py
+++ b/ryu/services/protocols/bgp/bgpspeaker.py
@@ -16,6 +16,7 @@
 
 """
 
+import netaddr
 from ryu.lib import hub
 from ryu.base import app_manager
 from ryu.services.protocols.bgp.operator import ssh
@@ -43,6 +44,7 @@ from ryu.services.protocols.bgp.rtconf.common import 
LABEL_RANGE
 from ryu.services.protocols.bgp.rtconf import neighbors
 from ryu.services.protocols.bgp.rtconf import vrfs
 from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_IPV4
+from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_IPV6
 from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV4
 from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV6
 from ryu.services.protocols.bgp.rtconf.neighbors import DEFAULT_CAP_MBGP_IPV4
@@ -188,9 +190,20 @@ class BGPSpeaker(object):
         bgp_neighbor = {}
         bgp_neighbor[neighbors.IP_ADDRESS] = address
         bgp_neighbor[neighbors.REMOTE_AS] = remote_as
-        bgp_neighbor[CAP_MBGP_IPV4] = enable_ipv4
-        bgp_neighbor[CAP_MBGP_VPNV4] = enable_vpnv4
-        bgp_neighbor[CAP_MBGP_VPNV6] = enable_vpnv6
+        # v6 advertizement is available with only v6 peering
+        if netaddr.valid_ipv4(address):
+            bgp_neighbor[CAP_MBGP_IPV4] = enable_ipv4
+            bgp_neighbor[CAP_MBGP_IPV6] = False
+            bgp_neighbor[CAP_MBGP_VPNV4] = enable_vpnv4
+            bgp_neighbor[CAP_MBGP_VPNV6] = enable_vpnv6
+        elif netaddr.valid_ipv6(address):
+            bgp_neighbor[CAP_MBGP_IPV4] = False
+            bgp_neighbor[CAP_MBGP_IPV6] = True
+            bgp_neighbor[CAP_MBGP_VPNV4] = False
+            bgp_neighbor[CAP_MBGP_VPNV6] = False
+        else:
+            # FIXME: should raise an exception
+            pass
         call('neighbor.create', **bgp_neighbor)
 
     def neighbor_del(self, address):
diff --git a/ryu/services/protocols/bgp/core_managers/table_manager.py 
b/ryu/services/protocols/bgp/core_managers/table_manager.py
index f8265dd..a4aad99 100644
--- a/ryu/services/protocols/bgp/core_managers/table_manager.py
+++ b/ryu/services/protocols/bgp/core_managers/table_manager.py
@@ -1,10 +1,13 @@
 import logging
+import netaddr
 from collections import OrderedDict
 
 from ryu.services.protocols.bgp.base import SUPPORTED_GLOBAL_RF
 from ryu.services.protocols.bgp.info_base.rtc import RtcTable
 from ryu.services.protocols.bgp.info_base.ipv4 import Ipv4Path
 from ryu.services.protocols.bgp.info_base.ipv4 import Ipv4Table
+from ryu.services.protocols.bgp.info_base.ipv6 import Ipv6Path
+from ryu.services.protocols.bgp.info_base.ipv6 import Ipv6Table
 from ryu.services.protocols.bgp.info_base.vpnv4 import Vpnv4Path
 from ryu.services.protocols.bgp.info_base.vpnv4 import Vpnv4Table
 from ryu.services.protocols.bgp.info_base.vpnv6 import Vpnv6Path
@@ -164,7 +167,8 @@ class TableCoreManager(object):
         global_table = None
         if route_family == RF_IPv4_UC:
             global_table = self.get_ipv4_table()
-
+        elif route_family == RF_IPv6_UC:
+            global_table = self.get_ipv6_table()
         elif route_family == RF_IPv4_VPN:
             global_table = self.get_vpn4_table()
 
@@ -205,6 +209,14 @@ class TableCoreManager(object):
 
         return vpn_table
 
+    def get_ipv6_table(self):
+        table = self._global_tables.get(RF_IPv6_UC)
+        if not table:
+            table = Ipv6Table(self._core_service, self._signal_bus)
+            self._global_tables[RF_IPv6_UC] = table
+            self._tables[(None, RF_IPv6_UC)] = table
+        return table
+
     def get_vpn6_table(self):
         """Returns global VPNv6 table.
 
@@ -483,13 +495,10 @@ class TableCoreManager(object):
             gen_lbl=True
         )
 
-    def add_to_ipv4_global_table(self, prefix, is_withdraw=False):
-        ip, masklen = prefix.split('/')
-        _nlri = IPAddrPrefix(int(masklen), ip)
+    def add_to_global_table(self, prefix, is_withdraw=False):
         src_ver_num = 1
         peer = None
         # set mandatory path attributes
-        nexthop = '0.0.0.0'
         origin = BGPPathAttributeOrigin(BGP_ATTR_ORIGIN_IGP)
         aspath = BGPPathAttributeAsPath([[]])
 
@@ -497,9 +506,22 @@ class TableCoreManager(object):
         pathattrs[BGP_ATTR_TYPE_ORIGIN] = origin
         pathattrs[BGP_ATTR_TYPE_AS_PATH] = aspath
 
-        new_path = Ipv4Path(peer, _nlri, src_ver_num,
-                            pattrs=pathattrs, nexthop=nexthop,
-                            is_withdraw=is_withdraw)
+        net = netaddr.IPNetwork(prefix)
+        ip = str(net.ip)
+        masklen = net.prefixlen
+        if netaddr.valid_ipv4(ip):
+            _nlri = IPAddrPrefix(masklen, ip)
+            nexthop = '0.0.0.0'
+            p = Ipv4Path
+        else:
+            _nlri = IP6AddrPrefix(masklen, ip)
+            nexthop = '::'
+            p = Ipv6Path
+
+        new_path = p(peer, _nlri, src_ver_num,
+                     pattrs=pathattrs, nexthop=nexthop,
+                     is_withdraw=is_withdraw)
+
         # add to global ipv4 table and propagates to neighbors
         self.learn_path(new_path)
 
diff --git a/ryu/services/protocols/bgp/info_base/ipv6.py 
b/ryu/services/protocols/bgp/info_base/ipv6.py
new file mode 100644
index 0000000..670f996
--- /dev/null
+++ b/ryu/services/protocols/bgp/info_base/ipv6.py
@@ -0,0 +1,85 @@
+# Copyright (C) 2014 Nippon Telegraph and Telephone Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+"""
+ Defines data types and models required specifically for IPv4 support.
+"""
+
+import logging
+
+from ryu.lib.packet.bgp import IPAddrPrefix
+from ryu.lib.packet.bgp import RF_IPv6_UC
+
+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.info_base.base import Destination
+from ryu.services.protocols.bgp.info_base.base import NonVrfPathProcessingMixin
+
+LOG = logging.getLogger('bgpspeaker.info_base.ipv6')
+
+
+class IPv6Dest(Destination, NonVrfPathProcessingMixin):
+    """v6 Destination
+
+    Store IPv6 Paths.
+    """
+    ROUTE_FAMILY = RF_IPv6_UC
+
+    def _best_path_lost(self):
+        old_best_path = self._best_path
+        NonVrfPathProcessingMixin._best_path_lost(self)
+        self._core_service._signal_bus.best_path_changed(old_best_path)
+
+    def _new_best_path(self, best_path):
+        NonVrfPathProcessingMixin._new_best_path(self, best_path)
+        self._core_service._signal_bus.best_path_changed(best_path)
+
+
+class Ipv6Table(Table):
+    """Global table to store IPv4 routing information.
+
+    Uses `IPv6Dest` to store destination information for each known vpnv6
+    paths.
+    """
+    ROUTE_FAMILY = RF_IPv6_UC
+    VPN_DEST_CLASS = IPv6Dest
+
+    def __init__(self, core_service, signal_bus):
+        super(Ipv6Table, self).__init__(None, core_service, signal_bus)
+
+    def _table_key(self, nlri):
+        """Return a key that will uniquely identify this NLRI inside
+        this table.
+        """
+        return nlri.prefix
+
+    def _create_dest(self, nlri):
+        return self.VPN_DEST_CLASS(self, nlri)
+
+    def __str__(self):
+        return '%s(scope_id: %s, rf: %s)' % (
+            self.__class__.__name__, self.scope_id, self.route_family
+        )
+
+
+class Ipv6Path(Path):
+    """Represents a way of reaching an v6 destination."""
+    ROUTE_FAMILY = RF_IPv6_UC
+    VRF_PATH_CLASS = None  # defined in init - anti cyclic import hack
+    NLRI_CLASS = IPAddrPrefix
+
+    def __init__(self, *args, **kwargs):
+        super(Ipv6Path, self).__init__(*args, **kwargs)
+        from ryu.services.protocols.bgp.info_base.vrf6 import Vrf6Path
+        self.VRF_PATH_CLASS = Vrf6Path
diff --git a/ryu/services/protocols/bgp/operator/commands/show/rib.py 
b/ryu/services/protocols/bgp/operator/commands/show/rib.py
index 94e1657..d5077d0 100644
--- a/ryu/services/protocols/bgp/operator/commands/show/rib.py
+++ b/ryu/services/protocols/bgp/operator/commands/show/rib.py
@@ -11,7 +11,7 @@ from ryu.services.protocols.bgp.operator.commands.responses 
import \
 
 
 class RibBase(Command, RouteFormatterMixin):
-    supported_families = ['ipv4', 'vpnv4', 'rtfilter', 'vpnv6']
+    supported_families = ['ipv4', 'ipv6', 'vpnv4', 'rtfilter', 'vpnv6']
 
 
 class Rib(RibBase):
diff --git a/ryu/services/protocols/bgp/peer.py 
b/ryu/services/protocols/bgp/peer.py
index 853473e..70e3668 100644
--- a/ryu/services/protocols/bgp/peer.py
+++ b/ryu/services/protocols/bgp/peer.py
@@ -1233,7 +1233,7 @@ class Peer(Source, Sink, NeighborConfListener, Activity):
                       ' UPDATE. %s' % update_msg)
             return
 
-        if msg_rf in (RF_IPv4_VPN, RF_IPv6_UC):
+        if msg_rf in (RF_IPv4_VPN, RF_IPv6_VPN):
             # Check if we have Extended Communities Attribute.
             # TODO(PH): Check if RT_NLRI afi/safi will ever have this attribute
             ext_comm_attr = umsg_pattrs.get(BGP_ATTR_TYPE_EXTENDED_COMMUNITIES)
diff --git a/ryu/services/protocols/bgp/rtconf/base.py 
b/ryu/services/protocols/bgp/rtconf/base.py
index 154dcca..271dab6 100644
--- a/ryu/services/protocols/bgp/rtconf/base.py
+++ b/ryu/services/protocols/bgp/rtconf/base.py
@@ -40,6 +40,7 @@ LOG = logging.getLogger('bgpspeaker.rtconf.base')
 CAP_REFRESH = 'cap_refresh'
 CAP_ENHANCED_REFRESH = 'cap_enhanced_refresh'
 CAP_MBGP_IPV4 = 'cap_mbgp_ipv4'
+CAP_MBGP_IPV6 = 'cap_mbgp_ipv6'
 CAP_MBGP_VPNV4 = 'cap_mbgp_vpnv4'
 CAP_MBGP_VPNV6 = 'cap_mbgp_vpnv6'
 CAP_RTC = 'cap_rtc'
@@ -597,6 +598,15 @@ def validate_cap_mbgp_ipv4(cmv4):
     return cmv4
 
 
+@validate(name=CAP_MBGP_IPV6)
+def validate_cap_mbgp_ipv4(cmv6):
+    if cmv6 not in (True, False):
+        raise ConfigTypeError(desc='Invalid Enhanced Refresh capability '
+                              'settings: %s boolean value expected' % cmv4)
+
+    return cmv6
+
+
 @validate(name=CAP_MBGP_VPNV4)
 def validate_cap_mbgp_vpnv4(cmv4):
     if cmv4 not in (True, False):
diff --git a/ryu/services/protocols/bgp/rtconf/neighbors.py 
b/ryu/services/protocols/bgp/rtconf/neighbors.py
index 8e98105..8d97cee 100644
--- a/ryu/services/protocols/bgp/rtconf/neighbors.py
+++ b/ryu/services/protocols/bgp/rtconf/neighbors.py
@@ -38,6 +38,7 @@ from ryu.services.protocols.bgp.rtconf.base import BaseConf
 from ryu.services.protocols.bgp.rtconf.base import BaseConfListener
 from ryu.services.protocols.bgp.rtconf.base import CAP_ENHANCED_REFRESH
 from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_IPV4
+from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_IPV6
 from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV4
 from ryu.services.protocols.bgp.rtconf.base import CAP_MBGP_VPNV6
 from ryu.services.protocols.bgp.rtconf.base import CAP_REFRESH
@@ -76,6 +77,7 @@ DEFAULT_CAP_GR_NULL = True
 DEFAULT_CAP_REFRESH = True
 DEFAULT_CAP_ENHANCED_REFRESH = False
 DEFAULT_CAP_MBGP_IPV4 = True
+DEFAULT_CAP_MBGP_IPV6 = False
 DEFAULT_CAP_MBGP_VPNV4 = False
 DEFAULT_CAP_MBGP_VPNV6 = False
 DEFAULT_HOLD_TIME = 40
@@ -156,8 +158,9 @@ class NeighborConf(ConfWithId, ConfWithStats):
     VALID_EVT = frozenset([UPDATE_ENABLED_EVT, UPDATE_MED_EVT])
     REQUIRED_SETTINGS = frozenset([REMOTE_AS, IP_ADDRESS])
     OPTIONAL_SETTINGS = frozenset([CAP_REFRESH,
-                                   CAP_ENHANCED_REFRESH, CAP_MBGP_VPNV4,
-                                   CAP_MBGP_IPV4, CAP_MBGP_VPNV6,
+                                   CAP_ENHANCED_REFRESH,
+                                   CAP_MBGP_IPV4, CAP_MBGP_IPV6,
+                                   CAP_MBGP_VPNV4, CAP_MBGP_VPNV6,
                                    CAP_RTC, RTC_AS, HOLD_TIME,
                                    ENABLED, MULTI_EXIT_DISC, MAX_PREFIXES,
                                    ADVERTISE_PEER_AS, SITE_OF_ORIGINS,
@@ -173,6 +176,8 @@ class NeighborConf(ConfWithId, ConfWithStats):
             CAP_ENHANCED_REFRESH, DEFAULT_CAP_ENHANCED_REFRESH, **kwargs)
         self._settings[CAP_MBGP_IPV4] = compute_optional_conf(
             CAP_MBGP_IPV4, DEFAULT_CAP_MBGP_IPV4, **kwargs)
+        self._settings[CAP_MBGP_IPV6] = compute_optional_conf(
+            CAP_MBGP_IPV6, DEFAULT_CAP_MBGP_IPV6, **kwargs)
         self._settings[CAP_MBGP_VPNV4] = compute_optional_conf(
             CAP_MBGP_VPNV4, DEFAULT_CAP_MBGP_VPNV4, **kwargs)
         self._settings[CAP_MBGP_VPNV6] = compute_optional_conf(
@@ -281,6 +286,10 @@ class NeighborConf(ConfWithId, ConfWithStats):
         return self._settings[CAP_MBGP_IPV4]
 
     @property
+    def cap_mbgp_ipv6(self):
+        return self._settings[CAP_MBGP_IPV6]
+
+    @property
     def cap_mbgp_vpnv4(self):
         return self._settings[CAP_MBGP_VPNV4]
 
@@ -354,6 +363,11 @@ class NeighborConf(ConfWithId, ConfWithStats):
                 BGPOptParamCapabilityMultiprotocol(
                     RF_IPv4_UC.afi, RF_IPv4_UC.safi))
 
+        if self.cap_mbgp_ipv6:
+            mbgp_caps.append(
+                BGPOptParamCapabilityMultiprotocol(
+                    RF_IPv6_UC.afi, RF_IPv6_UC.safi))
+
         if self.cap_mbgp_vpnv4:
             mbgp_caps.append(
                 BGPOptParamCapabilityMultiprotocol(
diff --git a/ryu/services/protocols/bgp/utils/bgp.py 
b/ryu/services/protocols/bgp/utils/bgp.py
index 4e7391b..95bcd26 100644
--- a/ryu/services/protocols/bgp/utils/bgp.py
+++ b/ryu/services/protocols/bgp/utils/bgp.py
@@ -21,6 +21,7 @@ import socket
 
 from ryu.lib.packet.bgp import BGPUpdate
 from ryu.lib.packet.bgp import RF_IPv4_UC
+from ryu.lib.packet.bgp import RF_IPv6_UC
 from ryu.lib.packet.bgp import RF_IPv4_VPN
 from ryu.lib.packet.bgp import RF_IPv6_VPN
 from ryu.lib.packet.bgp import RF_RTC_UC
@@ -31,6 +32,7 @@ from ryu.lib.packet.bgp import BGPPathAttributeMpUnreachNLRI
 from ryu.lib.packet.bgp import BGPPathAttributeUnknown
 from ryu.services.protocols.bgp.info_base.rtc import RtcPath
 from ryu.services.protocols.bgp.info_base.ipv4 import Ipv4Path
+from ryu.services.protocols.bgp.info_base.ipv6 import Ipv6Path
 from ryu.services.protocols.bgp.info_base.vpnv4 import Vpnv4Path
 from ryu.services.protocols.bgp.info_base.vpnv6 import Vpnv6Path
 
@@ -39,6 +41,7 @@ LOG = logging.getLogger('utils.bgp')
 
 # RouteFmaily to path sub-class mapping.
 _ROUTE_FAMILY_TO_PATH_MAP = {RF_IPv4_UC: Ipv4Path,
+                             RF_IPv6_UC: Ipv6Path,
                              RF_IPv4_VPN: Vpnv4Path,
                              RF_IPv6_VPN: Vpnv6Path,
                              RF_RTC_UC: RtcPath}
-- 
1.8.5.2 (Apple Git-48)


------------------------------------------------------------------------------
Open source business process management suite built on Java and Eclipse
Turn processes into business applications with Bonita BPM Community Edition
Quickly connect people, data, and systems into organized workflows
Winner of BOSSIE, CODIE, OW2 and Gartner awards
http://p.sf.net/sfu/Bonitasoft
_______________________________________________
Ryu-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ryu-devel

Reply via email to