test: add integrated OVS test suite
This patch adds a test framework with OVS to test various matches and actions; adding various matches and actions and check `ovs-ofctl dump-flows' output. First, create 'br-tester' bridge: fujita@rose:~$ sudo ovs-vsctl add-br br-tester Secondly, configure the bridge to use the local controller: fujita@rose:~$ sudo ovs-vsctl set-controller br-tester tcp:127.0.0.1 Thirdly, run what you want to test. If you want to try adding flows on OF1.0: fujita@rose:~$ ryu-manager --verbose --run_test_mod ryu.tests.integrated.test_add_flow_v10 ryu.tests.integrated.tester This patch adds three test sets: ryu.tests.integrated.test_add_flow_v10 ryu.tests.integrated.test_add_flow_v12_actions ryu.tests.integrated.test_add_flow_v12_matches Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
This commit is contained in:
parent
bdaafadc3f
commit
475ca44ef4
@ -32,6 +32,7 @@ from ryu import utils
|
||||
from ryu.app import wsgi
|
||||
from ryu.base.app_manager import AppManager
|
||||
from ryu.controller import controller
|
||||
from ryu.tests.integrated import tester
|
||||
|
||||
|
||||
FLAGS = gflags.FLAGS
|
||||
|
707
ryu/tests/integrated/test_add_flow_v10.py
Normal file
707
ryu/tests/integrated/test_add_flow_v10.py
Normal file
@ -0,0 +1,707 @@
|
||||
# Copyright (C) 2012 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.
|
||||
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
import logging
|
||||
|
||||
from ryu.controller import handler
|
||||
from ryu.controller.handler import set_ev_cls
|
||||
from ryu.tests.integrated import tester
|
||||
from ryu.ofproto import nx_match
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
_target = 'br-tester'
|
||||
|
||||
|
||||
class RunTest(tester.RunTestBase):
|
||||
|
||||
def __init__(self):
|
||||
super(RunTest, self).__init__()
|
||||
|
||||
def send_flow_mod(self, rule, cookie, command, idle_timeout, hard_timeout,
|
||||
priority=None, buffer_id=0xffffffff,
|
||||
out_port=None, flags=0, actions=None):
|
||||
|
||||
if priority is None:
|
||||
priority = self.ofproto.OFP_DEFAULT_PRIORITY
|
||||
if out_port is None:
|
||||
out_port = self.ofproto.OFPP_NONE
|
||||
|
||||
match_tuple = rule.match_tuple()
|
||||
match = self.ofproto_parser.OFPMatch(*match_tuple)
|
||||
flow_mod = self.ofproto_parser.OFPFlowMod(
|
||||
self.datapath, match, cookie, command, idle_timeout, hard_timeout,
|
||||
priority, buffer_id, out_port, flags, actions)
|
||||
|
||||
self.datapath.send_msg(flow_mod)
|
||||
|
||||
def test_action_output(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
out_port = 2
|
||||
self.set_val('out_port', out_port)
|
||||
|
||||
actions = [
|
||||
datapath.ofproto_parser.OFPActionOutput(out_port),
|
||||
]
|
||||
|
||||
rule = nx_match.ClsRule()
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_action_output(self):
|
||||
ovs_actions = {}
|
||||
out_port = self.get_val('out_port')
|
||||
|
||||
try:
|
||||
ovs_actions = self.get_ovs_flows(_target)[0]['actions']
|
||||
ovs_out_port = ovs_actions['output']
|
||||
except (KeyError, IndexError):
|
||||
ovs_out_port = ''
|
||||
|
||||
if ovs_out_port == '' or int(ovs_out_port) != out_port:
|
||||
err = 'send_actions=[output:%s] ovs_actions=[%s]' \
|
||||
% (out_port, self.cnv_txt(ovs_actions))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_action_vlan_vid(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
vlan_vid = 3
|
||||
self.set_val('vlan_vid', vlan_vid)
|
||||
|
||||
actions = [
|
||||
datapath.ofproto_parser.OFPActionVlanVid(vlan_vid),
|
||||
]
|
||||
|
||||
rule = nx_match.ClsRule()
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_action_vlan_vid(self):
|
||||
ovs_actions = {}
|
||||
vlan_vid = self.get_val('vlan_vid')
|
||||
|
||||
try:
|
||||
ovs_actions = self.get_ovs_flows(_target)[0]['actions']
|
||||
ovs_vlan_vid = ovs_actions['mod_vlan_vid']
|
||||
except (KeyError, IndexError):
|
||||
ovs_vlan_vid = ''
|
||||
|
||||
if ovs_vlan_vid == '' or int(ovs_vlan_vid) != vlan_vid:
|
||||
err = 'send_actions=[vlan_vid:%s] ovs_actions=[%s]' \
|
||||
% (vlan_vid, self.cnv_txt(ovs_actions))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_action_vlan_pcp(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
vlan_pcp = 4
|
||||
self.set_val('vlan_pcp', vlan_pcp)
|
||||
|
||||
actions = [
|
||||
datapath.ofproto_parser.OFPActionVlanPcp(vlan_pcp),
|
||||
]
|
||||
|
||||
rule = nx_match.ClsRule()
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_action_vlan_pcp(self):
|
||||
ovs_actions = {}
|
||||
vlan_pcp = self.get_val('vlan_pcp')
|
||||
|
||||
try:
|
||||
ovs_actions = self.get_ovs_flows(_target)[0]['actions']
|
||||
ovs_vlan_pcp = ovs_actions['mod_vlan_pcp']
|
||||
except (KeyError, IndexError):
|
||||
ovs_vlan_pcp = ''
|
||||
|
||||
if ovs_vlan_pcp == '' or int(ovs_vlan_pcp) != vlan_pcp:
|
||||
err = 'send_actions=[vlan_vid:%s] ovs_actions=[%s]' \
|
||||
% (vlan_pcp, self.cnv_txt(ovs_actions))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_action_strip_vlan(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
actions = [
|
||||
datapath.ofproto_parser.OFPActionStripVlan(),
|
||||
]
|
||||
|
||||
rule = nx_match.ClsRule()
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_action_strip_vlan(self):
|
||||
ovs_actions = {}
|
||||
try:
|
||||
ovs_actions = self.get_ovs_flows(_target)[0]['actions']
|
||||
except (KeyError, IndexError):
|
||||
pass
|
||||
|
||||
if not 'strip_vlan' in ovs_actions:
|
||||
err = 'send_actions=[strip_vlan] ovs_actions=[%s]' \
|
||||
% (self.cnv_txt(ovs_actions))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_action_set_dl_src(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
dl_src = '56:b3:42:04:b2:7a'
|
||||
self.set_val('dl_src', dl_src)
|
||||
|
||||
dl_src_bin = self.haddr_to_bin(dl_src)
|
||||
actions = [
|
||||
datapath.ofproto_parser.OFPActionSetDlSrc(dl_src_bin),
|
||||
]
|
||||
|
||||
rule = nx_match.ClsRule()
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_action_set_dl_src(self):
|
||||
ovs_actions = {}
|
||||
dl_src = self.get_val('dl_src')
|
||||
|
||||
try:
|
||||
ovs_actions = self.get_ovs_flows(_target)[0]['actions']
|
||||
ovs_dl_src = ovs_actions['mod_dl_src']
|
||||
except (KeyError, IndexError):
|
||||
ovs_dl_src = ''
|
||||
|
||||
if ovs_dl_src == '' or ovs_dl_src != dl_src:
|
||||
err = 'send_actions=[dl_src:%s] ovs_actions=[%s]' \
|
||||
% (dl_src, self.cnv_txt(ovs_actions))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_action_set_dl_dst(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
dl_dst = 'c2:93:a2:fb:d0:f4'
|
||||
self.set_val('dl_dst', dl_dst)
|
||||
|
||||
dl_dst_bin = self.haddr_to_bin(dl_dst)
|
||||
actions = [
|
||||
datapath.ofproto_parser.OFPActionSetDlDst(dl_dst_bin),
|
||||
]
|
||||
|
||||
rule = nx_match.ClsRule()
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_action_set_dl_dst(self):
|
||||
ovs_actions = {}
|
||||
dl_dst = self.get_val('dl_dst')
|
||||
|
||||
try:
|
||||
ovs_actions = self.get_ovs_flows(_target)[0]['actions']
|
||||
ovs_dl_dst = ovs_actions['mod_dl_dst']
|
||||
except (KeyError, IndexError):
|
||||
ovs_dl_dst = ''
|
||||
|
||||
if ovs_dl_dst == '' or ovs_dl_dst != dl_dst:
|
||||
err = 'send_actions=[dl_dst:%s] ovs_actions=[%s]' \
|
||||
% (dl_dst, self.cnv_txt(ovs_actions))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_action_set_nw_src(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
nw_src = '216.132.81.105'
|
||||
self.set_val('nw_src', nw_src)
|
||||
|
||||
nw_src_int = self.ipv4_to_int(nw_src)
|
||||
|
||||
actions = [
|
||||
datapath.ofproto_parser.OFPActionSetNwSrc(nw_src_int),
|
||||
]
|
||||
|
||||
rule = nx_match.ClsRule()
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_action_set_nw_src(self):
|
||||
ovs_actions = {}
|
||||
nw_src = self.get_val('nw_src')
|
||||
|
||||
try:
|
||||
ovs_actions = self.get_ovs_flows(_target)[0]['actions']
|
||||
ovs_nw_src = ovs_actions['mod_nw_src']
|
||||
except (KeyError, IndexError):
|
||||
ovs_nw_src = ''
|
||||
|
||||
if ovs_nw_src == '' or ovs_nw_src != nw_src:
|
||||
err = 'send_actions=[nw_src:%s] ovs_actions=[%s]' \
|
||||
% (nw_src, self.cnv_txt(ovs_actions))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_action_set_nw_dst(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
nw_dst = '223.201.206.3'
|
||||
self.set_val('nw_dst', nw_dst)
|
||||
|
||||
nw_dst_int = self.ipv4_to_int(nw_dst)
|
||||
|
||||
actions = [
|
||||
datapath.ofproto_parser.OFPActionSetNwDst(nw_dst_int),
|
||||
]
|
||||
|
||||
rule = nx_match.ClsRule()
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_action_set_nw_dst(self):
|
||||
ovs_actions = {}
|
||||
nw_dst = self.get_val('nw_dst')
|
||||
|
||||
try:
|
||||
ovs_actions = self.get_ovs_flows(_target)[0]['actions']
|
||||
ovs_nw_dst = ovs_actions['mod_nw_dst']
|
||||
except (KeyError, IndexError):
|
||||
ovs_nw_dst = ''
|
||||
|
||||
if ovs_nw_dst == '' or ovs_nw_dst != nw_dst:
|
||||
err = 'send_actions=[nw_dst:%s] ovs_actions=[%s]' \
|
||||
% (nw_dst, self.cnv_txt(ovs_actions))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_action_set_nw_tos(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
nw_tos = 111
|
||||
self.set_val('nw_tos', nw_tos)
|
||||
|
||||
actions = [
|
||||
datapath.ofproto_parser.OFPActionSetNwTos(nw_tos),
|
||||
]
|
||||
|
||||
rule = nx_match.ClsRule()
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_action_set_nw_tos(self):
|
||||
ovs_actions = {}
|
||||
nw_tos = self.get_val('nw_tos')
|
||||
|
||||
try:
|
||||
ovs_actions = self.get_ovs_flows(_target)[0]['actions']
|
||||
ovs_nw_tos = ovs_actions['mod_nw_tos']
|
||||
except (KeyError, IndexError):
|
||||
ovs_nw_tos = ''
|
||||
|
||||
if ovs_nw_tos == '' or int(ovs_nw_tos) != nw_tos:
|
||||
err = 'send_actions=[nw_tos:%s] ovs_actions=[%s]' \
|
||||
% (nw_tos, self.cnv_txt(ovs_actions))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_action_set_tp_src(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
tp_src = 55420
|
||||
self.set_val('tp_src', tp_src)
|
||||
|
||||
actions = [
|
||||
datapath.ofproto_parser.OFPActionSetTpSrc(tp_src),
|
||||
]
|
||||
|
||||
rule = nx_match.ClsRule()
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_action_set_tp_src(self):
|
||||
ovs_actions = {}
|
||||
tp_src = self.get_val('tp_src')
|
||||
|
||||
try:
|
||||
ovs_actions = self.get_ovs_flows(_target)[0]['actions']
|
||||
ovs_tp_src = ovs_actions['mod_tp_src']
|
||||
except (KeyError, IndexError):
|
||||
ovs_tp_src = ''
|
||||
|
||||
if ovs_tp_src == '' or int(ovs_tp_src) != tp_src:
|
||||
err = 'send_actions=[tp_src:%s] ovs_actions=[%s]' \
|
||||
% (tp_src, self.cnv_txt(ovs_actions))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_action_set_tp_dst(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
tp_dst = 15430
|
||||
self.set_val('tp_dst', tp_dst)
|
||||
|
||||
actions = [
|
||||
datapath.ofproto_parser.OFPActionSetTpDst(tp_dst),
|
||||
]
|
||||
|
||||
rule = nx_match.ClsRule()
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_action_set_tp_dst(self):
|
||||
ovs_actions = {}
|
||||
tp_dst = self.get_val('tp_dst')
|
||||
|
||||
try:
|
||||
ovs_actions = self.get_ovs_flows(_target)[0]['actions']
|
||||
ovs_tp_dst = ovs_actions['mod_tp_dst']
|
||||
except (KeyError, IndexError):
|
||||
ovs_tp_dst = ''
|
||||
|
||||
if ovs_tp_dst == '' or int(ovs_tp_dst) != tp_dst:
|
||||
err = 'send_actions=[tp_src:%s] ovs_actions=[%s]' \
|
||||
% (tp_dst, self.cnv_txt(ovs_actions))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_action_enqueue(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
port = 207
|
||||
queue_id = 4287508753
|
||||
self.set_val('enqueue', str(port) + 'q' + str(queue_id))
|
||||
|
||||
actions = [
|
||||
datapath.ofproto_parser.OFPActionEnqueue(port, queue_id),
|
||||
]
|
||||
|
||||
rule = nx_match.ClsRule()
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_action_enqueue(self):
|
||||
ovs_actions = {}
|
||||
enqueue = self.get_val('enqueue')
|
||||
|
||||
try:
|
||||
ovs_actions = self.get_ovs_flows(_target)[0]['actions']
|
||||
ovs_enqueue = ovs_actions['enqueue']
|
||||
except (KeyError, IndexError):
|
||||
ovs_enqueue = ''
|
||||
|
||||
if ovs_enqueue == '' or ovs_enqueue != enqueue:
|
||||
err = 'send_actions=[enqueue:%s] ovs_actions=[%s]' \
|
||||
% (enqueue, self.cnv_txt(ovs_actions))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_rule_set_in_port(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
in_port = 32
|
||||
self.set_val('in_port', in_port)
|
||||
|
||||
actions = []
|
||||
rule = nx_match.ClsRule()
|
||||
rule.set_in_port(in_port)
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_rule_set_in_port(self):
|
||||
ovs_rules = {}
|
||||
in_port = self.get_val('in_port')
|
||||
|
||||
try:
|
||||
ovs_rules = self.get_ovs_flows(_target)[0]['rules']
|
||||
ovs_in_port = ovs_rules['in_port']
|
||||
except (KeyError, IndexError):
|
||||
ovs_in_port = ''
|
||||
|
||||
if ovs_in_port == '' or int(ovs_in_port) != in_port:
|
||||
err = 'send_rules=[in_port:%s] ovs_rules=[%s]' \
|
||||
% (in_port, self.cnv_txt(ovs_rules))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_rule_set_dl_src(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
dl_src = 'b8:a1:94:51:78:83'
|
||||
self.set_val('dl_src', dl_src)
|
||||
|
||||
dl_src_bin = self.haddr_to_bin(dl_src)
|
||||
|
||||
actions = []
|
||||
rule = nx_match.ClsRule()
|
||||
rule.set_dl_src(dl_src_bin)
|
||||
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_rule_set_dl_src(self):
|
||||
ovs_rules = {}
|
||||
dl_src = self.get_val('dl_src')
|
||||
|
||||
try:
|
||||
ovs_rules = self.get_ovs_flows(_target)[0]['rules']
|
||||
ovs_dl_src = ovs_rules['dl_src']
|
||||
except (KeyError, IndexError):
|
||||
ovs_dl_src = ''
|
||||
|
||||
if ovs_dl_src == '' or ovs_dl_src != dl_src:
|
||||
err = 'send_rules=[dl_src:%s] ovs_rules=[%s]' \
|
||||
% (dl_src, self.cnv_txt(ovs_rules))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_rule_set_dl_type_ip(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
dl_type = nx_match.ETH_TYPE_IP
|
||||
self.set_val('dl_type', 'ip')
|
||||
|
||||
actions = []
|
||||
rule = nx_match.ClsRule()
|
||||
rule.set_dl_type(dl_type)
|
||||
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_rule_set_dl_type_ip(self):
|
||||
ovs_rules = {}
|
||||
dl_type = self.get_val('dl_type')
|
||||
|
||||
try:
|
||||
ovs_rules = self.get_ovs_flows(_target)[0]['rules']
|
||||
except (KeyError, IndexError):
|
||||
pass
|
||||
|
||||
if not dl_type in ovs_rules:
|
||||
err = 'send_rules=[dl_type:%s] ovs_rules=[%s]' \
|
||||
% (dl_type, self.cnv_txt(ovs_rules))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_rule_set_dl_type_arp(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
dl_type = nx_match.ETH_TYPE_ARP
|
||||
self.set_val('dl_type', 'arp')
|
||||
|
||||
actions = []
|
||||
rule = nx_match.ClsRule()
|
||||
rule.set_dl_type(dl_type)
|
||||
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_rule_set_dl_type_arp(self):
|
||||
ovs_rules = {}
|
||||
dl_type = self.get_val('dl_type')
|
||||
|
||||
try:
|
||||
ovs_rules = self.get_ovs_flows(_target)[0]['rules']
|
||||
except (KeyError, IndexError):
|
||||
pass
|
||||
|
||||
if not dl_type in ovs_rules:
|
||||
err = 'send_rules=[dl_type:%s] ovs_rules=[%s]' \
|
||||
% (dl_type, self.cnv_txt(ovs_rules))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_rule_set_dl_type_vlan(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
dl_type = nx_match.ETH_TYPE_VLAN
|
||||
self.set_val('dl_type', nx_match.ETH_TYPE_VLAN)
|
||||
|
||||
actions = []
|
||||
rule = nx_match.ClsRule()
|
||||
rule.set_dl_type(dl_type)
|
||||
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_rule_set_dl_type_vlan(self):
|
||||
ovs_rules = {}
|
||||
dl_type = self.get_val('dl_type')
|
||||
|
||||
try:
|
||||
ovs_rules = self.get_ovs_flows(_target)[0]['rules']
|
||||
ovs_dl_type = ovs_rules['dl_type']
|
||||
except (KeyError, IndexError):
|
||||
ovs_dl_type = ''
|
||||
|
||||
if ovs_dl_type == '' or int(ovs_dl_type, 16) != dl_type:
|
||||
err = 'send_rules=[dl_src:%s] ovs_rules=[%s]' \
|
||||
% (dl_type, self.cnv_txt(ovs_rules))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_rule_set_dl_type_ipv6(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
dl_type = nx_match.ETH_TYPE_IPV6
|
||||
self.set_val('dl_type', 'ipv6')
|
||||
|
||||
actions = []
|
||||
rule = nx_match.ClsRule()
|
||||
rule.set_dl_type(dl_type)
|
||||
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_rule_set_dl_type_ipv6(self):
|
||||
ovs_rules = {}
|
||||
dl_type = self.get_val('dl_type')
|
||||
|
||||
try:
|
||||
ovs_rules = self.get_ovs_flows(_target)[0]['rules']
|
||||
except (KeyError, IndexError):
|
||||
pass
|
||||
|
||||
if not dl_type in ovs_rules:
|
||||
err = 'send_rules=[dl_type:%s] ovs_rules=[%s]' \
|
||||
% (dl_type, self.cnv_txt(ovs_rules))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
||||
|
||||
def test_rule_set_dl_type_lacp(self):
|
||||
datapath = self.datapath
|
||||
ofproto = self.ofproto
|
||||
|
||||
dl_type = nx_match.ETH_TYPE_LACP
|
||||
self.set_val('dl_type', nx_match.ETH_TYPE_LACP)
|
||||
|
||||
actions = []
|
||||
rule = nx_match.ClsRule()
|
||||
rule.set_dl_type(dl_type)
|
||||
|
||||
self.send_flow_mod(
|
||||
rule=rule, cookie=0, command=ofproto.OFPFC_ADD,
|
||||
idle_timeout=0, hard_timeout=0,
|
||||
priority=ofproto.OFP_DEFAULT_PRIORITY,
|
||||
flags=ofproto.OFPFF_SEND_FLOW_REM, actions=actions)
|
||||
|
||||
def check_rule_set_dl_type_lacp(self):
|
||||
ovs_rules = {}
|
||||
dl_type = self.get_val('dl_type')
|
||||
|
||||
try:
|
||||
ovs_rules = self.get_ovs_flows(_target)[0]['rules']
|
||||
ovs_dl_type = ovs_rules['dl_type']
|
||||
except (KeyError, IndexError):
|
||||
ovs_dl_type = ''
|
||||
|
||||
if ovs_dl_type == '' or int(ovs_dl_type, 16) != dl_type:
|
||||
err = 'send_rules=[dl_src:%s] ovs_rules=[%s]' \
|
||||
% (dl_type, self.cnv_txt(ovs_rules))
|
||||
self.results(ret=False, msg=err)
|
||||
return
|
||||
self.results()
|
1063
ryu/tests/integrated/test_add_flow_v12_actions.py
Normal file
1063
ryu/tests/integrated/test_add_flow_v12_actions.py
Normal file
File diff suppressed because it is too large
Load Diff
2037
ryu/tests/integrated/test_add_flow_v12_matches.py
Normal file
2037
ryu/tests/integrated/test_add_flow_v12_matches.py
Normal file
File diff suppressed because it is too large
Load Diff
351
ryu/tests/integrated/tester.py
Normal file
351
ryu/tests/integrated/tester.py
Normal file
@ -0,0 +1,351 @@
|
||||
# Copyright (C) 2012 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.
|
||||
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
import sys
|
||||
import gflags
|
||||
import logging
|
||||
import subprocess
|
||||
import traceback
|
||||
|
||||
from ryu import utils
|
||||
from ryu.lib import mac
|
||||
from ryu.base import app_manager
|
||||
from ryu.controller import ofp_event
|
||||
from ryu.controller import dispatcher
|
||||
from ryu.controller import event
|
||||
from ryu.controller import handler
|
||||
from ryu.controller.handler import MAIN_DISPATCHER
|
||||
from ryu.controller.handler import CONFIG_DISPATCHER
|
||||
from ryu.controller.handler import set_ev_cls
|
||||
from ryu.ofproto import nx_match
|
||||
from ryu.ofproto import ofproto_v1_0
|
||||
from ryu.ofproto import ofproto_v1_2
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
FLAGS = gflags.FLAGS
|
||||
gflags.DEFINE_string('run_test_mod', '', 'Test run the module name.')
|
||||
|
||||
|
||||
class EventRunTest(event.EventBase):
|
||||
def __init__(self, datapath):
|
||||
super(EventRunTest, self).__init__()
|
||||
self.datapath = datapath
|
||||
|
||||
|
||||
QUEUE_NAME_RUN_TEST_EV = 'run_test_event'
|
||||
DISPATCHER_NAME_RUN_TEST_EV = 'run_test_event'
|
||||
RUN_TEST_EV_DISPATCHER = dispatcher.EventDispatcher(
|
||||
DISPATCHER_NAME_RUN_TEST_EV)
|
||||
|
||||
|
||||
LOG_TEST_START = 'TEST_START: %s'
|
||||
LOG_TEST_RESULTS = 'TEST_RESULTS:'
|
||||
LOG_TEST_FINISH = 'TEST_FINISHED: Completed=[%s], OK=[%s], NG=[%s]'
|
||||
|
||||
|
||||
class Tester(app_manager.RyuApp):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Tester, self).__init__()
|
||||
self.ev_q = dispatcher.EventQueue(QUEUE_NAME_RUN_TEST_EV,
|
||||
RUN_TEST_EV_DISPATCHER)
|
||||
|
||||
run_test_mod = utils.import_module(FLAGS.run_test_mod)
|
||||
LOG.debug('import run_test_mod.[%s]', run_test_mod.__name__)
|
||||
|
||||
self.run_test = run_test_mod.RunTest(*args, **kwargs)
|
||||
handler.register_instance(self.run_test)
|
||||
|
||||
@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
|
||||
def switch_features_handler(self, ev):
|
||||
msg = ev.msg
|
||||
datapath = msg.datapath
|
||||
|
||||
send_delete_all_flows(datapath)
|
||||
datapath.send_barrier()
|
||||
|
||||
@set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER)
|
||||
def barrier_replay_handler(self, ev):
|
||||
self.ev_q.queue(EventRunTest(ev.msg.datapath))
|
||||
|
||||
@set_ev_cls(EventRunTest, RUN_TEST_EV_DISPATCHER)
|
||||
def run_test_halder(self, ev):
|
||||
dp = ev.datapath
|
||||
t = self.run_test
|
||||
|
||||
if not t._test_started():
|
||||
t._test_init(dp)
|
||||
|
||||
if not self._run_test(t):
|
||||
# run_test was throwing exception.
|
||||
LOG.info(LOG_TEST_FINISH, False, t._RESULTS_OK, t._RESULTS_NG)
|
||||
return
|
||||
|
||||
if not t._test_completed():
|
||||
t.datapath.send_barrier()
|
||||
return
|
||||
|
||||
# Completed all tests.
|
||||
LOG.info(LOG_TEST_FINISH, True, t._RESULTS_OK, t._RESULTS_NG)
|
||||
|
||||
def _run_test(self, t):
|
||||
running = t._running()
|
||||
|
||||
if len(running) == 0:
|
||||
# next test
|
||||
name = t._pop_test()
|
||||
LOG.info(LOG_TEST_START, name)
|
||||
try:
|
||||
getattr(t, name)()
|
||||
except Exception:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
traceback.print_exception(exc_type, exc_value,
|
||||
exc_traceback, file=sys.stdout)
|
||||
send_delete_all_flows(t.datapath)
|
||||
return False
|
||||
else:
|
||||
# check
|
||||
name = 'check_' + running[5:]
|
||||
|
||||
if not name in dir(t):
|
||||
name = '_check_default'
|
||||
|
||||
err = 0
|
||||
try:
|
||||
# LOG.debug('_run_test: CHECK_TEST = [%s]', name)
|
||||
getattr(t, name)()
|
||||
except Exception:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
traceback.print_exception(exc_type, exc_value,
|
||||
exc_traceback, file=sys.stdout)
|
||||
err = 1
|
||||
finally:
|
||||
send_delete_all_flows(t.datapath)
|
||||
if err:
|
||||
return False
|
||||
t._check_run()
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def _send_delete_all_flows_v10(dp):
|
||||
rule = nx_match.ClsRule()
|
||||
match = dp.ofproto_parser.OFPMatch(dp.ofproto.OFPFW_ALL,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0)
|
||||
m = dp.ofproto_parser.OFPFlowMod(
|
||||
dp, match, 0,
|
||||
dp.ofproto.OFPFC_DELETE,
|
||||
0, 0, 0, 0,
|
||||
dp.ofproto.OFPP_NONE, 0, None)
|
||||
dp.send_msg(m)
|
||||
|
||||
|
||||
def _send_delete_all_flows_v12(dp):
|
||||
match = dp.ofproto_parser.OFPMatch()
|
||||
inst = []
|
||||
m = dp.ofproto_parser.OFPFlowMod(dp, 0, 0, 0,
|
||||
dp.ofproto.OFPFC_DELETE,
|
||||
0, 0, 0, 0,
|
||||
dp.ofproto.OFPP_ANY, 0xffffffff,
|
||||
0, match, inst)
|
||||
dp.send_msg(m)
|
||||
|
||||
|
||||
def send_delete_all_flows(dp):
|
||||
assert dp.ofproto in (ofproto_v1_0, ofproto_v1_2)
|
||||
if dp.ofproto == ofproto_v1_0:
|
||||
_send_delete_all_flows_v10(dp)
|
||||
elif dp.ofproto == ofproto_v1_2:
|
||||
_send_delete_all_flows_v12(dp)
|
||||
else:
|
||||
# this function will be remove.
|
||||
dp.send_delete_all_flows()
|
||||
|
||||
|
||||
def run_command(cmd, redirect_output=True, check_exit_code=True, env=None):
|
||||
if redirect_output:
|
||||
stdout = subprocess.PIPE
|
||||
else:
|
||||
stdout = None
|
||||
|
||||
proc = subprocess.Popen(cmd, stdout=stdout,
|
||||
stderr=subprocess.STDOUT, env=env)
|
||||
output = proc.communicate()[0]
|
||||
|
||||
LOG.debug('Exec command "%s" \n%s', ' '.join(cmd), output)
|
||||
if check_exit_code and proc.returncode != 0:
|
||||
raise Exception('Command "%s" failed.\n%s' % (' '.join(cmd), output))
|
||||
return output
|
||||
|
||||
|
||||
class RunTestBase(object):
|
||||
"""
|
||||
To run the tests is required for the following pair of functions.
|
||||
1. test_<test name>()
|
||||
To send flows to switch.
|
||||
|
||||
2. check_<test name>() or _check_default()
|
||||
To check flows of switch.
|
||||
|
||||
To deal common values to the functions(test_ and check_)
|
||||
can use `set_val('name', val)` and `get_val('name')`.
|
||||
This values is initialized before the next tests.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(RunTestBase, self).__init__()
|
||||
|
||||
self._TEST_STARTED = False
|
||||
self._TESTS = []
|
||||
self._RUNNING = ''
|
||||
self._RESULTS_OK = 0
|
||||
self._RESULTS_NG = 0
|
||||
self._CHECK = {}
|
||||
|
||||
def _test_started(self):
|
||||
return self._TEST_STARTED
|
||||
|
||||
def _test_init(self, dp):
|
||||
self.datapath = dp
|
||||
self.ofproto = dp.ofproto
|
||||
self.ofproto_parser = dp.ofproto_parser
|
||||
|
||||
for name in dir(self):
|
||||
if name.startswith("test_"):
|
||||
self._TESTS.append(name)
|
||||
self._TEST_STARTED = True
|
||||
|
||||
def _test_completed(self):
|
||||
if self._TEST_STARTED:
|
||||
if len(self._RUNNING) + len(self._TESTS) == 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _pop_test(self):
|
||||
self._RUNNING = self._TESTS.pop()
|
||||
return self._RUNNING
|
||||
|
||||
def _running(self):
|
||||
return self._RUNNING
|
||||
|
||||
def _check_run(self):
|
||||
self._RUNNING = ''
|
||||
|
||||
def _check_default(self):
|
||||
err = 'function %s() is not found.' % (self._RUNNING, )
|
||||
self.results(ret=False, msg=err)
|
||||
|
||||
def results(self, name=None, ret=True, msg=''):
|
||||
if not name:
|
||||
name = self._RUNNING
|
||||
|
||||
if ret:
|
||||
res = 'OK'
|
||||
self._RESULTS_OK += 1
|
||||
else:
|
||||
res = 'NG'
|
||||
self._RESULTS_NG += 1
|
||||
|
||||
LOG.info('%s %s [%s] %s', LOG_TEST_RESULTS, name, res, '\n' + msg)
|
||||
|
||||
def set_val(self, name, val):
|
||||
self._CHECK[name] = val
|
||||
|
||||
def get_val(self, name):
|
||||
return self._CHECK[name]
|
||||
|
||||
def del_val(self, name):
|
||||
del self._CHECK[name]
|
||||
|
||||
def del_val_all(self):
|
||||
self._CHECK.clear()
|
||||
|
||||
def get_ovs_flows(self, target):
|
||||
# flows (return):
|
||||
# [flow1, flow2,...]
|
||||
# flow:
|
||||
# {'actions': actions, 'rules': rules}
|
||||
# or {'apply_actions': actions, 'rules': rules}
|
||||
# or {'write_actions': actions, 'rules': rules}
|
||||
# or {'clear_actions': actions, 'rules': rules}
|
||||
# actions, rules:
|
||||
# {'<name>': <val>}
|
||||
|
||||
cmd = ('sudo', 'ovs-ofctl', 'dump-flows', target)
|
||||
output = run_command(cmd)
|
||||
|
||||
flows = []
|
||||
for line in output.splitlines():
|
||||
if line.startswith(" "):
|
||||
flow = {}
|
||||
rules, actions = line.split('actions=')
|
||||
rules = self.cnv_list(rules, '=')
|
||||
|
||||
if actions.startswith("apply_actions"):
|
||||
a_name = 'apply_actions'
|
||||
actions = actions[len(a_name) + 1:-1]
|
||||
elif actions.startswith("write_actions"):
|
||||
a_name = 'write_actions'
|
||||
actions = actions[len(a_name) + 1:-1]
|
||||
elif actions.startswith("clear_actions"):
|
||||
a_name = 'clear_actions'
|
||||
actions = actions[len(a_name) + 1:-1]
|
||||
else:
|
||||
a_name = 'actions'
|
||||
actions = self.cnv_list(actions, ':')
|
||||
flows.append({'rules': rules, a_name: actions, })
|
||||
|
||||
return flows
|
||||
|
||||
def cnv_list(self, tmp, sep):
|
||||
list_ = {}
|
||||
for p in tmp.split(','):
|
||||
if len(p.strip()) == 0:
|
||||
continue
|
||||
|
||||
if p.find(sep) > 0:
|
||||
name, val = p.strip().split(sep, 1)
|
||||
else:
|
||||
name = val = p.strip()
|
||||
list_[name] = val
|
||||
return list_
|
||||
|
||||
def cnv_txt(self, tmp, sep='='):
|
||||
return ",".join([(str(x) + sep + str(tmp[x])) for x in tmp if x >= 0])
|
||||
|
||||
def haddr_to_str(self, addr):
|
||||
return mac.haddr_to_str(addr)
|
||||
|
||||
def haddr_to_bin(self, string):
|
||||
return mac.haddr_to_bin(string)
|
||||
|
||||
def ipv4_to_int(self, string):
|
||||
ip = string.split('.')
|
||||
assert len(ip) == 4
|
||||
i = 0
|
||||
for b in ip:
|
||||
b = int(b)
|
||||
i = (i << 8) | b
|
||||
return i
|
||||
|
||||
def ipv6_to_int(self, string):
|
||||
ip = string.split(':')
|
||||
assert len(ip) == 8
|
||||
return [int(x, 16) for x in ip]
|
Loading…
Reference in New Issue
Block a user