mirror of
https://github.com/faucetsdn/ryu.git
synced 2026-01-22 17:12:01 +01:00
tester: Support to test OpenFlow1.0 switch
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:
parent
7c7fb56ad6
commit
74d5de7803
@ -46,10 +46,12 @@ CONF.register_cli_opts([
|
||||
cfg.StrOpt('dir', default='ryu/tests/switch/of13',
|
||||
help='test files directory'),
|
||||
cfg.StrOpt('target-version', default='openflow13',
|
||||
help='target sw OFP version [openflow13|openflow14] '
|
||||
help='target sw OFP version '
|
||||
'[openflow10|openflow13|openflow14] '
|
||||
'(default: openflow13)'),
|
||||
cfg.StrOpt('tester-version', default='openflow13',
|
||||
help='tester sw OFP version [openflow13|openflow14] '
|
||||
help='tester sw OFP version '
|
||||
'[openflow10|openflow13|openflow14] '
|
||||
'(default: openflow13)'),
|
||||
cfg.IntOpt('interval', default=0,
|
||||
help='interval time in seconds of each test '
|
||||
|
||||
@ -48,9 +48,11 @@ from ryu.lib import dpid as dpid_lib
|
||||
from ryu.lib import hub
|
||||
from ryu.lib import stringify
|
||||
from ryu.lib.packet import packet
|
||||
from ryu.ofproto import ofproto_parser
|
||||
from ryu.ofproto import ofproto_protocol
|
||||
from ryu.ofproto import ofproto_v1_0
|
||||
from ryu.ofproto import ofproto_v1_2
|
||||
from ryu.ofproto import ofproto_v1_3
|
||||
from ryu.ofproto import ofproto_v1_3_parser
|
||||
from ryu.ofproto import ofproto_v1_4
|
||||
from ryu.ofproto import ofproto_v1_5
|
||||
|
||||
@ -289,6 +291,7 @@ class OfTester(app_manager.RyuApp):
|
||||
|
||||
def __get_version(opt):
|
||||
vers = {
|
||||
'openflow10': ofproto_v1_0.OFP_VERSION,
|
||||
'openflow13': ofproto_v1_3.OFP_VERSION,
|
||||
'openflow14': ofproto_v1_4.OFP_VERSION,
|
||||
'openflow15': ofproto_v1_5.OFP_VERSION
|
||||
@ -297,9 +300,8 @@ class OfTester(app_manager.RyuApp):
|
||||
if ver is None:
|
||||
self.logger.error(
|
||||
'%s is not supported. '
|
||||
'Supported versions are openflow13, '
|
||||
'openflow14 and openflow15.',
|
||||
opt)
|
||||
'Supported versions are %s.',
|
||||
opt, list(vers.keys()))
|
||||
self._test_end()
|
||||
return ver
|
||||
|
||||
@ -364,6 +366,7 @@ class OfTester(app_manager.RyuApp):
|
||||
|
||||
def _register_sw(self, dp):
|
||||
vers = {
|
||||
ofproto_v1_0.OFP_VERSION: 'openflow10',
|
||||
ofproto_v1_3.OFP_VERSION: 'openflow13',
|
||||
ofproto_v1_4.OFP_VERSION: 'openflow14',
|
||||
ofproto_v1_5.OFP_VERSION: 'openflow15'
|
||||
@ -381,9 +384,6 @@ class OfTester(app_manager.RyuApp):
|
||||
vers[OfTester.tester_ver]
|
||||
else:
|
||||
self.tester_sw.dp = dp
|
||||
self.tester_sw.add_flow(
|
||||
in_port=self.tester_recv_port_1,
|
||||
out_port=dp.ofproto.OFPP_CONTROLLER)
|
||||
msg = 'Join tester SW.'
|
||||
else:
|
||||
msg = 'Connect unknown SW.'
|
||||
@ -456,8 +456,8 @@ class OfTester(app_manager.RyuApp):
|
||||
self._test(STATE_INIT_METER)
|
||||
self._test(STATE_INIT_GROUP)
|
||||
self._test(STATE_INIT_FLOW, self.target_sw)
|
||||
self._test(STATE_INIT_THROUGHPUT_FLOW, self.tester_sw,
|
||||
THROUGHPUT_COOKIE)
|
||||
self._test(STATE_INIT_THROUGHPUT_FLOW, self.tester_sw)
|
||||
|
||||
# Install flows.
|
||||
for flow in test.prerequisite:
|
||||
if isinstance(
|
||||
@ -599,8 +599,17 @@ class OfTester(app_manager.RyuApp):
|
||||
self.state = state
|
||||
return test[state](*args)
|
||||
|
||||
def _test_initialize_flow(self, datapath, cookie=0):
|
||||
xid = datapath.del_flows(cookie)
|
||||
def _test_initialize_flow(self, datapath):
|
||||
# Note: Because DELETE and DELETE_STRICT commands in OpenFlow 1.0
|
||||
# can not be filtered by the cookie value, this tool deletes all
|
||||
# flow entries of the tester switch temporarily and inserts default
|
||||
# flow entry immediately.
|
||||
xid = datapath.del_flows()
|
||||
self.send_msg_xids.append(xid)
|
||||
|
||||
xid = datapath.add_flow(
|
||||
in_port=self.tester_recv_port_1,
|
||||
out_port=datapath.dp.ofproto.OFPP_CONTROLLER)
|
||||
self.send_msg_xids.append(xid)
|
||||
|
||||
xid = datapath.send_barrier_request()
|
||||
@ -624,21 +633,24 @@ class OfTester(app_manager.RyuApp):
|
||||
assert isinstance(msg, datapath.dp.ofproto_parser.OFPBarrierReply)
|
||||
|
||||
def _test_exist_check(self, method, message):
|
||||
ofp = method.__self__.dp.ofproto
|
||||
parser = method.__self__.dp.ofproto_parser
|
||||
method_dict = {
|
||||
OpenFlowSw.send_flow_stats.__name__: {
|
||||
'reply': parser.OFPFlowStatsReply,
|
||||
'compare': self._compare_flow
|
||||
},
|
||||
OpenFlowSw.send_meter_config_stats.__name__: {
|
||||
'reply': parser.OFPMeterConfigStatsReply,
|
||||
'compare': self._compare_meter
|
||||
},
|
||||
OpenFlowSw.send_group_desc_stats.__name__: {
|
||||
}
|
||||
}
|
||||
if ofp.OFP_VERSION >= ofproto_v1_2.OFP_VERSION:
|
||||
method_dict[OpenFlowSw.send_group_desc_stats.__name__] = {
|
||||
'reply': parser.OFPGroupDescStatsReply,
|
||||
'compare': self._compare_group
|
||||
}
|
||||
}
|
||||
if ofp.OFP_VERSION >= ofproto_v1_3.OFP_VERSION:
|
||||
method_dict[OpenFlowSw.send_meter_config_stats.__name__] = {
|
||||
'reply': parser.OFPMeterConfigStatsReply,
|
||||
'compare': self._compare_meter
|
||||
}
|
||||
xid = method()
|
||||
self.send_msg_xids.append(xid)
|
||||
self._wait()
|
||||
@ -655,13 +667,18 @@ class OfTester(app_manager.RyuApp):
|
||||
ng_stats.append(stats)
|
||||
|
||||
error_dict = {
|
||||
OpenFlowSw.send_flow_stats.__name__:
|
||||
{'flows': ', '.join(ng_stats)},
|
||||
OpenFlowSw.send_meter_config_stats.__name__:
|
||||
{'meters': ', '.join(ng_stats)},
|
||||
OpenFlowSw.send_group_desc_stats.__name__:
|
||||
{'groups': ', '.join(ng_stats)}
|
||||
OpenFlowSw.send_flow_stats.__name__: {
|
||||
'flows': ', '.join(ng_stats)
|
||||
}
|
||||
}
|
||||
if ofp.OFP_VERSION >= ofproto_v1_2.OFP_VERSION:
|
||||
error_dict[OpenFlowSw.send_group_desc_stats.__name__] = {
|
||||
'groups': ', '.join(ng_stats)
|
||||
}
|
||||
if ofp.OFP_VERSION >= ofproto_v1_3.OFP_VERSION:
|
||||
error_dict[OpenFlowSw.send_meter_config_stats.__name__] = {
|
||||
'meters': ', '.join(ng_stats)
|
||||
}
|
||||
raise TestFailure(self.state, **error_dict[method.__name__])
|
||||
|
||||
def _test_get_packet_count(self, is_target):
|
||||
@ -711,15 +728,17 @@ class OfTester(app_manager.RyuApp):
|
||||
else pkt[KEY_PKT_IN])
|
||||
|
||||
if hasattr(msg.datapath.ofproto, "OFPR_NO_MATCH"):
|
||||
table_miss_value = msg.datapath.ofproto.OFPR_NO_MATCH
|
||||
invalid_packet_in_reason = [msg.datapath.ofproto.OFPR_NO_MATCH]
|
||||
else:
|
||||
table_miss_value = msg.datapath.ofproto.OFPR_TABLE_MISS
|
||||
invalid_packet_in_reason = [msg.datapath.ofproto.OFPR_TABLE_MISS]
|
||||
if hasattr(msg.datapath.ofproto, "OFPR_INVALID_TTL"):
|
||||
invalid_packet_in_reason.append(
|
||||
msg.datapath.ofproto.OFPR_INVALID_TTL)
|
||||
|
||||
if msg.datapath.id != pkt_in_src_model.dp.id:
|
||||
pkt_type = 'packet-in'
|
||||
err_msg = 'SW[dpid=%s]' % dpid_lib.dpid_to_str(msg.datapath.id)
|
||||
elif msg.reason == table_miss_value or \
|
||||
msg.reason == msg.datapath.ofproto.OFPR_INVALID_TTL:
|
||||
elif msg.reason in invalid_packet_in_reason:
|
||||
pkt_type = 'packet-in'
|
||||
err_msg = 'OFPPacketIn[reason=%d]' % msg.reason
|
||||
elif repr(msg.data) != repr(model_pkt):
|
||||
@ -878,45 +897,26 @@ class OfTester(app_manager.RyuApp):
|
||||
|
||||
def __reasm_match(match):
|
||||
""" reassemble match_fields. """
|
||||
mask_lengths = {'vlan_vid': 12 + 1,
|
||||
'ipv6_flabel': 20,
|
||||
'ipv6_exthdr': 9}
|
||||
match_fields = list()
|
||||
for key, united_value in match.items():
|
||||
if isinstance(united_value, tuple):
|
||||
(value, mask) = united_value
|
||||
# look up oxm_fields.TypeDescr to get mask length.
|
||||
for ofb in stats2.datapath.ofproto.oxm_types:
|
||||
if ofb.name == key:
|
||||
# create all one bits mask
|
||||
mask_len = mask_lengths.get(
|
||||
key, ofb.type.size * 8)
|
||||
all_one_bits = 2 ** mask_len - 1
|
||||
# convert mask to integer
|
||||
mask_bytes = ofb.type.from_user(mask)
|
||||
oxm_mask = int(binascii.hexlify(mask_bytes), 16)
|
||||
# when mask is all one bits, remove mask
|
||||
if oxm_mask & all_one_bits == all_one_bits:
|
||||
united_value = value
|
||||
# when mask is all zero bits, remove field.
|
||||
elif oxm_mask & all_one_bits == 0:
|
||||
united_value = None
|
||||
break
|
||||
if united_value is not None:
|
||||
match_fields.append((key, united_value))
|
||||
match_fields = match.to_jsondict()
|
||||
# For only OpenFlow1.0
|
||||
match_fields['OFPMatch'].pop('wildcards', None)
|
||||
return match_fields
|
||||
|
||||
attr_list = ['cookie', 'priority', 'hard_timeout', 'idle_timeout',
|
||||
'table_id', 'instructions', 'match']
|
||||
'match']
|
||||
if self.target_sw.dp.ofproto.OFP_VERSION == ofproto_v1_0.OFP_VERSION:
|
||||
attr_list += ['actions']
|
||||
else:
|
||||
attr_list += ['table_id', 'instructions']
|
||||
for attr in attr_list:
|
||||
value1 = getattr(stats1, attr)
|
||||
value2 = getattr(stats2, attr)
|
||||
if attr == 'instructions':
|
||||
if attr in ['actions', 'instructions']:
|
||||
value1 = sorted(value1, key=lambda x: x.type)
|
||||
value2 = sorted(value2, key=lambda x: x.type)
|
||||
elif attr == 'match':
|
||||
value1 = sorted(__reasm_match(value1))
|
||||
value2 = sorted(__reasm_match(value2))
|
||||
value1 = __reasm_match(value1)
|
||||
value2 = __reasm_match(value2)
|
||||
if str(value1) != str(value2):
|
||||
flow_stats = []
|
||||
for attr in attr_list:
|
||||
@ -1084,27 +1084,31 @@ class OfTester(app_manager.RyuApp):
|
||||
def stats_reply_handler(self, ev):
|
||||
# keys: stats reply event classes
|
||||
# values: states in which the events should be processed
|
||||
ofp = ev.msg.datapath.ofproto
|
||||
event_states = {
|
||||
ofp_event.EventOFPFlowStatsReply:
|
||||
[STATE_FLOW_EXIST_CHK,
|
||||
STATE_THROUGHPUT_FLOW_EXIST_CHK,
|
||||
STATE_GET_THROUGHPUT],
|
||||
ofp_event.EventOFPMeterConfigStatsReply:
|
||||
[STATE_METER_EXIST_CHK],
|
||||
ofp_event.EventOFPTableStatsReply:
|
||||
[STATE_GET_MATCH_COUNT,
|
||||
STATE_FLOW_UNMATCH_CHK],
|
||||
ofp_event.EventOFPPortStatsReply:
|
||||
[STATE_TARGET_PKT_COUNT,
|
||||
STATE_TESTER_PKT_COUNT],
|
||||
ofp_event.EventOFPGroupDescStatsReply:
|
||||
[STATE_GROUP_EXIST_CHK]
|
||||
}
|
||||
if ofp.OFP_VERSION >= ofproto_v1_2.OFP_VERSION:
|
||||
event_states[ofp_event.EventOFPGroupDescStatsReply] = [
|
||||
STATE_GROUP_EXIST_CHK
|
||||
]
|
||||
if ofp.OFP_VERSION >= ofproto_v1_3.OFP_VERSION:
|
||||
event_states[ofp_event.EventOFPMeterConfigStatsReply] = [
|
||||
STATE_METER_EXIST_CHK
|
||||
]
|
||||
if self.state in event_states[ev.__class__]:
|
||||
if self.waiter and ev.msg.xid in self.send_msg_xids:
|
||||
self.rcv_msgs.append(ev.msg)
|
||||
if not ev.msg.flags & \
|
||||
ev.msg.datapath.ofproto.OFPMPF_REPLY_MORE:
|
||||
if not ev.msg.flags:
|
||||
self.waiter.set()
|
||||
hub.sleep(0)
|
||||
|
||||
@ -1165,38 +1169,48 @@ class OpenFlowSw(object):
|
||||
""" Add flow. """
|
||||
ofp = self.dp.ofproto
|
||||
parser = self.dp.ofproto_parser
|
||||
|
||||
match = parser.OFPMatch(in_port=in_port)
|
||||
max_len = (0 if out_port != ofp.OFPP_CONTROLLER
|
||||
else ofp.OFPCML_MAX)
|
||||
actions = [parser.OFPActionOutput(out_port, max_len)]
|
||||
inst = [parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
|
||||
actions)]
|
||||
mod = parser.OFPFlowMod(self.dp, cookie=0,
|
||||
command=ofp.OFPFC_ADD,
|
||||
match=match, instructions=inst)
|
||||
actions = [parser.OFPActionOutput(out_port)]
|
||||
if ofp.OFP_VERSION == ofproto_v1_0.OFP_VERSION:
|
||||
mod = parser.OFPFlowMod(
|
||||
self.dp, match=match, cookie=0, command=ofp.OFPFC_ADD,
|
||||
actions=actions)
|
||||
else:
|
||||
inst = [parser.OFPInstructionActions(
|
||||
ofp.OFPIT_APPLY_ACTIONS, actions)]
|
||||
mod = parser.OFPFlowMod(
|
||||
self.dp, cookie=0, command=ofp.OFPFC_ADD, match=match,
|
||||
instructions=inst)
|
||||
return self.send_msg(mod)
|
||||
|
||||
def del_flows(self, cookie=0):
|
||||
""" Delete all flow except default flow. """
|
||||
"""
|
||||
Delete all flow except default flow by using the cookie value.
|
||||
|
||||
Note: In OpenFlow 1.0, DELETE and DELETE_STRICT commands can
|
||||
not be filtered by the cookie value and this value is ignored.
|
||||
"""
|
||||
ofp = self.dp.ofproto
|
||||
parser = self.dp.ofproto_parser
|
||||
cookie_mask = 0
|
||||
if cookie:
|
||||
cookie_mask = 0xffffffffffffffff
|
||||
mod = parser.OFPFlowMod(self.dp,
|
||||
cookie=cookie,
|
||||
cookie_mask=cookie_mask,
|
||||
table_id=ofp.OFPTT_ALL,
|
||||
command=ofp.OFPFC_DELETE,
|
||||
out_port=ofp.OFPP_ANY,
|
||||
out_group=ofp.OFPG_ANY)
|
||||
if ofp.OFP_VERSION == ofproto_v1_0.OFP_VERSION:
|
||||
match = parser.OFPMatch()
|
||||
mod = parser.OFPFlowMod(self.dp, match, cookie, ofp.OFPFC_DELETE)
|
||||
else:
|
||||
mod = parser.OFPFlowMod(
|
||||
self.dp, cookie=cookie, cookie_mask=cookie_mask,
|
||||
table_id=ofp.OFPTT_ALL, command=ofp.OFPFC_DELETE,
|
||||
out_port=ofp.OFPP_ANY, out_group=ofp.OFPG_ANY)
|
||||
return self.send_msg(mod)
|
||||
|
||||
def del_meters(self):
|
||||
""" Delete all meter entries. """
|
||||
ofp = self.dp.ofproto
|
||||
parser = self.dp.ofproto_parser
|
||||
if ofp.OFP_VERSION < ofproto_v1_3.OFP_VERSION:
|
||||
return None
|
||||
mod = parser.OFPMeterMod(self.dp,
|
||||
command=ofp.OFPMC_DELETE,
|
||||
flags=0,
|
||||
@ -1204,8 +1218,11 @@ class OpenFlowSw(object):
|
||||
return self.send_msg(mod)
|
||||
|
||||
def del_groups(self):
|
||||
""" Delete all group entries. """
|
||||
ofp = self.dp.ofproto
|
||||
parser = self.dp.ofproto_parser
|
||||
if ofp.OFP_VERSION < ofproto_v1_2.OFP_VERSION:
|
||||
return None
|
||||
mod = parser.OFPGroupMod(self.dp,
|
||||
command=ofp.OFPGC_DELETE,
|
||||
type_=0,
|
||||
@ -1223,26 +1240,41 @@ class OpenFlowSw(object):
|
||||
ofp = self.dp.ofproto
|
||||
parser = self.dp.ofproto_parser
|
||||
flags = 0
|
||||
req = parser.OFPPortStatsRequest(self.dp, flags, ofp.OFPP_ANY)
|
||||
if ofp.OFP_VERSION == ofproto_v1_0.OFP_VERSION:
|
||||
port = ofp.OFPP_NONE
|
||||
else:
|
||||
port = ofp.OFPP_ANY
|
||||
req = parser.OFPPortStatsRequest(self.dp, flags, port)
|
||||
return self.send_msg(req)
|
||||
|
||||
def send_flow_stats(self):
|
||||
""" Get all flow. """
|
||||
ofp = self.dp.ofproto
|
||||
parser = self.dp.ofproto_parser
|
||||
req = parser.OFPFlowStatsRequest(self.dp, 0, ofp.OFPTT_ALL,
|
||||
ofp.OFPP_ANY, ofp.OFPG_ANY,
|
||||
0, 0, parser.OFPMatch())
|
||||
if ofp.OFP_VERSION == ofproto_v1_0.OFP_VERSION:
|
||||
req = parser.OFPFlowStatsRequest(
|
||||
self.dp, 0, parser.OFPMatch(), 0xff, ofp.OFPP_NONE)
|
||||
else:
|
||||
req = parser.OFPFlowStatsRequest(
|
||||
self.dp, 0, ofp.OFPTT_ALL, ofp.OFPP_ANY, ofp.OFPG_ANY,
|
||||
0, 0, parser.OFPMatch())
|
||||
return self.send_msg(req)
|
||||
|
||||
def send_meter_config_stats(self):
|
||||
""" Get all meter. """
|
||||
ofp = self.dp.ofproto
|
||||
parser = self.dp.ofproto_parser
|
||||
if ofp.OFP_VERSION < ofproto_v1_3.OFP_VERSION:
|
||||
return None
|
||||
stats = parser.OFPMeterConfigStatsRequest(self.dp)
|
||||
return self.send_msg(stats)
|
||||
|
||||
def send_group_desc_stats(self):
|
||||
""" Get all group. """
|
||||
ofp = self.dp.ofproto
|
||||
parser = self.dp.ofproto_parser
|
||||
if ofp.OFP_VERSION < ofproto_v1_2.OFP_VERSION:
|
||||
return None
|
||||
stats = parser.OFPGroupDescStatsRequest(self.dp)
|
||||
return self.send_msg(stats)
|
||||
|
||||
@ -1350,36 +1382,9 @@ class Test(stringify.StringifyMixin):
|
||||
data.serialize()
|
||||
return six.binary_type(data.data)
|
||||
|
||||
def __normalize_match(ofproto, match):
|
||||
match_json = match.to_jsondict()
|
||||
oxm_fields = match_json['OFPMatch']['oxm_fields']
|
||||
fields = []
|
||||
for field in oxm_fields:
|
||||
field_obj = ofproto.oxm_from_jsondict(field)
|
||||
field_obj = ofproto.oxm_normalize_user(*field_obj)
|
||||
fields.append(field_obj)
|
||||
return match.__class__(_ordered_fields=fields)
|
||||
|
||||
def __normalize_action(ofproto, action):
|
||||
action_json = action.to_jsondict()
|
||||
field = action_json['OFPActionSetField']['field']
|
||||
field_obj = ofproto.oxm_from_jsondict(field)
|
||||
field_obj = ofproto.oxm_normalize_user(*field_obj)
|
||||
kwargs = {}
|
||||
kwargs[field_obj[0]] = field_obj[1]
|
||||
return action.__class__(**kwargs)
|
||||
|
||||
# get ofproto modules using user-specified versions
|
||||
(target_ofproto, target_parser) = ofproto_protocol._versions[
|
||||
OfTester.target_ver]
|
||||
(tester_ofproto, tester_parser) = ofproto_protocol._versions[
|
||||
OfTester.tester_ver]
|
||||
target_dp = DummyDatapath()
|
||||
target_dp.ofproto = target_ofproto
|
||||
target_dp.ofproto_parser = target_parser
|
||||
tester_dp = DummyDatapath()
|
||||
tester_dp.ofproto = tester_ofproto
|
||||
tester_dp.ofproto_parser = tester_parser
|
||||
# create Datapath instance using user-specified versions
|
||||
target_dp = DummyDatapath(OfTester.target_ver)
|
||||
tester_dp = DummyDatapath(OfTester.tester_ver)
|
||||
|
||||
# parse 'description'
|
||||
description = buf.get(KEY_DESC)
|
||||
@ -1388,51 +1393,9 @@ class Test(stringify.StringifyMixin):
|
||||
prerequisite = []
|
||||
if KEY_PREREQ not in buf:
|
||||
raise ValueError('a test requires a "%s" block' % KEY_PREREQ)
|
||||
allowed_mod = [KEY_FLOW, KEY_METER, KEY_GROUP]
|
||||
for flow in buf[KEY_PREREQ]:
|
||||
key, value = flow.popitem()
|
||||
if key not in allowed_mod:
|
||||
raise ValueError(
|
||||
'"%s" block allows only the followings: %s' % (
|
||||
KEY_PREREQ, allowed_mod))
|
||||
cls = getattr(target_parser, key)
|
||||
msg = cls.from_jsondict(value, datapath=target_dp)
|
||||
msg.version = target_ofproto.OFP_VERSION
|
||||
msg.msg_type = msg.cls_msg_type
|
||||
msg.xid = 0
|
||||
if isinstance(msg, target_parser.OFPFlowMod):
|
||||
# normalize OFPMatch
|
||||
msg.match = __normalize_match(target_ofproto, msg.match)
|
||||
# normalize OFPActionSetField
|
||||
insts = []
|
||||
for inst in msg.instructions:
|
||||
if isinstance(inst, target_parser.OFPInstructionActions):
|
||||
acts = []
|
||||
for act in inst.actions:
|
||||
if isinstance(
|
||||
act, target_parser.OFPActionSetField):
|
||||
act = __normalize_action(target_ofproto, act)
|
||||
acts.append(act)
|
||||
inst = target_parser.OFPInstructionActions(
|
||||
inst.type, actions=acts)
|
||||
insts.append(inst)
|
||||
msg.instructions = insts
|
||||
elif isinstance(msg, target_parser.OFPGroupMod):
|
||||
# normalize OFPActionSetField
|
||||
buckets = []
|
||||
for bucket in msg.buckets:
|
||||
acts = []
|
||||
for act in bucket.actions:
|
||||
if isinstance(act, target_parser.OFPActionSetField):
|
||||
act = __normalize_action(target_ofproto, act)
|
||||
acts.append(act)
|
||||
bucket = target_parser.OFPBucket(
|
||||
weight=bucket.weight,
|
||||
watch_port=bucket.watch_port,
|
||||
watch_group=bucket.watch_group,
|
||||
actions=acts)
|
||||
buckets.append(bucket)
|
||||
msg.buckets = buckets
|
||||
msg = ofproto_parser.ofp_msg_from_jsondict(
|
||||
target_dp, flow)
|
||||
msg.serialize()
|
||||
prerequisite.append(msg)
|
||||
|
||||
@ -1476,14 +1439,17 @@ class Test(stringify.StringifyMixin):
|
||||
throughputs = []
|
||||
for throughput in test[KEY_EGRESS][KEY_THROUGHPUT]:
|
||||
one = {}
|
||||
mod = {'match': {'OFPMatch': throughput[KEY_MATCH]}}
|
||||
cls = getattr(tester_parser, KEY_FLOW)
|
||||
msg = cls.from_jsondict(
|
||||
mod, datapath=tester_dp,
|
||||
cookie=THROUGHPUT_COOKIE,
|
||||
priority=THROUGHPUT_PRIORITY)
|
||||
msg.match = __normalize_match(
|
||||
tester_ofproto, msg.match)
|
||||
mod = {
|
||||
"OFPFlowMod": {
|
||||
'cookie': THROUGHPUT_COOKIE,
|
||||
'priority': THROUGHPUT_PRIORITY,
|
||||
'match': {
|
||||
'OFPMatch': throughput[KEY_MATCH]
|
||||
}
|
||||
}
|
||||
}
|
||||
msg = ofproto_parser.ofp_msg_from_jsondict(
|
||||
tester_dp, mod)
|
||||
one[KEY_FLOW] = msg
|
||||
one[KEY_KBPS] = throughput.get(KEY_KBPS)
|
||||
one[KEY_PKTPS] = throughput.get(KEY_PKTPS)
|
||||
@ -1505,10 +1471,9 @@ class Test(stringify.StringifyMixin):
|
||||
return (description, prerequisite, tests)
|
||||
|
||||
|
||||
class DummyDatapath(object):
|
||||
def __init__(self):
|
||||
self.ofproto = ofproto_v1_3
|
||||
self.ofproto_parser = ofproto_v1_3_parser
|
||||
class DummyDatapath(ofproto_protocol.ProtocolDesc):
|
||||
def __init__(self, version=None):
|
||||
super(DummyDatapath, self).__init__(version)
|
||||
|
||||
def set_xid(self, _):
|
||||
pass
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user