For now, only Linux is supported.

Signed-off-by: FUJITA Tomonori <[email protected]>
---
 ryu/services/protocols/bgp/base.py | 63 +++++++++++++++++++++++++++++---------
 ryu/services/protocols/bgp/core.py | 24 ++++++++++++++-
 2 files changed, 71 insertions(+), 16 deletions(-)

diff --git a/ryu/services/protocols/bgp/base.py 
b/ryu/services/protocols/bgp/base.py
index 87060cd..ef175db 100644
--- a/ryu/services/protocols/bgp/base.py
+++ b/ryu/services/protocols/bgp/base.py
@@ -330,22 +330,16 @@ class Activity(object):
         addr, port = sock.getsockname()[:2]
         return (self._canonicalize_ip(addr), str(port))
 
-    def _listen_tcp(self, loc_addr, conn_handle):
-        """Creates a TCP server socket which listens on `port` number.
-
-        For each connection `server_factory` starts a new protocol.
-        """
-        if ':' in loc_addr[0]:
-            server = hub.listen(loc_addr, family=socket.AF_INET6)
-        else:
-            server = hub.listen(loc_addr)
-
-        server_name = self.name + '_server@' + str(loc_addr)
-        self._asso_socket_map[server_name] = server
-
-        # We now wait for connection requests from client.
+    def _create_listen_socket(self, family, loc_addr):
+        s = socket.socket(family)
+        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+        s.bind(loc_addr)
+        s.listen(1)
+        return s
+
+    def _listen_socket_loop(self, s, conn_handle):
         while True:
-            sock, client_address = server.accept()
+            sock, client_address = s.accept()
             client_address, port = self.get_remotename(sock)
             LOG.debug('Connect request received from client for port'
                       ' %s:%s' % (client_address, port))
@@ -353,6 +347,45 @@ class Activity(object):
             self._asso_socket_map[client_name] = sock
             self._spawn(client_name, conn_handle, sock)
 
+    def _listen_tcp(self, loc_addr, conn_handle):
+        """Creates a TCP server socket which listens on `port` number.
+
+        For each connection `server_factory` starts a new protocol.
+        """
+        info = socket.getaddrinfo(None, loc_addr[1], socket.AF_UNSPEC,
+                                  socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
+        listen_sockets = {}
+        for res in info:
+            af, socktype, proto, cannonname, sa = res
+            sock = None
+            try:
+                sock = socket.socket(af, socktype, proto)
+                sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+                if af == socket.AF_INET6:
+                    sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
+
+                sock.bind(sa)
+                sock.listen(50)
+                listen_sockets[sa] = sock
+            except socket.error:
+                if sock:
+                    sock.close()
+
+        count = 0
+        server = None
+        for sa in listen_sockets.keys():
+            name = self.name + '_server@' + str(sa[0])
+            if count == 0:
+                import eventlet
+                server = eventlet.spawn(self._listen_socket_loop,
+                                        listen_sockets[sa], conn_handle)
+
+                count += 1
+            else:
+                self._spawn(name, self._listen_socket_loop,
+                            listen_sockets[sa], conn_handle)
+        return server, listen_sockets
+
     def _connect_tcp(self, peer_addr, conn_handler, time_out=None,
                      bind_address=None, password=None):
         """Creates a TCP connection to given peer address.
diff --git a/ryu/services/protocols/bgp/core.py 
b/ryu/services/protocols/bgp/core.py
index fa9ee18..27eae15 100644
--- a/ryu/services/protocols/bgp/core.py
+++ b/ryu/services/protocols/bgp/core.py
@@ -21,6 +21,7 @@
 """
 import logging
 import netaddr
+import socket
 
 from ryu.lib.packet.bgp import BGP_ERROR_CEASE
 from ryu.lib.packet.bgp import BGP_ERROR_SUB_CONNECTION_RESET
@@ -40,6 +41,7 @@ from ryu.services.protocols.bgp.signals.emit import 
BgpSignalBus
 from ryu.services.protocols.bgp.speaker import BgpProtocol
 from ryu.services.protocols.bgp.utils.rtfilter import RouteTargetManager
 from ryu.services.protocols.bgp.utils import stats
+from ryu.lib import sockopt
 
 
 LOG = logging.getLogger('bgpspeaker.core')
@@ -221,7 +223,9 @@ class CoreService(Factory, Activity):
         server_addr = (CORE_IP, self._common_config.bgp_server_port)
         waiter = kwargs.pop('waiter')
         waiter.set()
-        server_thread = self._listen_tcp(server_addr, self.start_protocol)
+        server_thread, sockets = self._listen_tcp(server_addr,
+                                                  self.start_protocol)
+        self.listen_sockets = sockets
 
         server_thread.wait()
         processor_thread.wait()
@@ -358,7 +362,21 @@ class CoreService(Factory, Activity):
             out_route = FlexinetOutgoingRoute(path, route_dist)
             sink.enque_outgoing_msg(out_route)
 
+    def _set_password(self, address, password):
+        if netaddr.valid_ipv4(address):
+            family = socket.AF_INET
+        else:
+            family = socket.AF_INET6
+
+        for sock in self.listen_sockets.values():
+            if sock.family == family:
+                sockopt.set_tcp_md5sig(sock, address, password)
+
     def on_peer_added(self, peer):
+        if peer._neigh_conf.password:
+            self._set_password(peer._neigh_conf.ip_address,
+                               peer._neigh_conf.password)
+
         if self.started:
             self._spawn_activity(
                 peer, self.start_protocol
@@ -372,6 +390,10 @@ class CoreService(Factory, Activity):
             )
 
     def on_peer_removed(self, peer):
+        if peer._neigh_conf.password:
+            # seting zero length key means deleting the key
+            self._set_password(peer._neigh_conf.ip_address, '')
+
         if peer.rtc_as != self.asn:
             self._spawn(
                 'OLD_RTC_AS_HANDLER %s' % peer.rtc_as,
-- 
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