
hacky workaround, will be removed. OF1.3 doesn't have ports. An application should not depend on them. But there might be such bad applications so let's keep this workaround for while. Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
120 lines
4.3 KiB
Python
120 lines
4.3 KiB
Python
# Copyright (C) 2011, 2012 Nippon Telegraph and Telephone Corporation.
|
|
# Copyright (C) 2011, 2012 Isaku Yamahata <yamahata at valinux co jp>
|
|
#
|
|
# 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.
|
|
|
|
import logging
|
|
|
|
from ryu import utils
|
|
from ryu.base import app_manager
|
|
from ryu.controller import dispatcher
|
|
from ryu.controller import ofp_event
|
|
from ryu.controller.handler import set_ev_cls
|
|
from ryu.controller.handler import HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER,\
|
|
MAIN_DISPATCHER
|
|
|
|
LOG = logging.getLogger('ryu.controller.ofp_handler')
|
|
|
|
# The state transition: HANDSHAKE -> CONFIG -> MAIN
|
|
#
|
|
# HANDSHAKE: if it receives HELLO message with the valid OFP version,
|
|
# sends Features Request message, and moves to CONFIG.
|
|
#
|
|
# CONFIG: it receives Features Reply message and moves to MAIN
|
|
#
|
|
# MAIN: it does nothing. Applications are expected to register their
|
|
# own handlers.
|
|
#
|
|
# Note that at any state, when we receive Echo Request message, send
|
|
# back Echo Reply message.
|
|
|
|
|
|
class OFPHandler(app_manager.RyuApp):
|
|
def __init__(self, *args, **kwargs):
|
|
super(OFPHandler, self).__init__(*args, **kwargs)
|
|
|
|
@set_ev_cls(ofp_event.EventOFPHello, HANDSHAKE_DISPATCHER)
|
|
def hello_handler(self, ev):
|
|
LOG.debug('hello ev %s', ev)
|
|
msg = ev.msg
|
|
datapath = msg.datapath
|
|
|
|
# TODO: check if received version is supported.
|
|
# pre 1.0 is not supported
|
|
if msg.version not in datapath.supported_ofp_version:
|
|
# send the error
|
|
error_msg = datapath.ofproto_parser.OFPErrorMsg(datapath)
|
|
error_msg.type = datapath.ofproto.OFPET_HELLO_FAILED
|
|
error_msg.code = datapath.ofproto.OFPHFC_INCOMPATIBLE
|
|
error_msg.data = 'unsupported version 0x%x' % msg.version
|
|
datapath.send_msg(error_msg)
|
|
return
|
|
|
|
# should we again send HELLO with the version that the switch
|
|
# supports?
|
|
# msg.version != datapath.ofproto.OFP_VERSION:
|
|
|
|
datapath.set_version(msg.version)
|
|
|
|
# now send feature
|
|
features_reqeust = datapath.ofproto_parser.OFPFeaturesRequest(datapath)
|
|
datapath.send_msg(features_reqeust)
|
|
|
|
# now move on to config state
|
|
LOG.debug('move onto config mode')
|
|
datapath.ev_q.set_dispatcher(CONFIG_DISPATCHER)
|
|
|
|
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
|
|
def switch_features_handler(self, ev):
|
|
msg = ev.msg
|
|
datapath = msg.datapath
|
|
LOG.debug('switch features ev %s', msg)
|
|
|
|
datapath.id = msg.datapath_id
|
|
|
|
# hacky workaround, will be removed. OF1.3 doesn't have
|
|
# ports. An application should not depend on them. But there
|
|
# might be such bad applications so keep this workaround for
|
|
# while.
|
|
if datapath.ofproto.OFP_VERSION < 0x04:
|
|
datapath.ports = msg.ports
|
|
|
|
ofproto = datapath.ofproto
|
|
ofproto_parser = datapath.ofproto_parser
|
|
set_config = ofproto_parser.OFPSetConfig(
|
|
datapath, ofproto.OFPC_FRAG_NORMAL,
|
|
128 # TODO:XXX
|
|
)
|
|
datapath.send_msg(set_config)
|
|
|
|
LOG.debug('move onto main mode')
|
|
ev.msg.datapath.ev_q.set_dispatcher(MAIN_DISPATCHER)
|
|
|
|
@set_ev_cls(ofp_event.EventOFPEchoRequest,
|
|
[HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
|
|
def echo_request_handler(self, ev):
|
|
msg = ev.msg
|
|
datapath = msg.datapath
|
|
echo_reply = datapath.ofproto_parser.OFPEchoReply(datapath)
|
|
echo_reply.xid = msg.xid
|
|
echo_reply.data = msg.data
|
|
datapath.send_msg(echo_reply)
|
|
|
|
@set_ev_cls(ofp_event.EventOFPErrorMsg,
|
|
[HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER])
|
|
def error_msg_handler(self, ev):
|
|
msg = ev.msg
|
|
LOG.debug('error msg ev %s type 0x%x code 0x%x %s',
|
|
msg, msg.type, msg.code, utils.hex_array(msg.data))
|