1 # Copyright (C) 2012 Nippon Telegraph and Telephone Corporation.
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
16 # vim: tabstop=4 shiftwidth=4 softtabstop=4
21 from ryu.controller import ofp_event
22 from ryu.controller.handler import MAIN_DISPATCHER
23 from ryu.controller.handler import set_ev_cls
24 from ryu.ofproto import ofproto_v1_2
25 from ryu.tests.integrated import tester
27 LOG = logging.getLogger(__name__)
30 class RunTest(tester.TestFlowBase):
31 """ Test case for Request-Reply messages.
33 Some tests need attached port to switch.
34 If use the OVS, can do it with the following commands.
35 # ip link add <port> type dummy
36 # ovs-vsctl add-port <bridge> <port>
39 OFP_VERSIONS = [ofproto_v1_2.OFP_VERSION]
41 def __init__(self, *args, **kwargs):
42 super(RunTest, self).__init__(*args, **kwargs)
45 self.n_tables = ofproto_v1_2.OFPTT_MAX
47 def start_next_test(self, dp):
49 self.delete_all_flows(dp)
52 t = self.pending.pop()
53 if self.is_supported(t):
54 LOG.info(tester.LOG_TEST_START, t)
58 self.results[t] = 'SKIP (unsupported)'
60 self.start_next_test(dp)
64 def run_verify(self, ev):
68 verify_func = self.verify_default
69 v = "verify" + self.current[4:]
71 verify_func = getattr(self, v)
73 result = verify_func(dp, msg)
77 self.results[self.current] = result
78 self.start_next_test(dp)
80 def verify_default(self, dp, msg):
83 if msg.msg_type == dp.ofproto.OFPT_STATS_REPLY:
84 return self.verify_stats(dp, msg.body, type_)
85 elif msg.msg_type == type_:
88 return 'Reply msg_type %s expected %s' \
89 % (msg.msg_type, type_)
91 def verify_stats(self, dp, stats, type_):
92 stats_types = dp.ofproto_parser.OFPStatsReply._STATS_TYPES
93 expect = stats_types.get(type_).__name__
95 if isinstance(stats, list):
97 if expect == s.__class__.__name__:
100 if expect == stats.__class__.__name__:
102 return 'Reply msg has not \'%s\' class.\n%s' % (expect, stats)
104 def mod_flow(self, dp, cookie=0, cookie_mask=0, table_id=0,
105 command=None, idle_timeout=0, hard_timeout=0,
106 priority=0xff, buffer_id=0xffffffff, match=None,
107 actions=None, inst_type=None, out_port=None,
108 out_group=None, flags=0, inst=None):
111 command = dp.ofproto.OFPFC_ADD
114 if inst_type is None:
115 inst_type = dp.ofproto.OFPIT_APPLY_ACTIONS
118 if actions is not None:
119 inst = [dp.ofproto_parser.OFPInstructionActions(
123 match = dp.ofproto_parser.OFPMatch()
126 out_port = dp.ofproto.OFPP_ANY
128 if out_group is None:
129 out_group = dp.ofproto.OFPG_ANY
131 m = dp.ofproto_parser.OFPFlowMod(dp, cookie, cookie_mask,
133 idle_timeout, hard_timeout,
140 def get_port(self, dp):
141 for port_no, port in dp.ports.items():
142 if port_no != dp.ofproto.OFPP_LOCAL:
146 # Test for Reply message type
147 def test_desc_stats_request(self, dp):
148 self._verify = dp.ofproto.OFPST_DESC
149 m = dp.ofproto_parser.OFPDescStatsRequest(dp)
152 def test_flow_stats_request(self, dp):
153 self._verify = dp.ofproto.OFPST_FLOW
155 self.send_flow_stats(dp)
157 def test_aggregate_stats_request(self, dp):
158 self._verify = dp.ofproto.OFPST_AGGREGATE
159 match = dp.ofproto_parser.OFPMatch()
160 m = dp.ofproto_parser.OFPAggregateStatsRequest(
161 dp, dp.ofproto.OFPTT_ALL, dp.ofproto.OFPP_ANY,
162 dp.ofproto.OFPG_ANY, 0, 0, match)
165 def test_table_stats_request(self, dp):
166 self._verify = dp.ofproto.OFPST_TABLE
167 m = dp.ofproto_parser.OFPTableStatsRequest(dp)
170 def test_port_stats_request(self, dp):
171 self._verify = dp.ofproto.OFPST_PORT
172 m = dp.ofproto_parser.OFPPortStatsRequest(dp, dp.ofproto.OFPP_ANY)
175 def test_echo_request(self, dp):
176 self._verify = dp.ofproto.OFPT_ECHO_REPLY
177 m = dp.ofproto_parser.OFPEchoRequest(dp)
180 def test_features_request(self, dp):
181 self._verify = dp.ofproto.OFPT_FEATURES_REPLY
182 m = dp.ofproto_parser.OFPFeaturesRequest(dp)
185 def test_get_config_request(self, dp):
186 self._verify = dp.ofproto.OFPT_GET_CONFIG_REPLY
187 m = dp.ofproto_parser.OFPGetConfigRequest(dp)
190 def test_barrier_request(self, dp):
191 self._verify = dp.ofproto.OFPT_BARRIER_REPLY
194 def test_error_reply(self, dp):
197 if p != dp.ofproto.OFPP_LOCAL:
200 port_no = max(ports) + 1
201 self._verify = dp.ofproto.OFPT_ERROR
202 m = dp.ofproto_parser.OFPPortMod(
203 dp, port_no, 'ff:ff:ff:ff:ff:ff', 0, 0, 0)
206 # Test for reply value
207 def test_flow_stats_none(self, dp):
208 self.send_flow_stats(dp)
210 def verify_flow_stats_none(self, dp, msg):
213 return 'Reply msg has body. %s' % (stats, )
216 def test_flow_stats_reply_value(self, dp):
219 while c < self.n_tables:
220 # value = (talbe_id, cookie, idle_timeout, hard_timeout, priority)
221 v = (c, c + 1, c + 2, c + 3, c + 4)
222 self._verify.append(v)
223 self.mod_flow(dp, table_id=v[0], cookie=v[1],
224 idle_timeout=v[2], hard_timeout=v[3], priority=v[4])
227 self.send_flow_stats(dp)
229 def verify_flow_stats_reply_value(self, dp, msg):
232 f_value = (f.table_id, f.cookie, f.idle_timeout,
233 f.hard_timeout, f.priority, )
234 if f_value != self._verify[c]:
235 return 'param is mismatched. verify=%s, reply=%s' \
236 % (self._verify[c], f_value,)
238 return len(msg.body) == self.n_tables
240 def test_echo_request_has_data(self, dp):
243 m = dp.ofproto_parser.OFPEchoRequest(dp)
247 def verify_echo_request_has_data(self, dp, msg):
249 return self._verify == data
251 def test_aggregate_stats_flow_count(self, dp):
253 while c < self.n_tables:
254 self.mod_flow(dp, table_id=c)
257 match = dp.ofproto_parser.OFPMatch()
258 m = dp.ofproto_parser.OFPAggregateStatsRequest(
259 dp, dp.ofproto.OFPTT_ALL, dp.ofproto.OFPP_ANY,
260 dp.ofproto.OFPG_ANY, 0, 0, match)
263 def verify_aggregate_stats_flow_count(self, dp, msg):
265 return stats.flow_count == self.n_tables
267 def test_aggregate_stats_flow_count_out_port(self, dp):
268 actions = [dp.ofproto_parser.OFPActionOutput(1, 1500)]
269 self.mod_flow(dp, table_id=1, actions=actions)
271 actions = [dp.ofproto_parser.OFPActionOutput(2, 1500)]
272 self.mod_flow(dp, table_id=2, actions=actions)
276 match = dp.ofproto_parser.OFPMatch()
277 m = dp.ofproto_parser.OFPAggregateStatsRequest(
278 dp, dp.ofproto.OFPTT_ALL, out_port,
279 dp.ofproto.OFPG_ANY, 0, 0, match)
282 def verify_aggregate_stats_flow_count_out_port(self, dp, msg):
284 return stats.flow_count == 1
286 def test_aggregate_stats_packet_count(self, dp):
289 self._verify = {'packet_count': 1,
290 'byte_count': len(data)}
293 match = dp.ofproto_parser.OFPMatch()
294 match.set_in_port(in_port)
295 self.mod_flow(dp, table_id=0, match=match)
298 output = dp.ofproto.OFPP_TABLE
299 actions = [dp.ofproto_parser.OFPActionOutput(output, 0)]
300 m = dp.ofproto_parser.OFPPacketOut(dp, 0xffffffff, in_port,
305 match = dp.ofproto_parser.OFPMatch()
306 m = dp.ofproto_parser.OFPAggregateStatsRequest(
307 dp, dp.ofproto.OFPTT_ALL, dp.ofproto.OFPP_ANY,
308 dp.ofproto.OFPG_ANY, 0, 0, match)
311 def verify_aggregate_stats_packet_count(self, dp, msg):
312 for name, val in self._verify.items():
313 r_val = getattr(msg.body, name)
315 return '%s is mismatched. verify=%s, reply=%s' \
319 def test_set_config_nomal(self, dp):
320 flags = dp.ofproto.OFPC_FRAG_NORMAL
322 m = dp.ofproto_parser.OFPSetConfig(dp, flags, 0)
326 m = dp.ofproto_parser.OFPGetConfigRequest(dp)
329 def verify_set_config_nomal(self, dp, msg):
330 return self._verify == msg.flags
332 def test_set_config_drop(self, dp):
333 flags = dp.ofproto.OFPC_FRAG_DROP
335 m = dp.ofproto_parser.OFPSetConfig(dp, flags, 0)
339 m = dp.ofproto_parser.OFPGetConfigRequest(dp)
342 def verify_set_config_drop(self, dp, msg):
343 return self._verify == msg.flags
345 def test_set_config_mask(self, dp):
346 flags = dp.ofproto.OFPC_FRAG_MASK
348 m = dp.ofproto_parser.OFPSetConfig(dp, flags, 0)
352 m = dp.ofproto_parser.OFPGetConfigRequest(dp)
355 def verify_set_config_mask(self, dp, msg):
356 return self._verify == msg.flags
358 def test_set_config_ttl_to_controller(self, dp):
359 flags = dp.ofproto.OFPC_INVALID_TTL_TO_CONTROLLER
361 m = dp.ofproto_parser.OFPSetConfig(dp, flags, 0)
365 m = dp.ofproto_parser.OFPGetConfigRequest(dp)
368 def verify_set_config_ttl_to_controller(self, dp, msg):
369 return self._verify == msg.flags
371 def test_set_config_miss_send_len(self, dp):
372 flags = dp.ofproto.OFPC_FRAG_NORMAL
374 self._verify = ms_len
375 m = dp.ofproto_parser.OFPSetConfig(dp, flags, ms_len)
379 m = dp.ofproto_parser.OFPGetConfigRequest(dp)
382 def verify_set_config_miss_send_len(self, dp, msg):
383 return self._verify == msg.miss_send_len
385 def test_set_config_miss_send_len_max(self, dp):
386 flags = dp.ofproto.OFPC_FRAG_NORMAL
387 ms_len = dp.ofproto.OFPCML_MAX
388 self._verify = ms_len
389 m = dp.ofproto_parser.OFPSetConfig(dp, flags, ms_len)
393 m = dp.ofproto_parser.OFPGetConfigRequest(dp)
396 def verify_set_config_miss_send_len_max(self, dp, msg):
397 return self._verify == msg.miss_send_len
399 def test_set_config_no_buffer(self, dp):
400 flags = dp.ofproto.OFPC_FRAG_NORMAL
401 ms_len = dp.ofproto.OFPCML_NO_BUFFER
402 self._verify = ms_len
403 m = dp.ofproto_parser.OFPSetConfig(dp, flags, ms_len)
407 m = dp.ofproto_parser.OFPGetConfigRequest(dp)
410 def verify_set_config_no_buffer(self, dp, msg):
411 return self._verify == msg.miss_send_len
413 def _verify_flow_inst_type(self, dp, msg):
414 inst_type = self._verify
418 for i in s.instructions:
419 if i.type == inst_type:
421 return 'not found inst_type[%s]' % (inst_type, )
423 def test_flow_add_apply_actions(self, dp):
424 inst_type = dp.ofproto.OFPIT_APPLY_ACTIONS
425 self._verify = inst_type
427 actions = [dp.ofproto_parser.OFPActionOutput(1, 1500)]
428 self.mod_flow(dp, actions=actions, inst_type=inst_type)
429 self.send_flow_stats(dp)
431 def verify_flow_add_apply_actions(self, dp, msg):
432 return self._verify_flow_inst_type(dp, msg)
434 def test_flow_add_goto_table(self, dp):
435 self._verify = dp.ofproto.OFPIT_GOTO_TABLE
437 inst = [dp.ofproto_parser.OFPInstructionGotoTable(1), ]
438 self.mod_flow(dp, inst=inst)
439 self.send_flow_stats(dp)
441 def verify_flow_add_goto_table(self, dp, msg):
442 return self._verify_flow_inst_type(dp, msg)
444 def _verify_flow_value(self, dp, msg):
446 verify = self._verify
448 if len(verify) != len(stats):
449 return 'flow_count is mismatched. verify=%s stats=%s' \
450 % (len(verify), len(stats))
454 v = verify.get(s.table_id, None)
458 s_port = s.instructions[0].actions[0].port
461 return 'port is mismatched. table_id=%s verify=%s, stats=%s' \
462 % (s.table_id, v_port, s_port)
465 def _add_flow_for_flow_mod_tests(self, dp):
466 a1 = dp.ofproto_parser.OFPActionOutput(1, 1500)
467 a2 = dp.ofproto_parser.OFPActionOutput(2, 1500)
469 # table_id, cookie, priority, dl_dst, action)
470 tables = {0: [0xffff, 10, b'\xee' * 6, a1],
471 1: [0xff00, 10, b'\xee' * 6, a2],
472 2: [0xf000, 100, b'\xee' * 6, a1],
473 3: [0x0000, 10, b'\xff' * 6, a1]}
475 self._verify = tables
476 for table_id, val in tables.items():
477 match = dp.ofproto_parser.OFPMatch()
478 match.set_dl_dst(val[2])
479 self.mod_flow(dp, match=match, actions=[val[3]],
480 table_id=table_id, cookie=val[0], priority=val[1])
483 def test_flow_mod_table_id(self, dp):
484 self._add_flow_for_flow_mod_tests(dp)
486 # modify flow of table_id=3
487 action = dp.ofproto_parser.OFPActionOutput(3, 1500)
488 self._verify[3][3] = action
491 self.mod_flow(dp, command=dp.ofproto.OFPFC_MODIFY,
492 actions=[action], table_id=table_id)
495 self.send_flow_stats(dp)
497 def verify_flow_mod_table_id(self, dp, msg):
498 return self._verify_flow_value(dp, msg)
500 def test_flow_mod_cookie(self, dp):
501 self._add_flow_for_flow_mod_tests(dp)
503 # modify flow of table_id=1
504 action = dp.ofproto_parser.OFPActionOutput(3, 1500)
505 self._verify[1][3] = action
510 self.mod_flow(dp, command=dp.ofproto.OFPFC_MODIFY,
511 actions=[action], table_id=table_id,
512 cookie=cookie, cookie_mask=cookie_mask)
515 self.send_flow_stats(dp)
517 def verify_flow_mod_cookie(self, dp, msg):
518 return self._verify_flow_value(dp, msg)
520 def test_flow_mod_cookie_mask(self, dp):
521 self._add_flow_for_flow_mod_tests(dp)
523 # modify flow of table_id=0,1
524 action = dp.ofproto_parser.OFPActionOutput(3, 1500)
525 self._verify[0][3] = action
526 self._verify[1][3] = action
530 for table_id in range(2):
531 self.mod_flow(dp, command=dp.ofproto.OFPFC_MODIFY,
532 actions=[action], table_id=table_id,
533 cookie=cookie, cookie_mask=cookie_mask)
536 self.send_flow_stats(dp)
538 def verify_flow_mod_cookie_mask(self, dp, msg):
539 return self._verify_flow_value(dp, msg)
541 def test_flow_mod_match(self, dp):
542 self._add_flow_for_flow_mod_tests(dp)
544 # modify flow of table_id=3
545 action = dp.ofproto_parser.OFPActionOutput(3, 1500)
546 self._verify[3][3] = action
548 match = dp.ofproto_parser.OFPMatch()
549 match.set_dl_dst(b'\xff' * 6)
551 self.mod_flow(dp, command=dp.ofproto.OFPFC_MODIFY,
552 actions=[action], table_id=table_id, match=match)
555 self.send_flow_stats(dp)
557 def verify_flow_mod_match(self, dp, msg):
558 return self._verify_flow_value(dp, msg)
560 def test_flow_mod_strict(self, dp):
561 self._add_flow_for_flow_mod_tests(dp)
563 # modify flow of table_id=2
564 action = dp.ofproto_parser.OFPActionOutput(3, 1500)
565 self._verify[2][3] = action
567 match = dp.ofproto_parser.OFPMatch()
568 match.set_dl_dst(b'\xee' * 6)
571 self.mod_flow(dp, command=dp.ofproto.OFPFC_MODIFY_STRICT,
572 actions=[action], table_id=table_id,
573 match=match, priority=priority)
576 self.send_flow_stats(dp)
578 def verify_flow_mod_strict(self, dp, msg):
579 return self._verify_flow_value(dp, msg)
581 def test_flow_del_table_id(self, dp):
582 self._add_flow_for_flow_mod_tests(dp)
584 # delete flow of table_id=3
588 self.mod_flow(dp, command=dp.ofproto.OFPFC_DELETE,
592 self.send_flow_stats(dp)
594 def verify_flow_del_table_id(self, dp, msg):
595 return self._verify_flow_value(dp, msg)
597 def test_flow_del_table_id_all(self, dp):
598 self._add_flow_for_flow_mod_tests(dp)
603 self.mod_flow(dp, command=dp.ofproto.OFPFC_DELETE,
604 table_id=dp.ofproto.OFPTT_ALL)
607 self.send_flow_stats(dp)
609 def verify_flow_del_table_id_all(self, dp, msg):
610 return self._verify_flow_value(dp, msg)
612 def test_flow_del_cookie(self, dp):
613 self._add_flow_for_flow_mod_tests(dp)
615 # delete flow of table_id=1
620 self.mod_flow(dp, command=dp.ofproto.OFPFC_DELETE,
621 table_id=dp.ofproto.OFPTT_ALL,
622 cookie=cookie, cookie_mask=cookie_mask)
625 self.send_flow_stats(dp)
627 def verify_flow_del_cookie(self, dp, msg):
628 return self._verify_flow_value(dp, msg)
630 def test_flow_del_cookie_mask(self, dp):
631 self._add_flow_for_flow_mod_tests(dp)
633 # delete flow of table_id=0,1
639 self.mod_flow(dp, command=dp.ofproto.OFPFC_DELETE,
640 table_id=dp.ofproto.OFPTT_ALL,
641 cookie=cookie, cookie_mask=cookie_mask)
644 self.send_flow_stats(dp)
646 def verify_flow_del_cookie_mask(self, dp, msg):
647 return self._verify_flow_value(dp, msg)
649 def test_flow_del_match(self, dp):
650 self._add_flow_for_flow_mod_tests(dp)
652 # delete flow of table_id=3
655 match = dp.ofproto_parser.OFPMatch()
656 match.set_dl_dst(b'\xff' * 6)
657 self.mod_flow(dp, command=dp.ofproto.OFPFC_DELETE,
658 table_id=dp.ofproto.OFPTT_ALL, match=match)
661 self.send_flow_stats(dp)
663 def verify_flow_del_match(self, dp, msg):
664 return self._verify_flow_value(dp, msg)
666 def test_flow_del_out_port(self, dp):
667 self._add_flow_for_flow_mod_tests(dp)
669 # delete flow of table_id=1
673 self.mod_flow(dp, command=dp.ofproto.OFPFC_DELETE,
674 table_id=dp.ofproto.OFPTT_ALL, out_port=out_port)
677 self.send_flow_stats(dp)
679 def verify_flow_del_out_port(self, dp, msg):
680 return self._verify_flow_value(dp, msg)
682 def test_flow_del_strict(self, dp):
683 self._add_flow_for_flow_mod_tests(dp)
685 # delete flow of table_id=2
688 match = dp.ofproto_parser.OFPMatch()
689 match.set_dl_dst(b'\xee' * 6)
691 self.mod_flow(dp, command=dp.ofproto.OFPFC_DELETE_STRICT,
692 table_id=dp.ofproto.OFPTT_ALL,
693 match=match, priority=priority)
696 self.send_flow_stats(dp)
698 def verify_flow_del_strict(self, dp, msg):
699 return self._verify_flow_value(dp, msg)
701 def _send_port_mod(self, dp, config, mask):
702 p = self.get_port(dp)
704 err = 'need attached port to switch.'
705 self.results[self.current] = err
706 self.start_next_test(dp)
709 self._verify = [p.port_no, config & mask]
710 m = dp.ofproto_parser.OFPPortMod(dp, p.port_no, p.hw_addr,
715 # TODO: waiting to port UP|DOWN.
717 m = dp.ofproto_parser.OFPFeaturesRequest(dp)
720 def _verify_port_mod_config(self, dp, msg):
721 port_no = self._verify[0]
722 config = self._verify[1]
724 port = msg.ports[port_no]
725 if config != port.config:
726 return "config is mismatched. verify=%s, stats=%s" \
727 % (bin(config), bin(port.config))
730 def test_port_mod_config_01_all(self, dp):
733 self._send_port_mod(dp, config, mask)
735 def verify_port_mod_config_01_all(self, dp, msg):
736 return self._verify_port_mod_config(dp, msg)
738 def test_port_mod_config_02_none(self, dp):
741 self._send_port_mod(dp, config, mask)
743 def verify_port_mod_config_02_none(self, dp, msg):
744 return self._verify_port_mod_config(dp, msg)
746 def test_port_mod_config_03_mask(self, dp):
749 self._send_port_mod(dp, config, mask)
751 def verify_port_mod_config_03_mask(self, dp, msg):
752 res = self._verify_port_mod_config(dp, msg)
754 port_no = self._verify[0]
755 p = msg.ports[port_no]
756 m = dp.ofproto_parser.OFPPortMod(dp, p.port_no, p.hw_addr,
762 def test_port_stats_port_no(self, dp):
763 p = self.get_port(dp)
765 err = 'need attached port to switch.'
766 self.results[self.current] = err
767 self.start_next_test(dp)
770 self._verify = p.port_no
771 m = dp.ofproto_parser.OFPPortStatsRequest(dp, p.port_no)
774 def verify_port_stats_port_no(self, dp, msg):
777 return 'reply some ports.\n%s' % (ports)
779 if ports[0].port_no != self._verify:
780 return 'port_no is mismatched. request=%s reply=%s' \
781 % (self._verify, ports[0].port_no)
785 def _add_flow_flow_removed(self, dp, reason, table_id=0,
786 cookie=0xff, priority=100, in_port=1,
787 idle_timeout=0, hard_timeout=0):
789 self._verify['params'] = {'reason': reason,
790 'table_id': table_id,
792 'priority': priority}
793 self._verify['in_port'] = in_port
794 self._verify['timeout'] = idle_timeout
796 if (idle_timeout == 0 or idle_timeout > hard_timeout):
797 self._verify['timeout'] = hard_timeout
799 match = dp.ofproto_parser.OFPMatch()
800 match.set_in_port(in_port)
801 self.mod_flow(dp, match=match, cookie=cookie,
802 priority=priority, table_id=table_id,
803 idle_timeout=idle_timeout, hard_timeout=hard_timeout,
804 flags=dp.ofproto.OFPFF_SEND_FLOW_REM)
806 def _verify_flow_removed(self, dp, msg):
807 params = self._verify['params']
808 in_port = self._verify['in_port']
809 timeout = self._verify['timeout']
812 duration_nsec = (msg.duration_sec * 10 ** 9) + msg.duration_nsec
813 timeout_nsec = timeout * 10 ** 9
815 # grace of -0.5 and +1.5 second to timeout.
816 l = (timeout - 0.5) * 10 ** 9
817 h = (timeout + 1.5) * 10 ** 9
818 if not l < duration_nsec < h:
819 return 'bad duration time. set=%s(nsec), duration=%s(nsec)' \
820 % (timeout_nsec, duration_nsec)
822 for name, val in params.items():
823 r_val = getattr(msg, name)
825 return '%s is mismatched. verify=%s, reply=%s' \
828 for f in msg.match.fields:
829 if f.header == ofproto_v1_2.OXM_OF_IN_PORT:
830 if f.value != in_port:
831 return 'in_port is mismatched. verify=%s, reply=%s' \
835 def test_flow_removed_idle_timeout(self, dp):
836 reason = dp.ofproto.OFPRR_IDLE_TIMEOUT
838 self._add_flow_flow_removed(dp, reason,
839 idle_timeout=idle_timeout)
841 def verify_flow_removed_idle_timeout(self, dp, msg):
842 return self._verify_flow_removed(dp, msg)
844 def test_flow_removed_idle_timeout_hit(self, dp):
845 reason = dp.ofproto.OFPRR_IDLE_TIMEOUT
851 self._add_flow_flow_removed(dp, reason, in_port=in_port,
852 idle_timeout=idle_timeout)
853 self._verify['timeout'] = idle_timeout + sleep
859 output = dp.ofproto.OFPP_TABLE
860 actions = [dp.ofproto_parser.OFPActionOutput(output, 0)]
861 m = dp.ofproto_parser.OFPPacketOut(dp, 0xffffffff, in_port,
865 def verify_flow_removed_idle_timeout_hit(self, dp, msg):
866 return self._verify_flow_removed(dp, msg)
868 def test_flow_removed_hard_timeout(self, dp):
869 reason = dp.ofproto.OFPRR_HARD_TIMEOUT
871 self._add_flow_flow_removed(dp, reason,
872 hard_timeout=hard_timeout)
874 def verify_flow_removed_hard_timeout(self, dp, msg):
875 return self._verify_flow_removed(dp, msg)
877 def test_flow_removed_hard_timeout_hit(self, dp):
878 reason = dp.ofproto.OFPRR_HARD_TIMEOUT
883 self._add_flow_flow_removed(dp, reason, in_port=in_port,
884 hard_timeout=hard_timeout)
891 output = dp.ofproto.OFPP_TABLE
892 actions = [dp.ofproto_parser.OFPActionOutput(output, 0)]
893 m = dp.ofproto_parser.OFPPacketOut(dp, 0xffffffff, in_port,
897 def verify_flow_removed_hard_timeout_hit(self, dp, msg):
898 return self._verify_flow_removed(dp, msg)
900 def test_flow_removed_delete(self, dp):
901 reason = dp.ofproto.OFPRR_DELETE
902 self._add_flow_flow_removed(dp, reason)
904 self.delete_all_flows(dp)
906 def verify_flow_removed_delete(self, dp, msg):
907 return self._verify_flow_removed(dp, msg)
909 def test_flow_removed_table_id(self, dp):
910 reason = dp.ofproto.OFPRR_DELETE
912 self._add_flow_flow_removed(dp, reason, table_id=table_id)
914 self.delete_all_flows(dp)
916 def verify_flow_removed_table_id(self, dp, msg):
917 return self._verify_flow_removed(dp, msg)
919 def _send_packet_out(self, dp, buffer_id=0xffffffff,
920 in_port=None, output=None, data=''):
922 in_port = dp.ofproto.OFPP_LOCAL
925 output = dp.ofproto.OFPP_CONTROLLER
927 self._verify['in_port'] = in_port
928 self._verify['data'] = data
930 actions = [dp.ofproto_parser.OFPActionOutput(output, len(data))]
931 m = dp.ofproto_parser.OFPPacketOut(dp, buffer_id, in_port,
935 def _verify_packet_in(self, dp, msg):
936 for name, val in self._verify.items():
937 if name == 'in_port':
938 for f in msg.match.fields:
939 if f.header == ofproto_v1_2.OXM_OF_IN_PORT:
942 r_val = getattr(msg, name)
945 return '%s is mismatched. verify=%s, reply=%s' \
949 def test_packet_in_action(self, dp):
951 self._verify['reason'] = dp.ofproto.OFPR_ACTION
952 self._send_packet_out(dp)
954 def verify_packet_in_action(self, dp, msg):
955 return self._verify_packet_in(dp, msg)
957 def test_packet_in_data(self, dp):
959 self._verify['reason'] = dp.ofproto.OFPR_ACTION
961 self._send_packet_out(dp, data=data)
963 def verify_packet_in_data(self, dp, msg):
964 return self._verify_packet_in(dp, msg)
966 def test_packet_in_table_id(self, dp):
969 output = dp.ofproto.OFPP_TABLE
972 self._verify['reason'] = dp.ofproto.OFPR_ACTION
973 self._verify['table_id'] = table_id
975 # add flow (goto_table)
976 match = dp.ofproto_parser.OFPMatch()
977 match.set_in_port(in_port)
978 inst = [dp.ofproto_parser.OFPInstructionGotoTable(table_id)]
979 self.mod_flow(dp, inst=inst, match=match)
982 match = dp.ofproto_parser.OFPMatch()
983 match.set_in_port(in_port)
984 out = dp.ofproto.OFPP_CONTROLLER
985 actions = [dp.ofproto_parser.OFPActionOutput(out, 0)]
986 self.mod_flow(dp, actions=actions, match=match, table_id=table_id)
990 self._send_packet_out(dp, in_port=in_port, output=output)
992 def verify_packet_in_table_id(self, dp, msg):
993 return self._verify_packet_in(dp, msg)
996 @set_ev_cls(ofp_event.EventOFPEchoReply, MAIN_DISPATCHER)
997 def echo_replay_handler(self, ev):
998 if self.current.find('echo_request') > 0:
1001 @set_ev_cls(ofp_event.EventOFPStatsReply, MAIN_DISPATCHER)
1002 def stats_reply_handler(self, ev):
1003 if self.current is None:
1006 if self._verify == dp.ofproto.OFPST_TABLE:
1007 self.table_stats = msg.body
1008 self.start_next_test(dp)
1012 @set_ev_cls(ofp_event.EventOFPSwitchFeatures, MAIN_DISPATCHER)
1013 def features_replay_handler(self, ev):
1014 if self.current is None:
1019 @set_ev_cls(ofp_event.EventOFPGetConfigReply, MAIN_DISPATCHER)
1020 def get_config_replay_handler(self, ev):
1023 @set_ev_cls(ofp_event.EventOFPBarrierReply, MAIN_DISPATCHER)
1024 def barrier_replay_handler(self, ev):
1025 if self.current == 'test_barrier_request':
1028 @set_ev_cls(ofp_event.EventOFPPortStatus, MAIN_DISPATCHER)
1029 def port_status_handler(self, ev):
1032 @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
1033 def packet_in_handler(self, ev):
1034 if self.current.find('packet_in'):
1037 @set_ev_cls(ofp_event.EventOFPFlowRemoved, MAIN_DISPATCHER)
1038 def flow_removed_handler(self, ev):
1039 if self.current.find('flow_removed') > 0:
1042 @set_ev_cls(ofp_event.EventOFPErrorMsg, MAIN_DISPATCHER)
1043 def error_handler(self, ev):
1044 if self.current.find('error') > 0:
1047 def is_supported(self, t):
1050 for u in unsupported: