summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorIWASE Yusuke <iwase.yusuke0@gmail.com>2017-10-06 10:35:00 +0900
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2017-10-15 13:04:39 +0900
commit09d5b2533ce2df3e042415ffeedf62795c3cdbe7 (patch)
tree976fa979eb608ae4b99b21f67c55a65fd47ef833
parentf7752903604fbc334752867920947909d79c7039 (diff)
controller: APIs to register switch address dynamically
This patch introduces APIs to register/unregister switch address after Ryu (ofp_handler) starting. Signed-off-by: IWASE Yusuke <iwase.yusuke0@gmail.com> Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
-rw-r--r--ryu/controller/controller.py14
-rw-r--r--ryu/controller/ofp_api.py73
-rw-r--r--ryu/controller/ofp_event.py3
-rw-r--r--ryu/controller/ofp_handler.py6
4 files changed, 93 insertions, 3 deletions
diff --git a/ryu/controller/controller.py b/ryu/controller/controller.py
index 84e0e05c..2de14a75 100644
--- a/ryu/controller/controller.py
+++ b/ryu/controller/controller.py
@@ -66,7 +66,7 @@ CONF.register_cli_opts([
cfg.StrOpt('ca-certs', default=None, help='CA certificates'),
cfg.ListOpt('ofp-switch-address-list', item_type=str, default=[],
help='list of IP address and port pairs (default empty). '
- 'e.g., "127.0.0.1:6653,127.0.0.1:6633"'),
+ 'e.g., "127.0.0.1:6653,[::1]:6653"'),
cfg.IntOpt('ofp-switch-connect-interval',
default=DEFAULT_OFP_SW_CON_INTERVAL,
help='interval in seconds to connect to switches '
@@ -133,6 +133,12 @@ class OpenFlowController(object):
self.ofp_tcp_listen_port = CONF.ofp_tcp_listen_port
self.ofp_ssl_listen_port = CONF.ofp_ssl_listen_port
+ # Example:
+ # self._clients = {
+ # ('127.0.0.1', 6653): <instance of StreamClient>,
+ # }
+ self._clients = {}
+
# entry point
def __call__(self):
# LOG.debug('call')
@@ -147,6 +153,12 @@ class OpenFlowController(object):
interval = interval or CONF.ofp_switch_connect_interval
client = hub.StreamClient(addr)
hub.spawn(client.connect_loop, datapath_connection_factory, interval)
+ self._clients[addr] = client
+
+ def stop_client_loop(self, addr):
+ client = self._clients.get(addr, None)
+ if client is not None:
+ client.stop()
def server_loop(self, ofp_tcp_listen_port, ofp_ssl_listen_port):
if CONF.ctl_privkey is not None and CONF.ctl_cert is not None:
diff --git a/ryu/controller/ofp_api.py b/ryu/controller/ofp_api.py
new file mode 100644
index 00000000..088f140d
--- /dev/null
+++ b/ryu/controller/ofp_api.py
@@ -0,0 +1,73 @@
+# Copyright (C) 2017 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.
+
+"""
+OpenFlow related APIs of ryu.controller module.
+"""
+
+import netaddr
+
+from ryu.base import app_manager
+from ryu.lib import hub
+from . import ofp_event
+
+
+_TMP_ADDRESSES = {}
+
+
+def register_switch_address(addr, interval=None):
+ """
+ Registers a new address to initiate connection to switch.
+
+ Registers a new IP address and port pair of switch to let
+ ryu.controller.controller.OpenFlowController to try to initiate
+ connection to switch.
+
+ :param addr: A tuple of (host, port) pair of switch.
+ :param interval: Interval in seconds to try to connect to switch
+ """
+ assert len(addr) == 2
+ assert netaddr.valid_ipv4(addr[0]) or netaddr.valid_ipv6(addr[0])
+ ofp_handler = app_manager.lookup_service_brick(ofp_event.NAME)
+ _TMP_ADDRESSES[addr] = interval
+
+ def _retry_loop():
+ # Delays registration if ofp_handler is not started yet
+ while True:
+ if ofp_handler.controller is not None:
+ for a, i in _TMP_ADDRESSES.items():
+ ofp_handler.controller.spawn_client_loop(a, i)
+ hub.sleep(1)
+ break
+ hub.sleep(1)
+
+ hub.spawn(_retry_loop)
+
+
+def unregister_switch_address(addr):
+ """
+ Unregister the given switch address.
+
+ Unregisters the given switch address to let
+ ryu.controller.controller.OpenFlowController stop trying to initiate
+ connection to switch.
+
+ :param addr: A tuple of (host, port) pair of switch.
+ """
+ ofp_handler = app_manager.lookup_service_brick(ofp_event.NAME)
+ # Do nothing if ofp_handler is not started yet
+ if ofp_handler.controller is None:
+ return
+ ofp_handler.controller.stop_client_loop(addr)
diff --git a/ryu/controller/ofp_event.py b/ryu/controller/ofp_event.py
index 6eb8e5f8..7640b41f 100644
--- a/ryu/controller/ofp_event.py
+++ b/ryu/controller/ofp_event.py
@@ -26,6 +26,9 @@ from ryu import ofproto
from . import event
+NAME = 'ofp_event'
+
+
class EventOFPMsgBase(event.EventBase):
"""
The base class of OpenFlow event class.
diff --git a/ryu/controller/ofp_handler.py b/ryu/controller/ofp_handler.py
index 7b4bfd11..4f439c2e 100644
--- a/ryu/controller/ofp_handler.py
+++ b/ryu/controller/ofp_handler.py
@@ -51,11 +51,13 @@ from ryu.ofproto import ofproto_parser
class OFPHandler(ryu.base.app_manager.RyuApp):
def __init__(self, *args, **kwargs):
super(OFPHandler, self).__init__(*args, **kwargs)
- self.name = 'ofp_event'
+ self.name = ofp_event.NAME
+ self.controller = None
def start(self):
super(OFPHandler, self).start()
- return hub.spawn(OpenFlowController())
+ self.controller = OpenFlowController()
+ return hub.spawn(self.controller)
def _hello_failed(self, datapath, error_desc):
self.logger.error(error_desc)