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>
This commit is contained in:
IWASE Yusuke 2017-10-06 10:35:00 +09:00 committed by FUJITA Tomonori
parent f775290360
commit 09d5b2533c
4 changed files with 93 additions and 3 deletions

View File

@ -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:

73
ryu/controller/ofp_api.py Normal file
View File

@ -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)

View File

@ -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.

View File

@ -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)