blob: 660aa07c2d400283744b4941e116bca3db8bc3bb [file] [log] [blame]
Dan Talayco5eba8442010-03-10 13:58:43 -08001"""
2Test cases for testing actions taken on packets
3
4See basic.py for other info.
5
6It is recommended that these definitions be kept in their own
7namespace as different groups of tests will likely define
8similar identifiers.
9
10 The function test_set_init is called with a complete configuration
11dictionary prior to the invocation of any tests from this file.
12
13 The switch is actively attempting to contact the controller at the address
14indicated oin oft_config
15
16"""
17
Dan Talayco9f47f4d2010-06-03 13:54:37 -070018import copy
19
Dan Talayco5eba8442010-03-10 13:58:43 -080020import logging
21
22import unittest
23
24import oftest.controller as controller
25import oftest.cstruct as ofp
26import oftest.message as message
27import oftest.dataplane as dataplane
28import oftest.action as action
29import oftest.parse as parse
30import basic
Dan Talayco8a64e332012-03-28 14:53:20 -070031import time
Dan Talayco5eba8442010-03-10 13:58:43 -080032
33from testutils import *
34
35#@var port_map Local copy of the configuration map from OF port
36# numbers to OS interfaces
37pa_port_map = None
38#@var pa_logger Local logger object
39pa_logger = None
40#@var pa_config Local copy of global configuration data
41pa_config = None
42
Dan Talayco551befa2010-07-15 17:05:32 -070043# For test priority
44#@var test_prio Set test priority for local tests
45test_prio = {}
46
47WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
Dan Talayco488fbc52012-04-09 16:30:41 -070048 ofp.OFPFW_DL_VLAN | ofp.OFPFW_DL_VLAN_PCP,
Dan Talayco551befa2010-07-15 17:05:32 -070049 ofp.OFPFW_DL_SRC,
50 ofp.OFPFW_DL_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070051 (ofp.OFPFW_DL_TYPE | ofp.OFPFW_NW_SRC_ALL |
52 ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS | ofp.OFPFW_NW_PROTO |
53 ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
54 (ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
Dan Talayco551befa2010-07-15 17:05:32 -070055 ofp.OFPFW_TP_SRC,
56 ofp.OFPFW_TP_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070057 ofp.OFPFW_NW_SRC_MASK,
58 ofp.OFPFW_NW_DST_MASK,
Dan Talayco551befa2010-07-15 17:05:32 -070059 ofp.OFPFW_DL_VLAN_PCP,
60 ofp.OFPFW_NW_TOS]
61
Dan Talayco488fbc52012-04-09 16:30:41 -070062NO_WILDCARD_VALUES = [(ofp.OFPFW_ALL ^ ofp.OFPFW_IN_PORT),
63 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN),
64 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_SRC),
65 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_DST),
66 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE),
67 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO),
68 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
69 ofp.OFPFW_TP_SRC),
70 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
71 ofp.OFPFW_TP_DST),
72 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
73 ofp.OFPFW_NW_SRC_MASK),
74 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
75 ofp.OFPFW_NW_DST_MASK),
76 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN ^ ofp.OFPFW_DL_VLAN_PCP),
77 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
78 ofp.OFPFW_NW_TOS)]
79
Dan Talayco551befa2010-07-15 17:05:32 -070080MODIFY_ACTION_VALUES = [ofp.OFPAT_SET_VLAN_VID,
81 ofp.OFPAT_SET_VLAN_PCP,
82 ofp.OFPAT_STRIP_VLAN,
83 ofp.OFPAT_SET_DL_SRC,
84 ofp.OFPAT_SET_DL_DST,
85 ofp.OFPAT_SET_NW_SRC,
86 ofp.OFPAT_SET_NW_DST,
87 ofp.OFPAT_SET_NW_TOS,
88 ofp.OFPAT_SET_TP_SRC,
89 ofp.OFPAT_SET_TP_DST]
90
Dan Talayco21381562010-07-17 00:34:47 -070091TEST_VID_DEFAULT = 2
92
Dan Talayco5eba8442010-03-10 13:58:43 -080093def test_set_init(config):
94 """
95 Set up function for packet action test classes
96
97 @param config The configuration dictionary; see oft
98 """
99
Ed Swierk89f78352012-03-29 12:32:32 -0700100 basic.test_set_init(config)
101
Dan Talayco5eba8442010-03-10 13:58:43 -0800102 global pa_port_map
103 global pa_logger
104 global pa_config
105
106 pa_logger = logging.getLogger("pkt_act")
107 pa_logger.info("Initializing test set")
108 pa_port_map = config["port_map"]
109 pa_config = config
110
111class DirectPacket(basic.SimpleDataPlane):
112 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700113 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -0800114
115 Generate a packet
116 Generate and install a matching flow
117 Add action to direct the packet to an egress port
118 Send the packet to ingress dataplane port
119 Verify the packet is received at the egress port only
120 """
121 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700122 self.handleFlow()
123
124 def handleFlow(self, pkttype='TCP'):
Dan Talayco5eba8442010-03-10 13:58:43 -0800125 of_ports = pa_port_map.keys()
126 of_ports.sort()
127 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
128
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700129 if (pkttype == 'ICMP'):
130 pkt = simple_icmp_packet()
131 else:
132 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700133 match = packet_to_flow_match(self, pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700134 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800135 self.assertTrue(match is not None,
136 "Could not generate flow match from pkt")
137 act = action.action_output()
138
139 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700140 rv = delete_all_flows(self.controller, pa_logger)
141 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700142
Dan Talayco5eba8442010-03-10 13:58:43 -0800143 ingress_port = of_ports[idx]
144 egress_port = of_ports[(idx + 1) % len(of_ports)]
145 pa_logger.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700146 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800147
148 match.in_port = ingress_port
149
150 request = message.flow_mod()
151 request.match = match
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700152
Dan Talayco5eba8442010-03-10 13:58:43 -0800153 request.buffer_id = 0xffffffff
154 act.port = egress_port
155 self.assertTrue(request.actions.add(act), "Could not add action")
156
157 pa_logger.info("Inserting flow")
158 rv = self.controller.message_send(request)
159 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700160 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco5eba8442010-03-10 13:58:43 -0800161
162 pa_logger.info("Sending packet to dp port " +
163 str(ingress_port))
164 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700165
166 exp_pkt_arg = None
167 exp_port = None
168 if pa_config["relax"]:
169 exp_pkt_arg = pkt
170 exp_port = egress_port
171
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700172 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700173 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800174 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700175 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800176 str(rcv_port))
177 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
178 self.assertEqual(str(pkt), str(rcv_pkt),
179 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700180
Rich Lane51c23b32012-07-27 16:37:25 -0700181class DirectPacketController(basic.SimpleDataPlane):
182 """
183 Send packet to the controller port
184
185 Generate a packet
186 Generate and install a matching flow
187 Add action to direct the packet to the controller port
188 Send the packet to ingress dataplane port
189 Verify the packet is received at the controller port
190 """
191 def runTest(self):
192 self.handleFlow()
193
194 def handleFlow(self, pkttype='TCP'):
195 of_ports = pa_port_map.keys()
196 of_ports.sort()
197 self.assertTrue(len(of_ports) > 0, "Not enough ports for test")
198
199 if (pkttype == 'ICMP'):
200 pkt = simple_icmp_packet()
201 else:
202 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700203 match = packet_to_flow_match(self, pkt)
Rich Lane51c23b32012-07-27 16:37:25 -0700204 match.wildcards &= ~ofp.OFPFW_IN_PORT
205 self.assertTrue(match is not None,
206 "Could not generate flow match from pkt")
207 act = action.action_output()
208
209 rv = delete_all_flows(self.controller, pa_logger)
210 self.assertEqual(rv, 0, "Failed to delete all flows")
211
212 ingress_port = of_ports[0]
213 match.in_port = ingress_port
214
215 request = message.flow_mod()
216 request.match = match
217
218 request.buffer_id = 0xffffffff
219 act.port = ofp.OFPP_CONTROLLER
220 act.max_len = 65535
221 self.assertTrue(request.actions.add(act), "Could not add action")
222
223 pa_logger.info("Inserting flow")
224 rv = self.controller.message_send(request)
225 self.assertTrue(rv != -1, "Error installing flow mod")
226 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
227
228 pa_logger.info("Sending packet to dp port " +
229 str(ingress_port))
230 self.dataplane.send(ingress_port, str(pkt))
231
232 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
233
234 self.assertTrue(response is not None,
235 'Packet in message not received by controller')
236 if not dataplane.match_exp_pkt(pkt, response.data):
237 pa_logger.debug("Sent %s" % format_packet(pkt))
238 pa_logger.debug("Resp %s" % format_packet(response.data))
239 self.assertTrue(False,
240 'Response packet does not match send packet' +
241 ' for controller port')
242
Howard Pershf97840f2012-04-10 16:30:42 -0700243
244class DirectPacketQueue(basic.SimpleDataPlane):
245 """
246 Send packet to single queue on single egress port
247
248 Generate a packet
249 Generate and install a matching flow
250 Add action to direct the packet to an egress port and queue
251 Send the packet to ingress dataplane port
252 Verify the packet is received at the egress port only
253 """
254 def runTest(self):
255 self.handleFlow()
256
Howard Persh670b5672012-04-13 09:08:29 -0700257 def portQueuesGet(self, queue_stats, port_num):
258 result = []
259 for qs in queue_stats.stats:
260 if qs.port_no != port_num:
261 continue
262 result.append(qs.queue_id)
263 return result
264
Howard Pershf97840f2012-04-10 16:30:42 -0700265 def handleFlow(self, pkttype='TCP'):
266 of_ports = pa_port_map.keys()
267 of_ports.sort()
268 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
269
270 if (pkttype == 'ICMP'):
271 pkt = simple_icmp_packet()
272 else:
273 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700274 match = packet_to_flow_match(self, pkt)
Howard Pershf97840f2012-04-10 16:30:42 -0700275 match.wildcards &= ~ofp.OFPFW_IN_PORT
276 self.assertTrue(match is not None,
277 "Could not generate flow match from pkt")
278
Howard Persh670b5672012-04-13 09:08:29 -0700279 # Get queue stats from switch
280
281 request = message.queue_stats_request()
282 request.port_no = ofp.OFPP_ALL
283 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700284 (queue_stats, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700285 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
286
287 act = action.action_enqueue()
Howard Pershf97840f2012-04-10 16:30:42 -0700288
289 for idx in range(len(of_ports)):
Howard Pershf97840f2012-04-10 16:30:42 -0700290 ingress_port = of_ports[idx]
291 egress_port = of_ports[(idx + 1) % len(of_ports)]
Howard Pershf97840f2012-04-10 16:30:42 -0700292
Howard Persh670b5672012-04-13 09:08:29 -0700293 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
294 pa_logger.info("Ingress " + str(ingress_port)
295 + " to egress " + str(egress_port)
296 + " queue " + str(egress_queue_id)
297 )
Howard Pershf97840f2012-04-10 16:30:42 -0700298
Howard Persh670b5672012-04-13 09:08:29 -0700299 rv = delete_all_flows(self.controller, pa_logger)
300 self.assertEqual(rv, 0, "Failed to delete all flows")
Howard Pershf97840f2012-04-10 16:30:42 -0700301
Howard Persh670b5672012-04-13 09:08:29 -0700302 match.in_port = ingress_port
303
304 request = message.flow_mod()
305 request.match = match
Howard Pershf97840f2012-04-10 16:30:42 -0700306
Howard Persh670b5672012-04-13 09:08:29 -0700307 request.buffer_id = 0xffffffff
308 act.port = egress_port
309 act.queue_id = egress_queue_id
310 self.assertTrue(request.actions.add(act), "Could not add action")
Howard Pershf97840f2012-04-10 16:30:42 -0700311
Howard Persh670b5672012-04-13 09:08:29 -0700312 pa_logger.info("Inserting flow")
313 rv = self.controller.message_send(request)
314 self.assertTrue(rv != -1, "Error installing flow mod")
315 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Howard Pershf97840f2012-04-10 16:30:42 -0700316
Howard Persh670b5672012-04-13 09:08:29 -0700317 # Get current stats for selected egress queue
Howard Pershf97840f2012-04-10 16:30:42 -0700318
Howard Persh670b5672012-04-13 09:08:29 -0700319 request = message.queue_stats_request()
320 request.port_no = egress_port
321 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700322 (qs_before, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700323 self.assertNotEqual(qs_before, None, "Queue stats request failed")
324
325 pa_logger.info("Sending packet to dp port " +
326 str(ingress_port))
327 self.dataplane.send(ingress_port, str(pkt))
328
329 exp_pkt_arg = None
330 exp_port = None
331 if pa_config["relax"]:
332 exp_pkt_arg = pkt
333 exp_port = egress_port
334
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700335 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Howard Persh670b5672012-04-13 09:08:29 -0700336 exp_pkt=exp_pkt_arg)
337 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
338 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
339 str(rcv_port))
340 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
341 self.assertEqual(str(pkt), str(rcv_pkt),
342 'Response packet does not match send packet')
343
Ed Swierkb8a86512012-04-18 18:45:58 -0700344 # FIXME: instead of sleeping, keep requesting queue stats until
345 # the expected queue counter increases or some large timeout is
346 # reached
347 time.sleep(2)
348
Howard Persh670b5672012-04-13 09:08:29 -0700349 # Get current stats for selected egress queue again
350
351 request = message.queue_stats_request()
352 request.port_no = egress_port
353 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700354 (qs_after, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700355 self.assertNotEqual(qs_after, None, "Queue stats request failed")
356
357 # Make sure that tx packet counter for selected egress queue was
358 # incremented
359
Ed Swierk22f59152012-04-17 16:36:47 -0700360 self.assertEqual(qs_after.stats[0].tx_packets, \
361 qs_before.stats[0].tx_packets + 1, \
Howard Persh670b5672012-04-13 09:08:29 -0700362 "Verification of egress queue tx packet count failed"
363 )
364
365
Ken Chiang899ff8e2012-05-23 18:26:12 -0700366class DirectPacketControllerQueue(basic.SimpleDataPlane):
367 """
368 Send a packet from each of the openflow ports
369 to each of the queues configured on the controller port.
370 If no queues have been configured, no packets are sent.
Howard Pershf97840f2012-04-10 16:30:42 -0700371
Ken Chiang899ff8e2012-05-23 18:26:12 -0700372 Generate a packet
373 Generate and install a matching flow
374 Add action to direct the packet to one of the controller port queues
375 Send the packet to ingress dataplane port
376 Verify the packet is received on the controller port queue
377 """
378 def runTest(self):
379 self.handleFlow()
380
381 def portQueuesGet(self, queue_stats, port_num):
382 result = []
383 for qs in queue_stats.stats:
384 if qs.port_no != port_num:
385 continue
386 result.append(qs.queue_id)
387 return result
388
389 def handleFlow(self, pkttype='TCP'):
390 of_ports = pa_port_map.keys()
391 of_ports.sort()
392 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
393
394 if (pkttype == 'ICMP'):
395 pkt = simple_icmp_packet()
396 else:
397 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700398 match = packet_to_flow_match(self, pkt)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700399 match.wildcards &= ~ofp.OFPFW_IN_PORT
400 self.assertTrue(match is not None,
401 "Could not generate flow match from pkt")
402
403 # Get queue stats from switch
404
405 request = message.queue_stats_request()
406 request.port_no = ofp.OFPP_CONTROLLER
407 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700408 (queue_stats, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700409 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
410
411 act = action.action_enqueue()
412
413 for idx in range(len(of_ports)):
414 ingress_port = of_ports[idx]
415 egress_port = ofp.OFPP_CONTROLLER
416
417 pa_logger.info("Ingress port " + str(ingress_port)
418 + ", controller port queues "
419 + str(self.portQueuesGet(queue_stats, egress_port)))
420
421 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
422 pa_logger.info("Ingress " + str(ingress_port)
423 + " to egress " + str(egress_port)
424 + " queue " + str(egress_queue_id)
425 )
426
427 rv = delete_all_flows(self.controller, pa_logger)
428 self.assertEqual(rv, 0, "Failed to delete all flows")
429
430 match.in_port = ingress_port
431
432 request = message.flow_mod()
433 request.match = match
434
435 request.buffer_id = 0xffffffff
436 act.port = egress_port
437 act.queue_id = egress_queue_id
438 self.assertTrue(request.actions.add(act), "Could not add action")
439
440 pa_logger.info("Inserting flow")
441 rv = self.controller.message_send(request)
442 self.assertTrue(rv != -1, "Error installing flow mod")
443 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
444
445 # Get current stats for selected egress queue
446
447 request = message.queue_stats_request()
448 request.port_no = egress_port
449 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700450 (qs_before, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700451 self.assertNotEqual(qs_before, None, "Queue stats request failed")
452
453 pa_logger.info("Sending packet to dp port " +
454 str(ingress_port))
455 self.dataplane.send(ingress_port, str(pkt))
456
457 exp_pkt_arg = None
458 exp_port = None
459
460 while True:
Dan Talaycoc689a792012-09-28 14:22:53 -0700461 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700462 if not response: # Timeout
463 break
464 if dataplane.match_exp_pkt(pkt, response.data): # Got match
465 break
466 if not basic_config["relax"]: # Only one attempt to match
467 break
468 count += 1
469 if count > 10: # Too many tries
470 break
471
472 self.assertTrue(response is not None,
473 'Packet in message not received by controller')
474 if not dataplane.match_exp_pkt(pkt, response.data):
475 basic_logger.debug("Sent %s" % format_packet(pkt))
476 basic_logger.debug("Resp %s" % format_packet(response.data))
477 self.assertTrue(False,
478 'Response packet does not match send packet' +
479 ' for controller port')
480
481 # FIXME: instead of sleeping, keep requesting queue stats until
482 # the expected queue counter increases or some large timeout is
483 # reached
484 time.sleep(2)
485
486 # Get current stats for selected egress queue again
487
488 request = message.queue_stats_request()
489 request.port_no = egress_port
490 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700491 (qs_after, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700492 self.assertNotEqual(qs_after, None, "Queue stats request failed")
493
494 # Make sure that tx packet counter for selected egress queue was
495 # incremented
496
497 self.assertEqual(qs_after.stats[0].tx_packets, \
498 qs_before.stats[0].tx_packets + 1, \
499 "Verification of egress queue tx packet count failed"
500 )
501
Howard Pershf97840f2012-04-10 16:30:42 -0700502
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700503class DirectPacketICMP(DirectPacket):
504 """
505 Send ICMP packet to single egress port
506
507 Generate a ICMP packet
508 Generate and install a matching flow
509 Add action to direct the packet to an egress port
510 Send the packet to ingress dataplane port
511 Verify the packet is received at the egress port only
512 Difference from DirectPacket test is that sent packet is ICMP
513 """
514 def runTest(self):
515 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700516
517class DirectTwoPorts(basic.SimpleDataPlane):
518 """
519 Send packet to two egress ports
520
521 Generate a packet
522 Generate and install a matching flow
523 Add action to direct the packet to two egress ports
524 Send the packet to ingress dataplane port
525 Verify the packet is received at the two egress ports
526 """
527 def runTest(self):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700528 of_ports = pa_port_map.keys()
529 of_ports.sort()
530 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
531
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700532 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700533 match = packet_to_flow_match(self, pkt)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700534 match.wildcards &= ~ofp.OFPFW_IN_PORT
535 self.assertTrue(match is not None,
536 "Could not generate flow match from pkt")
537 act = action.action_output()
538
539 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700540 rv = delete_all_flows(self.controller, pa_logger)
541 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700542
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700543 ingress_port = of_ports[idx]
544 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
545 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
546 pa_logger.info("Ingress " + str(ingress_port) +
547 " to egress " + str(egress_port1) + " and " +
548 str(egress_port2))
549
550 match.in_port = ingress_port
551
552 request = message.flow_mod()
553 request.match = match
554 request.buffer_id = 0xffffffff
555 act.port = egress_port1
556 self.assertTrue(request.actions.add(act), "Could not add action1")
557 act.port = egress_port2
558 self.assertTrue(request.actions.add(act), "Could not add action2")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700559 # pa_logger.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700560
561 pa_logger.info("Inserting flow")
562 rv = self.controller.message_send(request)
563 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700564 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700565
566 pa_logger.info("Sending packet to dp port " +
567 str(ingress_port))
568 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700569 yes_ports = set([egress_port1, egress_port2])
570 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700571
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700572 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700573 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700574
575class DirectMCNonIngress(basic.SimpleDataPlane):
576 """
577 Multicast to all non-ingress ports
578
579 Generate a packet
580 Generate and install a matching flow
581 Add action to direct the packet to all non-ingress ports
582 Send the packet to ingress dataplane port
583 Verify the packet is received at all non-ingress ports
584
585 Does not use the flood action
586 """
587 def runTest(self):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700588 of_ports = pa_port_map.keys()
589 of_ports.sort()
590 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
591
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700592 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700593 match = packet_to_flow_match(self, pkt)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700594 match.wildcards &= ~ofp.OFPFW_IN_PORT
595 self.assertTrue(match is not None,
596 "Could not generate flow match from pkt")
597 act = action.action_output()
598
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700599 for ingress_port in of_ports:
600 rv = delete_all_flows(self.controller, pa_logger)
601 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700602
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700603 pa_logger.info("Ingress " + str(ingress_port) +
604 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700605 match.in_port = ingress_port
606
607 request = message.flow_mod()
608 request.match = match
609 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700610 for egress_port in of_ports:
611 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700612 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700613 act.port = egress_port
614 self.assertTrue(request.actions.add(act),
615 "Could not add output to " + str(egress_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700616 pa_logger.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700617
618 pa_logger.info("Inserting flow")
619 rv = self.controller.message_send(request)
620 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700621 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700622
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700623 pa_logger.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700624 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700625 yes_ports = set(of_ports).difference([ingress_port])
626 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700627 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700628
Dan Talayco32fa6542010-05-11 15:54:08 -0700629
630class DirectMC(basic.SimpleDataPlane):
631 """
632 Multicast to all ports including ingress
633
634 Generate a packet
635 Generate and install a matching flow
636 Add action to direct the packet to all non-ingress ports
637 Send the packet to ingress dataplane port
638 Verify the packet is received at all ports
639
640 Does not use the flood action
641 """
642 def runTest(self):
Dan Talayco32fa6542010-05-11 15:54:08 -0700643 of_ports = pa_port_map.keys()
644 of_ports.sort()
645 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
646
Dan Talayco32fa6542010-05-11 15:54:08 -0700647 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700648 match = packet_to_flow_match(self, pkt)
Dan Talayco32fa6542010-05-11 15:54:08 -0700649 match.wildcards &= ~ofp.OFPFW_IN_PORT
650 self.assertTrue(match is not None,
651 "Could not generate flow match from pkt")
652 act = action.action_output()
653
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700654 for ingress_port in of_ports:
655 rv = delete_all_flows(self.controller, pa_logger)
656 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700657
Dan Talayco32fa6542010-05-11 15:54:08 -0700658 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700659 match.in_port = ingress_port
660
661 request = message.flow_mod()
662 request.match = match
663 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700664 for egress_port in of_ports:
665 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700666 act.port = ofp.OFPP_IN_PORT
667 else:
668 act.port = egress_port
669 self.assertTrue(request.actions.add(act),
670 "Could not add output to " + str(egress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700671 # pa_logger.info(request.show())
672
673 pa_logger.info("Inserting flow")
674 rv = self.controller.message_send(request)
675 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700676 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2e77a842010-05-12 15:39:46 -0700677
678 pa_logger.info("Sending packet to dp port " + str(ingress_port))
679 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700680 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700681 pa_logger, pa_config)
Dan Talayco2e77a842010-05-12 15:39:46 -0700682
683class Flood(basic.SimpleDataPlane):
684 """
685 Flood to all ports except ingress
686
687 Generate a packet
688 Generate and install a matching flow
689 Add action to flood the packet
690 Send the packet to ingress dataplane port
691 Verify the packet is received at all other ports
692 """
693 def runTest(self):
Dan Talayco2e77a842010-05-12 15:39:46 -0700694 of_ports = pa_port_map.keys()
695 of_ports.sort()
696 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
697
698 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700699 match = packet_to_flow_match(self, pkt)
Dan Talayco2e77a842010-05-12 15:39:46 -0700700 match.wildcards &= ~ofp.OFPFW_IN_PORT
701 self.assertTrue(match is not None,
702 "Could not generate flow match from pkt")
703 act = action.action_output()
704
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700705 for ingress_port in of_ports:
706 rv = delete_all_flows(self.controller, pa_logger)
707 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700708
Dan Talayco2e77a842010-05-12 15:39:46 -0700709 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700710 match.in_port = ingress_port
711
712 request = message.flow_mod()
713 request.match = match
714 request.buffer_id = 0xffffffff
715 act.port = ofp.OFPP_FLOOD
716 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700717 "Could not add flood port action")
Dan Talayco32fa6542010-05-11 15:54:08 -0700718 pa_logger.info(request.show())
719
720 pa_logger.info("Inserting flow")
721 rv = self.controller.message_send(request)
722 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700723 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco32fa6542010-05-11 15:54:08 -0700724
725 pa_logger.info("Sending packet to dp port " + str(ingress_port))
726 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700727 yes_ports = set(of_ports).difference([ingress_port])
728 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700729 self, pa_logger, pa_config)
Dan Talayco3be5b062010-05-12 15:46:21 -0700730
Dan Talayco3be5b062010-05-12 15:46:21 -0700731class FloodPlusIngress(basic.SimpleDataPlane):
732 """
733 Flood to all ports plus send to ingress port
734
735 Generate a packet
736 Generate and install a matching flow
737 Add action to flood the packet
738 Add action to send to ingress port
739 Send the packet to ingress dataplane port
740 Verify the packet is received at all other ports
741 """
742 def runTest(self):
Dan Talayco3be5b062010-05-12 15:46:21 -0700743 of_ports = pa_port_map.keys()
744 of_ports.sort()
745 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
746
747 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700748 match = packet_to_flow_match(self, pkt)
Dan Talayco3be5b062010-05-12 15:46:21 -0700749 match.wildcards &= ~ofp.OFPFW_IN_PORT
750 self.assertTrue(match is not None,
751 "Could not generate flow match from pkt")
752 act = action.action_output()
753
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700754 for ingress_port in of_ports:
755 rv = delete_all_flows(self.controller, pa_logger)
756 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700757
Dan Talayco3be5b062010-05-12 15:46:21 -0700758 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700759 match.in_port = ingress_port
760
761 request = message.flow_mod()
762 request.match = match
763 request.buffer_id = 0xffffffff
764 act.port = ofp.OFPP_FLOOD
765 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700766 "Could not add flood port action")
767 act.port = ofp.OFPP_IN_PORT
768 self.assertTrue(request.actions.add(act),
769 "Could not add ingress port for output")
770 pa_logger.info(request.show())
771
772 pa_logger.info("Inserting flow")
773 rv = self.controller.message_send(request)
774 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700775 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700776
777 pa_logger.info("Sending packet to dp port " + str(ingress_port))
778 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700779 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700780 pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700781
782class All(basic.SimpleDataPlane):
783 """
784 Send to OFPP_ALL port
785
786 Generate a packet
787 Generate and install a matching flow
788 Add action to forward to OFPP_ALL
789 Send the packet to ingress dataplane port
790 Verify the packet is received at all other ports
791 """
792 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700793 of_ports = pa_port_map.keys()
794 of_ports.sort()
795 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
796
797 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700798 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700799 match.wildcards &= ~ofp.OFPFW_IN_PORT
800 self.assertTrue(match is not None,
801 "Could not generate flow match from pkt")
802 act = action.action_output()
803
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700804 for ingress_port in of_ports:
805 rv = delete_all_flows(self.controller, pa_logger)
806 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700807
Dan Talayco4aa13122010-05-12 15:54:44 -0700808 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700809 match.in_port = ingress_port
810
811 request = message.flow_mod()
812 request.match = match
813 request.buffer_id = 0xffffffff
814 act.port = ofp.OFPP_ALL
815 self.assertTrue(request.actions.add(act),
816 "Could not add ALL port action")
817 pa_logger.info(request.show())
818
819 pa_logger.info("Inserting flow")
820 rv = self.controller.message_send(request)
821 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700822 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700823
824 pa_logger.info("Sending packet to dp port " + str(ingress_port))
825 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700826 yes_ports = set(of_ports).difference([ingress_port])
827 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700828 self, pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700829
830class AllPlusIngress(basic.SimpleDataPlane):
831 """
832 Send to OFPP_ALL port and ingress port
833
834 Generate a packet
835 Generate and install a matching flow
836 Add action to forward to OFPP_ALL
837 Add action to forward to ingress port
838 Send the packet to ingress dataplane port
839 Verify the packet is received at all other ports
840 """
841 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700842 of_ports = pa_port_map.keys()
843 of_ports.sort()
844 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
845
846 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700847 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700848 match.wildcards &= ~ofp.OFPFW_IN_PORT
849 self.assertTrue(match is not None,
850 "Could not generate flow match from pkt")
851 act = action.action_output()
852
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700853 for ingress_port in of_ports:
854 rv = delete_all_flows(self.controller, pa_logger)
855 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700856
Dan Talayco4aa13122010-05-12 15:54:44 -0700857 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700858 match.in_port = ingress_port
859
860 request = message.flow_mod()
861 request.match = match
862 request.buffer_id = 0xffffffff
863 act.port = ofp.OFPP_ALL
864 self.assertTrue(request.actions.add(act),
865 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700866 act.port = ofp.OFPP_IN_PORT
867 self.assertTrue(request.actions.add(act),
868 "Could not add ingress port for output")
869 pa_logger.info(request.show())
870
871 pa_logger.info("Inserting flow")
872 rv = self.controller.message_send(request)
873 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700874 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco3be5b062010-05-12 15:46:21 -0700875
876 pa_logger.info("Sending packet to dp port " + str(ingress_port))
877 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700878 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700879 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700880
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700881class FloodMinusPort(basic.SimpleDataPlane):
882 """
883 Config port with No_Flood and test Flood action
884
885 Generate a packet
886 Generate a matching flow
887 Add action to forward to OFPP_ALL
888 Set port to no-flood
889 Send the packet to ingress dataplane port
890 Verify the packet is received at all other ports except
891 the ingress port and the no_flood port
892 """
893 def runTest(self):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700894 of_ports = pa_port_map.keys()
895 of_ports.sort()
896 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
897
898 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700899 match = packet_to_flow_match(self, pkt)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700900 match.wildcards &= ~ofp.OFPFW_IN_PORT
901 self.assertTrue(match is not None,
902 "Could not generate flow match from pkt")
903 act = action.action_output()
904
905 for idx in range(len(of_ports)):
906 rv = delete_all_flows(self.controller, pa_logger)
907 self.assertEqual(rv, 0, "Failed to delete all flows")
908
909 ingress_port = of_ports[idx]
910 no_flood_idx = (idx + 1) % len(of_ports)
911 no_flood_port = of_ports[no_flood_idx]
912 rv = port_config_set(self.controller, no_flood_port,
913 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
914 pa_logger)
915 self.assertEqual(rv, 0, "Failed to set port config")
916
917 match.in_port = ingress_port
918
919 request = message.flow_mod()
920 request.match = match
921 request.buffer_id = 0xffffffff
922 act.port = ofp.OFPP_FLOOD
923 self.assertTrue(request.actions.add(act),
924 "Could not add flood port action")
925 pa_logger.info(request.show())
926
927 pa_logger.info("Inserting flow")
928 rv = self.controller.message_send(request)
929 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700930 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700931
932 pa_logger.info("Sending packet to dp port " + str(ingress_port))
933 pa_logger.info("No flood port is " + str(no_flood_port))
934 self.dataplane.send(ingress_port, str(pkt))
935 no_ports = set([ingress_port, no_flood_port])
936 yes_ports = set(of_ports).difference(no_ports)
937 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700938 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700939
940 # Turn no flood off again
941 rv = port_config_set(self.controller, no_flood_port,
942 0, ofp.OFPPC_NO_FLOOD, pa_logger)
943 self.assertEqual(rv, 0, "Failed to reset port config")
944
945 #@todo Should check no other packets received
946
Dan Talayco21381562010-07-17 00:34:47 -0700947
948
Dan Talayco551befa2010-07-15 17:05:32 -0700949################################################################
950
951class BaseMatchCase(basic.SimpleDataPlane):
952 def setUp(self):
953 basic.SimpleDataPlane.setUp(self)
954 self.logger = pa_logger
955 def runTest(self):
956 self.logger.info("BaseMatchCase")
957
958class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700959 """
Dan Talayco551befa2010-07-15 17:05:32 -0700960 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700961
962 Generate a packet
963 Generate and install a matching flow without wildcard mask
964 Add action to forward to a port
965 Send the packet to the port
966 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700967 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700968
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700969 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700970 flow_match_test(self, pa_port_map)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700971
Dan Talayco551befa2010-07-15 17:05:32 -0700972class ExactMatchTagged(BaseMatchCase):
973 """
974 Exact match for all port pairs with tagged pkts
975 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700976
Dan Talayco551befa2010-07-15 17:05:32 -0700977 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700978 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700979 flow_match_test(self, pa_port_map, dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700980
Dan Talayco551befa2010-07-15 17:05:32 -0700981class ExactMatchTaggedMany(BaseMatchCase):
982 """
983 ExactMatchTagged with many VLANS
984 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700985
Dan Talayco551befa2010-07-15 17:05:32 -0700986 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700987 for vid in range(2,100,10):
Dan Talayco551befa2010-07-15 17:05:32 -0700988 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
989 for vid in range(100,4000,389):
990 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
991 flow_match_test(self, pa_port_map, dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700992
Dan Talayco551befa2010-07-15 17:05:32 -0700993# Don't run by default
994test_prio["ExactMatchTaggedMany"] = -1
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700995
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700996
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700997class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700998 """
999 SingleWildcardMatchPriority
1000 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001001
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001002 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001003 self.pkt = simple_tcp_packet()
1004 self.flowMsgs = {}
1005
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001006 def _ClearTable(self):
1007 rc = delete_all_flows(self.controller, self.logger)
1008 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001009 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001010
1011 def runTest(self):
1012
1013 self._Init()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001014 of_ports = pa_port_map.keys()
1015 of_ports.sort()
1016
1017 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001018 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001019
1020 # Run several combinations, each at lower priority settings.
1021 # At the end of each call to runPrioFlows(), the table should
1022 # be empty. If its not, we'll catch it as the priorities decreases
1023 portA = of_ports[0]
1024 portB = of_ports[1]
1025 portC = of_ports[2]
1026
1027 # TODO -- these priority numbers should be validated somehow?
1028 self.runPrioFlows(portA, portB, portC, 1000, 999)
1029 self.runPrioFlows(portB, portC, portA, 998, 997)
1030 self.runPrioFlows(portC, portA, portB, 996, 995)
1031 self.runPrioFlows(portA, portC, portB, 994, 993)
1032
1033
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001034
1035 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
1036 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001037
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001038 if clearTable:
1039 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001040
1041 # Sanity check flow at lower priority from pA to pB
1042 self.logger.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
1043 % (portA, portB, portC, prioHigher, prioLower))
1044
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001045 # Sanity check flow at lower priority from pA to pC
1046 self.installFlow(prioLower, portA, portC)
1047 self.verifyFlow(portA, portC)
1048 self.removeFlow(prioLower)
1049
1050 # Install and verify pA->pB @ prioLower
1051 self.installFlow(prioLower, portA, portB)
1052 self.verifyFlow(portA, portB)
1053
1054 # Install and verify pA->pC @ prioHigher, should override pA->pB
1055 self.installFlow(prioHigher, portA, portC)
1056 self.verifyFlow(portA, portC)
1057 # remove pA->pC
1058 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001059 # Old flow pA -> pB @ prioLower should still be active
1060 self.verifyFlow(portA, portB)
1061 self.removeFlow(prioLower)
1062
1063 # Table should be empty at this point, leave it alone as
1064 # an assumption for future test runs
1065
1066
1067
Ed Swierk99a74de2012-08-22 06:40:54 -07001068 def installFlow(self, prio, inp, egp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001069 wildcards=ofp.OFPFW_DL_SRC):
Ed Swierk99a74de2012-08-22 06:40:54 -07001070 wildcards |= required_wildcards(self)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001071 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001072 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001073 egr_ports=egp)
1074 request.priority = prio
Ken Chiang38d7a152012-05-24 15:33:50 -07001075 self.logger.debug("Install flow with priority " + str(prio))
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001076 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001077 self.flowMsgs[prio] = request
1078
1079 def removeFlow(self, prio):
1080 if self.flowMsgs.has_key(prio):
1081 msg = self.flowMsgs[prio]
1082 msg.command = ofp.OFPFC_DELETE_STRICT
1083 # This *must* be set for DELETE
1084 msg.out_port = ofp.OFPP_NONE
Ken Chiang38d7a152012-05-24 15:33:50 -07001085 self.logger.debug("Remove flow with priority " + str(prio))
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001086 self.controller.message_send(msg)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001087 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001088 else:
1089 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001090
1091
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001092 def verifyFlow(self, inp, egp, pkt=None):
1093 if pkt == None:
1094 pkt = self.pkt
1095
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001096 self.logger.info("Pkt match test: " + str(inp) +
1097 " to " + str(egp))
1098 self.logger.debug("Send packet: " + str(inp) + " to "
1099 + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001100 self.dataplane.send(inp, str(pkt))
1101 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001102
1103
1104
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001105class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
1106
1107 def runTest(self):
1108
1109 self._Init()
1110
1111 of_ports = pa_port_map.keys()
1112 of_ports.sort()
1113
1114 # Install an entry from 0 -> 1 @ prio 1000
1115 self._ClearTable()
1116 self.installFlow(1000, of_ports[0], of_ports[1])
1117 self.verifyFlow(of_ports[0], of_ports[1])
1118 self.installFlow(1000, of_ports[1], of_ports[0])
1119 self.verifyFlow(of_ports[1], of_ports[0])
1120 self.installFlow(1001, of_ports[0], of_ports[1])
1121 self.verifyFlow(of_ports[0], of_ports[1])
1122 self.installFlow(1001, of_ports[1], of_ports[0])
1123 self.verifyFlow(of_ports[1], of_ports[0])
1124 self.removeFlow(1001)
1125 self.verifyFlow(of_ports[0], of_ports[1])
1126 self.removeFlow(1000)
1127
1128
1129
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001130class WildcardPriority(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001131 """
1132 1. Add wildcard flow, verify packet received.
1133 2. Add exact match flow with higher priority, verify packet received
1134 on port specified by this flow.
1135 3. Add wildcard flow with even higher priority, verify packet received
1136 on port specified by this flow.
1137 """
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001138
1139 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001140
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001141 self._Init()
1142
1143 of_ports = pa_port_map.keys()
1144 of_ports.sort()
1145
1146 self._ClearTable()
Ken Chiang38d7a152012-05-24 15:33:50 -07001147
1148 # Install a flow with wildcards
1149 self.installFlow(999, of_ports[0], of_ports[1],
1150 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001151 self.verifyFlow(of_ports[0], of_ports[1])
Ken Chiang38d7a152012-05-24 15:33:50 -07001152 # Install a flow with no wildcards for our packet
1153 self.installFlow(1000, of_ports[0], of_ports[2], wildcards=0)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001154 self.verifyFlow(of_ports[0], of_ports[2])
Ken Chiang38d7a152012-05-24 15:33:50 -07001155 # Install a flow with wildcards for our packet with higher
1156 # priority
1157 self.installFlow(1001, of_ports[0], of_ports[3])
1158 self.verifyFlow(of_ports[0], of_ports[3])
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001159
1160
Ken Chiang3978f242012-06-13 14:14:09 -07001161class WildcardPriorityWithDelete(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001162 """
1163 1. Add exact match flow, verify packet received.
1164 2. Add wildcard flow with higher priority, verify packet received on port
1165 specified by this flow.
1166 3. Add exact match flow with even higher priority, verify packet received
1167 on port specified by this flow.
1168 4. Delete lowest priority flow, verify packet received on port specified
1169 by highest priority flow.
1170 5. Delete highest priority flow, verify packet received on port specified
1171 by remaining flow.
1172 """
1173
1174 def runTest(self):
1175
1176 self._Init()
1177
1178 of_ports = pa_port_map.keys()
1179 of_ports.sort()
1180
1181 self._ClearTable()
1182
1183 # Install an exact match flow
1184 self.installFlow(250, of_ports[0], of_ports[1], wildcards=0)
1185 self.verifyFlow(of_ports[0], of_ports[1])
1186 # Install a flow with wildcards of higher priority
1187 self.installFlow(1250, of_ports[0], of_ports[2],
1188 wildcards=ofp.OFPFW_DL_DST)
1189 self.verifyFlow(of_ports[0], of_ports[2])
1190 # Install an exact match flow with even higher priority
1191 self.installFlow(2001, of_ports[0], of_ports[3], wildcards=0)
1192 self.verifyFlow(of_ports[0], of_ports[3])
1193 # Delete lowest priority flow
1194 self.removeFlow(250)
1195 self.verifyFlow(of_ports[0], of_ports[3])
1196 # Delete highest priority flow
1197 self.removeFlow(2001)
1198 self.verifyFlow(of_ports[0], of_ports[2])
1199
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001200
Dan Talayco551befa2010-07-15 17:05:32 -07001201class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001202 """
1203 Exercise wildcard matching for all ports
1204
1205 Generate a packet
1206 Generate and install a matching flow with wildcard mask
1207 Add action to forward to a port
1208 Send the packet to the port
1209 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001210 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001211 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001212 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -07001213 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001214 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001215 wc |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001216 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001217 # Set nonzero VLAN id to avoid sending priority-tagged packet
1218 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001219 else:
1220 dl_vlan = -1
1221 flow_match_test(self, pa_port_map, wildcards=wc,
1222 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001223
Dan Talayco551befa2010-07-15 17:05:32 -07001224class SingleWildcardMatchTagged(BaseMatchCase):
1225 """
1226 SingleWildcardMatch with tagged packets
1227 """
1228 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001229 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001230 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001231 wc |= required_wildcards(self)
Dan Talayco21381562010-07-17 00:34:47 -07001232 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -07001233 max_test=10)
1234
1235class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001236 """
Dan Talayco80b54ed2010-07-13 09:48:35 -07001237 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001238
1239 Generate a packet
1240 Generate and install a matching flow with wildcard all except one filed
1241 Add action to forward to a port
1242 Send the packet to the port
1243 Verify the packet is received at all other ports (one port at a time)
1244 Verify flow_expiration message is correct when command option is set
1245 """
1246 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -07001247 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001248 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001249 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001250 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001251 # Set nonzero VLAN id to avoid sending priority-tagged packet
1252 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001253 else:
1254 dl_vlan = -1
1255 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
1256 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001257
Dan Talayco551befa2010-07-15 17:05:32 -07001258class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1259 """
1260 Match one field with tagged packets
1261 """
1262 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001263 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001264 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001265 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco21381562010-07-17 00:34:47 -07001266 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
1267 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001268
1269class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001270 """
1271 Create Wildcard-all flow and exercise for all ports
1272
1273 Generate a packet
1274 Generate and install a matching flow with wildcard-all
1275 Add action to forward to a port
1276 Send the packet to the port
1277 Verify the packet is received at all other ports (one port at a time)
1278 Verify flow_expiration message is correct when command option is set
1279 """
1280 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -07001281 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001282
Dan Talayco551befa2010-07-15 17:05:32 -07001283class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001284 """
Dan Talayco551befa2010-07-15 17:05:32 -07001285 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001286 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001287 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001288 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -07001289 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
1290 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001291
Dan Talaycoba3745c2010-07-21 21:51:08 -07001292
Dan Talayco551befa2010-07-15 17:05:32 -07001293class AddVLANTag(BaseMatchCase):
1294 """
1295 Add a VLAN tag to an untagged packet
1296 """
1297 def runTest(self):
1298 new_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001299 sup_acts = self.supported_actions
Dan Talayco551befa2010-07-15 17:05:32 -07001300 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001301 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001302 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001303
Dan Talayco551befa2010-07-15 17:05:32 -07001304 len = 100
1305 len_w_vid = 104
1306 pkt = simple_tcp_packet(pktlen=len)
1307 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1308 dl_vlan=new_vid)
1309 vid_act = action.action_set_vlan_vid()
1310 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001311
Dan Talayco551befa2010-07-15 17:05:32 -07001312 flow_match_test(self, pa_port_map, pkt=pkt,
1313 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001314
Dan Talayco551befa2010-07-15 17:05:32 -07001315class PacketOnly(basic.DataPlaneOnly):
1316 """
1317 Just send a packet thru the switch
1318 """
1319 def runTest(self):
1320 pkt = simple_tcp_packet()
1321 of_ports = pa_port_map.keys()
1322 of_ports.sort()
1323 ing_port = of_ports[0]
1324 pa_logger.info("Sending packet to " + str(ing_port))
1325 pa_logger.debug("Data: " + str(pkt).encode('hex'))
1326 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001327
Dan Talayco551befa2010-07-15 17:05:32 -07001328class PacketOnlyTagged(basic.DataPlaneOnly):
1329 """
1330 Just send a packet thru the switch
1331 """
1332 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001333 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001334 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
1335 of_ports = pa_port_map.keys()
1336 of_ports.sort()
1337 ing_port = of_ports[0]
1338 pa_logger.info("Sending packet to " + str(ing_port))
1339 pa_logger.debug("Data: " + str(pkt).encode('hex'))
1340 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001341
Dan Talayco551befa2010-07-15 17:05:32 -07001342test_prio["PacketOnly"] = -1
1343test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001344
Dan Talayco551befa2010-07-15 17:05:32 -07001345class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001346 """
1347 Modify the VLAN ID in the VLAN tag of a tagged packet
1348 """
Dan Talaycoaf669322012-09-12 22:51:22 -07001349 def setUp(self):
1350 BaseMatchCase.setUp(self)
1351 self.ing_port=False
1352
Dan Talayco551befa2010-07-15 17:05:32 -07001353 def runTest(self):
1354 old_vid = 2
1355 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001356 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001357 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001358 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001359 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001360
Dan Talayco551befa2010-07-15 17:05:32 -07001361 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1362 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
1363 vid_act = action.action_set_vlan_vid()
1364 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001365
Dan Talayco551befa2010-07-15 17:05:32 -07001366 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoaf669322012-09-12 22:51:22 -07001367 action_list=[vid_act], ing_port=self.ing_port)
1368
1369class ModifyVIDToIngress(ModifyVID):
1370 """
1371 Modify the VLAN ID in the VLAN tag of a tagged packet and send to
1372 ingress port
1373 """
1374 def setUp(self):
1375 BaseMatchCase.setUp(self)
1376 self.ing_port=True
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001377
Ken Chiange9a211d2012-04-20 14:52:11 -07001378class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1379 """
1380 With vlan ID and priority wildcarded, perform SET_VLAN_VID action.
1381 The same flow should match on both untagged and tagged packets.
1382 """
1383 def runTest(self):
1384 old_vid = 2
1385 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001386 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001387 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1388 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1389 return
1390
1391 of_ports = pa_port_map.keys()
1392 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1393 ing_port = of_ports[0]
1394 egr_ports = of_ports[1]
1395
1396 rv = delete_all_flows(self.controller, pa_logger)
1397 self.assertEqual(rv, 0, "Failed to delete all flows")
1398
1399 len_untagged = 100
1400 len_w_vid = 104
1401 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1402 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
1403 dl_vlan_enable=True, dl_vlan=old_vid)
1404 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1405 dl_vlan=new_vid)
Ed Swierk99a74de2012-08-22 06:40:54 -07001406 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1407 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001408 vid_act = action.action_set_vlan_vid()
1409 vid_act.vlan_vid = new_vid
1410 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
1411 wildcards=wildcards, egr_ports=egr_ports,
1412 action_list=[vid_act])
1413 flow_msg_install(self, request)
1414
1415 pa_logger.debug("Send untagged packet: " + str(ing_port) + " to " +
1416 str(egr_ports))
1417 self.dataplane.send(ing_port, str(untagged_pkt))
1418 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1419
1420 pa_logger.debug("Send tagged packet: " + str(ing_port) + " to " +
1421 str(egr_ports))
1422 self.dataplane.send(ing_port, str(tagged_pkt))
1423 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1424
Howard Pershc1199d52012-04-11 14:21:32 -07001425class ModifyVlanPcp(BaseMatchCase):
1426 """
1427 Modify the priority field of the VLAN tag of a tagged packet
1428 """
1429 def runTest(self):
1430 vid = 123
1431 old_vlan_pcp = 2
1432 new_vlan_pcp = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001433 sup_acts = self.supported_actions
Ed Swierk8c3af7f2012-04-24 14:19:17 -07001434 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_PCP):
1435 skip_message_emit(self, "Modify VLAN priority test")
Howard Pershc1199d52012-04-11 14:21:32 -07001436 return
1437
1438 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1439 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1440 vid_act = action.action_set_vlan_pcp()
1441 vid_act.vlan_pcp = new_vlan_pcp
1442
1443 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1444 action_list=[vid_act])
1445
Dan Talayco551befa2010-07-15 17:05:32 -07001446class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001447 """
1448 Strip the VLAN tag from a tagged packet
1449 """
Dan Talayco551befa2010-07-15 17:05:32 -07001450 def runTest(self):
1451 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001452 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001453 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001454 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001455 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001456
Dan Talayco551befa2010-07-15 17:05:32 -07001457 len_w_vid = 104
1458 len = 100
1459 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1460 dl_vlan=old_vid)
1461 exp_pkt = simple_tcp_packet(pktlen=len)
1462 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001463
Dan Talayco551befa2010-07-15 17:05:32 -07001464 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1465 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001466
Ken Chiange9a211d2012-04-20 14:52:11 -07001467class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1468 """
1469 Strip the VLAN tag from a tagged packet.
1470 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1471 """
1472 def runTest(self):
1473 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001474 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001475 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1476 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1477 return
1478
1479 len_w_vid = 104
1480 len_untagged = 100
1481 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1482 dl_vlan=old_vid)
1483 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
Ed Swierk99a74de2012-08-22 06:40:54 -07001484 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1485 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001486 vid_act = action.action_strip_vlan()
1487
1488 flow_match_test(self, pa_port_map,
Ed Swierk99a74de2012-08-22 06:40:54 -07001489 wildcards=wildcards,
Ken Chiange9a211d2012-04-20 14:52:11 -07001490 pkt=pkt, exp_pkt=exp_pkt,
1491 action_list=[vid_act])
1492
Dan Talayco4b2bee62010-07-20 14:10:05 -07001493def init_pkt_args():
1494 """
1495 Pass back a dictionary with default packet arguments
1496 """
1497 args = {}
1498 args["dl_src"] = '00:23:45:67:89:AB'
1499
1500 dl_vlan_enable=False
1501 dl_vlan=-1
1502 if pa_config["test-params"]["vid"]:
1503 dl_vlan_enable=True
1504 dl_vlan = pa_config["test-params"]["vid"]
1505
1506# Unpack operator is ** on a dictionary
1507
1508 return args
1509
Dan Talayco551befa2010-07-15 17:05:32 -07001510class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001511 """
1512 Modify the source MAC address (TP1)
1513 """
Dan Talayco551befa2010-07-15 17:05:32 -07001514 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001515 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001516 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001517 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001518 return
1519
1520 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1521 check_test_params=True)
1522 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1523 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001524
Dan Talayco551befa2010-07-15 17:05:32 -07001525class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001526 """
1527 Modify the dest MAC address (TP1)
1528 """
Dan Talayco551befa2010-07-15 17:05:32 -07001529 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001530 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001531 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001532 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001533 return
1534
1535 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1536 check_test_params=True)
1537 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1538 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001539
Dan Talayco551befa2010-07-15 17:05:32 -07001540class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001541 """
1542 Modify the source IP address of an IP packet (TP1)
1543 """
Dan Talayco551befa2010-07-15 17:05:32 -07001544 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001545 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001546 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001547 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001548 return
1549
1550 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1551 check_test_params=True)
1552 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1553 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001554
Dan Talayco551befa2010-07-15 17:05:32 -07001555class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001556 """
1557 Modify the dest IP address of an IP packet (TP1)
1558 """
Dan Talayco551befa2010-07-15 17:05:32 -07001559 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001560 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001561 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001562 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001563 return
1564
1565 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1566 check_test_params=True)
1567 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1568 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001569
1570class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001571 """
1572 Modify the source TCP port of a TCP packet (TP1)
1573 """
Dan Talayco551befa2010-07-15 17:05:32 -07001574 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001575 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001576 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001577 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001578 return
1579
1580 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1581 check_test_params=True)
1582 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1583 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001584
1585class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001586 """
1587 Modify the dest TCP port of a TCP packet (TP1)
1588 """
Dan Talayco551befa2010-07-15 17:05:32 -07001589 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001590 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001591 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001592 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001593 return
1594
1595 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1596 check_test_params=True)
1597 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1598 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001599
1600class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001601 """
1602 Modify the IP type of service of an IP packet (TP1)
1603 """
Dan Talayco551befa2010-07-15 17:05:32 -07001604 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001605 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001606 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001607 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001608 return
Dan Talayco551befa2010-07-15 17:05:32 -07001609
Dan Talayco4b2bee62010-07-20 14:10:05 -07001610 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1611 check_test_params=True)
1612 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001613 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001614
Dan Talaycof6e76c02012-03-23 10:56:12 -07001615class ModifyL2DstMC(BaseMatchCase):
1616 """
1617 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001618 """
1619 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001620 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001621 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001622 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001623 return
1624
Dan Talaycof6e76c02012-03-23 10:56:12 -07001625 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1626 check_test_params=True)
1627 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001628 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001629
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001630class ModifyL2DstIngress(BaseMatchCase):
1631 """
1632 Modify the L2 dest and send to the ingress port
1633 """
1634 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001635 sup_acts = self.supported_actions
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001636 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001637 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001638 return
1639
1640 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1641 check_test_params=True)
1642 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1643 action_list=acts, max_test=2, egr_count=0,
1644 ing_port=True)
1645
Dan Talaycod8ae7582012-03-23 12:24:56 -07001646class ModifyL2DstIngressMC(BaseMatchCase):
1647 """
1648 Modify the L2 dest and send to the ingress port
1649 """
1650 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001651 sup_acts = self.supported_actions
Dan Talaycod8ae7582012-03-23 12:24:56 -07001652 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1653 skip_message_emit(self, "ModifyL2dstMC test")
1654 return
1655
1656 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1657 check_test_params=True)
1658 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1659 action_list=acts, max_test=2, egr_count=-1,
1660 ing_port=True)
1661
Dan Talaycof6e76c02012-03-23 10:56:12 -07001662class ModifyL2SrcMC(BaseMatchCase):
1663 """
1664 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001665 """
1666 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001667 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001668 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001669 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001670 return
1671
Dan Talaycof6e76c02012-03-23 10:56:12 -07001672 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1673 check_test_params=True)
1674 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001675 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001676
1677class ModifyL2SrcDstMC(BaseMatchCase):
1678 """
1679 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001680 """
1681 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001682 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001683 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1684 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1685 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001686 return
1687
Dan Talaycof6e76c02012-03-23 10:56:12 -07001688 mod_fields = ['dl_dst', 'dl_src']
1689 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1690 check_test_params=True)
1691 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001692 action_list=acts, max_test=2, egr_count=-1)
1693
1694class ModifyL2DstVIDMC(BaseMatchCase):
1695 """
1696 Modify the L2 dest and send to 2 ports
1697 """
1698 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001699 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001700 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1701 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1702 skip_message_emit(self, "ModifyL2DstVIDMC test")
1703 return
1704
1705 mod_fields = ['dl_dst', 'dl_vlan']
1706 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1707 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1708 check_test_params=True)
1709 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1710 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001711
Dan Talaycofa6454f2012-04-05 10:04:13 -07001712class FlowToggle(BaseMatchCase):
1713 """
1714 Add flows to the table and modify them repeatedly
Dan Talaycof7c41312012-07-23 12:53:19 -07001715
1716 This is done by using only "add" flow messages. Since the check overlap
1717 flag is not set, the switch is supposed to modify the existing flow if
1718 the match already exists.
1719
1720 Would probably be better to exercise more of the flow modify commands
1721 (add, modify, delete +/- strict).
Dan Talaycofa6454f2012-04-05 10:04:13 -07001722 """
1723 def runTest(self):
Dan Talayco50be7672012-04-05 11:38:08 -07001724 flow_count = test_param_get(self.config, 'ft_flow_count', default=20)
1725 iter_count = test_param_get(self.config, 'ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001726
1727 pa_logger.info("Running flow toggle with %d flows, %d iterations" %
1728 (flow_count, iter_count))
1729 acts = []
1730 acts.append(action.action_output())
1731 acts.append(action.action_output())
1732
1733 of_ports = pa_port_map.keys()
1734 if len(of_ports) < 3:
1735 self.assertTrue(False, "Too few ports for test")
1736
1737 for idx in range(2):
1738 acts[idx].port = of_ports[idx]
1739
1740 flows = []
1741 flows.append([])
1742 flows.append([])
1743
Ed Swierk99a74de2012-08-22 06:40:54 -07001744 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_SRC |
1745 ofp.OFPFW_DL_DST)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001746 # Create up the flows in an array
1747 for toggle in range(2):
1748 for f_idx in range(flow_count):
1749 pkt = simple_tcp_packet(tcp_sport=f_idx)
1750 msg = message.flow_mod()
Ed Swierk99a74de2012-08-22 06:40:54 -07001751 match = packet_to_flow_match(self, pkt)
Shudong Zhou031373c2012-07-19 17:37:42 -07001752 match.in_port = of_ports[2]
Dan Talayco50be7672012-04-05 11:38:08 -07001753 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001754 msg.match = match
1755 msg.buffer_id = 0xffffffff
Dan Talaycof7c41312012-07-23 12:53:19 -07001756 msg.command = ofp.OFPFC_ADD
Dan Talaycofa6454f2012-04-05 10:04:13 -07001757 msg.actions.add(acts[toggle])
1758 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001759
1760 # Show two sample flows
1761 pa_logger.debug(flows[0][0].show())
1762 pa_logger.debug(flows[1][0].show())
1763
Dan Talaycofa6454f2012-04-05 10:04:13 -07001764 # Install the first set of flows
1765 for f_idx in range(flow_count):
1766 rv = self.controller.message_send(flows[0][f_idx])
1767 self.assertTrue(rv != -1, "Error installing flow %d" % f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001768 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycofa6454f2012-04-05 10:04:13 -07001769
1770 pa_logger.info("Installed %d flows" % flow_count)
1771
1772 # Repeatedly modify all the flows back and forth
1773 updates = 0
1774 # Report status about 5 times
1775 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001776 start = time.time()
1777 for iter_idx in range(iter_count):
1778 if not iter_idx % mod_val:
1779 pa_logger.info("Flow Toggle: iter %d of %d. " %
1780 (iter_idx, iter_count) +
1781 "%d updates in %d secs" %
1782 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001783 for toggle in range(2):
1784 t_idx = 1 - toggle
1785 for f_idx in range(flow_count):
1786 rv = self.controller.message_send(flows[t_idx][f_idx])
1787 updates += 1
1788 self.assertTrue(rv != -1, "Error modifying flow %d" %
1789 f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001790 self.assertEqual(do_barrier(self.controller), 0,
1791 "Barrier failed")
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001792
1793 end = time.time()
1794 divisor = end - start or (end - start + 1)
1795 pa_logger.info("Flow toggle: %d iterations" % iter_count)
1796 pa_logger.info(" %d flow mods in %d secs, %d mods/sec" %
1797 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001798
1799
Dan Talayco8a64e332012-03-28 14:53:20 -07001800# You can pick and choose these by commenting tests in or out
1801iter_classes = [
1802 basic.PacketIn,
1803 basic.PacketOut,
1804 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001805 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001806 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001807 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001808 AllWildcardMatch,
1809 AllWildcardMatchTagged,
1810 SingleWildcardMatch,
1811 SingleWildcardMatchTagged,
1812 ExactMatch,
1813 ExactMatchTagged,
1814 SingleWildcardMatch,
1815 ModifyL2Src,
1816 ModifyL2Dst,
1817 ModifyL2SrcMC,
1818 ModifyL2DstMC,
1819 ModifyL2SrcDstMC
1820 ]
1821
1822class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001823 """
1824 Iterate over a bunch of test cases
1825
1826 The cases come from the list above
1827 """
1828
Dan Talayco8a64e332012-03-28 14:53:20 -07001829 def runTest(self):
1830 count = test_param_get(self.config, 'iter_count', default=10)
1831 tests_done = 0
1832 pa_logger.info("Running iteration test " + str(count) + " times")
1833 start = time.time()
1834 last = start
1835 for idx in range(count):
1836 pa_logger.info("Iteration " + str(idx + 1))
1837 for cls in iter_classes:
1838 test = cls()
1839 test.inheritSetup(self)
1840 test.runTest()
1841 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001842 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001843 if time.time() - last > 60:
1844 last = time.time()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001845 pa_logger.info(
1846 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1847 (idx, count, tests_done, last - start) +
1848 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001849 stats = all_stats_get(self)
1850 last = time.time()
1851 pa_logger.info("\nIterCases ran %d tests in %d seconds." %
1852 (tests_done, last - start))
1853 pa_logger.info(" flows: %d. packets: %d. bytes: %d" %
1854 (stats["flows"], stats["packets"], stats["bytes"]))
1855 pa_logger.info(" active: %d. lookups: %d. matched %d." %
1856 (stats["active"], stats["lookups"], stats["matched"]))
1857
1858# Don't run by default
1859test_prio["IterCases"] = -1
Dan Talaycof6e76c02012-03-23 10:56:12 -07001860
Dan Talayco4b2bee62010-07-20 14:10:05 -07001861#@todo Need to implement tagged versions of the above tests
1862#
1863#@todo Implement a test case that strips tag 2, adds tag 3
1864# and modifies tag 4 to tag 5. Then verify (in addition) that
1865# tag 6 does not get modified.
1866
1867class MixedVLAN(BaseMatchCase):
1868 """
1869 Test mixture of VLAN tag actions
1870
1871 Strip tag 2 on port 1, send to port 2
1872 Add tag 3 on port 1, send to port 2
1873 Modify tag 4 to 5 on port 1, send to port 2
1874 All other traffic from port 1, send to port 3
1875 All traffic from port 2 sent to port 4
1876 Use exact matches with different packets for all mods
1877 Verify the following: (port, vid)
1878 (port 1, vid 2) => VLAN tag stripped, out port 2
1879 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1880 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1881 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1882 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1883 (port 2, no tag) => untagged packet out port 4
1884 (port 2, vid 2-6) => unmodified packet out port 4
1885
1886 Variation: Might try sending VID 5 to port 3 and check.
1887 If only VID 5 distinguishes pkt, this will fail on some platforms
1888 """
1889
1890test_prio["MixedVLAN"] = -1
Rich Lane8d6ab272012-09-23 18:06:20 -07001891
1892class MatchEach(basic.SimpleDataPlane):
1893 """
1894 Check that each match field is actually matched on.
1895 Installs two flows that differ in one field. The flow that should not
1896 match has a higher priority, so if that field is ignored during matching
1897 the packet will be sent out the wrong port.
1898
1899 TODO test UDP, ARP, ICMP, etc.
1900 """
1901 def runTest(self):
1902 of_ports = pa_port_map.keys()
1903 of_ports.sort()
1904 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1905
1906 delete_all_flows(self.controller, pa_logger)
1907
1908 pkt = simple_tcp_packet()
1909 ingress_port = of_ports[0]
1910 egress_port = of_ports[1]
1911
1912 def testField(field, mask):
1913 pa_logger.info("Testing field %s" % field)
1914
1915 def addFlow(matching, priority, output_port):
1916 match = packet_to_flow_match(self, pkt)
1917 self.assertTrue(match is not None, "Could not generate flow match from pkt")
1918 match.wildcards &= ~ofp.OFPFW_IN_PORT
1919 match.in_port = ingress_port
1920 if not matching:
1921 # Make sure flow doesn't match
1922 orig = getattr(match, field)
1923 if isinstance(orig, list):
1924 new = map(lambda a: ~a[0] & a[1], zip(orig, mask))
1925 else:
1926 new = ~orig & mask
1927 setattr(match, field, new)
1928 request = message.flow_mod()
1929 request.match = match
1930 request.buffer_id = 0xffffffff
1931 request.priority = priority
1932 act = action.action_output()
1933 act.port = output_port
1934 self.assertTrue(request.actions.add(act), "Could not add action")
1935 pa_logger.info("Inserting flow")
1936 self.controller.message_send(request)
1937
1938 # This flow should match.
1939 addFlow(matching=True, priority=0, output_port=egress_port)
1940 # This flow should not match, but it has a higher priority.
1941 addFlow(matching=False, priority=1, output_port=ofp.OFPP_IN_PORT)
1942
1943 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
1944
1945 pa_logger.info("Sending packet to dp port " + str(ingress_port))
1946 self.dataplane.send(ingress_port, str(pkt))
1947
1948 exp_pkt_arg = None
1949 exp_port = None
1950 if pa_config["relax"]:
1951 exp_pkt_arg = pkt
1952 exp_port = egress_port
1953
1954 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
1955 exp_pkt=exp_pkt_arg)
1956 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
1957 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
1958 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
1959 self.assertEqual(str(pkt), str(rcv_pkt), 'Response packet does not match send packet')
1960
1961 # TODO in_port
1962 testField("dl_src", [0xff]*6)
1963 testField("dl_dst", [0xff]*6)
1964 testField("dl_type", 0xffff)
1965 testField("dl_vlan", 0xfff)
1966 # TODO dl_vlan_pcp
1967 testField("nw_src", 0xffffffff)
1968 testField("nw_dst", 0xffffffff)
1969 testField("nw_tos", 0x3f)
1970 testField("nw_proto", 0xff)
1971 testField("tp_src", 0xffff)
1972 testField("tp_dst", 0xffff)
1973
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001974if __name__ == "__main__":
1975 print "Please run through oft script: ./oft --test_spec=basic"