blob: c045e5d2af5d5794ffd40e763143a0c0f2f6605b [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
31
32from testutils import *
33
34#@var port_map Local copy of the configuration map from OF port
35# numbers to OS interfaces
36pa_port_map = None
37#@var pa_logger Local logger object
38pa_logger = None
39#@var pa_config Local copy of global configuration data
40pa_config = None
41
Dan Talayco551befa2010-07-15 17:05:32 -070042# For test priority
43#@var test_prio Set test priority for local tests
44test_prio = {}
45
46WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
47 ofp.OFPFW_DL_VLAN,
48 ofp.OFPFW_DL_SRC,
49 ofp.OFPFW_DL_DST,
50 ofp.OFPFW_DL_TYPE,
51 ofp.OFPFW_NW_PROTO,
52 ofp.OFPFW_TP_SRC,
53 ofp.OFPFW_TP_DST,
54 0x3F << ofp.OFPFW_NW_SRC_SHIFT,
55 0x3F << ofp.OFPFW_NW_DST_SHIFT,
56 ofp.OFPFW_DL_VLAN_PCP,
57 ofp.OFPFW_NW_TOS]
58
59MODIFY_ACTION_VALUES = [ofp.OFPAT_SET_VLAN_VID,
60 ofp.OFPAT_SET_VLAN_PCP,
61 ofp.OFPAT_STRIP_VLAN,
62 ofp.OFPAT_SET_DL_SRC,
63 ofp.OFPAT_SET_DL_DST,
64 ofp.OFPAT_SET_NW_SRC,
65 ofp.OFPAT_SET_NW_DST,
66 ofp.OFPAT_SET_NW_TOS,
67 ofp.OFPAT_SET_TP_SRC,
68 ofp.OFPAT_SET_TP_DST]
69
70# Cache supported features to avoid transaction overhead
71cached_supported_actions = None
72
Dan Talayco21381562010-07-17 00:34:47 -070073TEST_VID_DEFAULT = 2
74
Dan Talayco5eba8442010-03-10 13:58:43 -080075def test_set_init(config):
76 """
77 Set up function for packet action test classes
78
79 @param config The configuration dictionary; see oft
80 """
81
Ed Swierk6ccbb072012-03-19 14:48:40 -070082 basic.test_set_init(config)
83
Dan Talayco5eba8442010-03-10 13:58:43 -080084 global pa_port_map
85 global pa_logger
86 global pa_config
87
88 pa_logger = logging.getLogger("pkt_act")
89 pa_logger.info("Initializing test set")
90 pa_port_map = config["port_map"]
91 pa_config = config
92
93class DirectPacket(basic.SimpleDataPlane):
94 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -070095 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -080096
97 Generate a packet
98 Generate and install a matching flow
99 Add action to direct the packet to an egress port
100 Send the packet to ingress dataplane port
101 Verify the packet is received at the egress port only
102 """
103 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700104 self.handleFlow()
105
106 def handleFlow(self, pkttype='TCP'):
Dan Talayco5eba8442010-03-10 13:58:43 -0800107 of_ports = pa_port_map.keys()
108 of_ports.sort()
109 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
110
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700111 if (pkttype == 'ICMP'):
112 pkt = simple_icmp_packet()
113 else:
114 pkt = simple_tcp_packet()
Dan Talayco5eba8442010-03-10 13:58:43 -0800115 match = parse.packet_to_flow_match(pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700116 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800117 self.assertTrue(match is not None,
118 "Could not generate flow match from pkt")
119 act = action.action_output()
120
121 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700122 rv = delete_all_flows(self.controller, pa_logger)
123 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700124
Dan Talayco5eba8442010-03-10 13:58:43 -0800125 ingress_port = of_ports[idx]
126 egress_port = of_ports[(idx + 1) % len(of_ports)]
127 pa_logger.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700128 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800129
130 match.in_port = ingress_port
131
132 request = message.flow_mod()
133 request.match = match
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700134
Dan Talayco5eba8442010-03-10 13:58:43 -0800135 request.buffer_id = 0xffffffff
136 act.port = egress_port
137 self.assertTrue(request.actions.add(act), "Could not add action")
138
139 pa_logger.info("Inserting flow")
140 rv = self.controller.message_send(request)
141 self.assertTrue(rv != -1, "Error installing flow mod")
142 do_barrier(self.controller)
143
144 pa_logger.info("Sending packet to dp port " +
145 str(ingress_port))
146 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700147
148 exp_pkt_arg = None
149 exp_port = None
150 if pa_config["relax"]:
151 exp_pkt_arg = pkt
152 exp_port = egress_port
153
154 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(timeout=1,
155 port_number=exp_port,
156 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800157 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700158 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800159 str(rcv_port))
160 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
161 self.assertEqual(str(pkt), str(rcv_pkt),
162 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700163
164class DirectPacketICMP(DirectPacket):
165 """
166 Send ICMP packet to single egress port
167
168 Generate a ICMP packet
169 Generate and install a matching flow
170 Add action to direct the packet to an egress port
171 Send the packet to ingress dataplane port
172 Verify the packet is received at the egress port only
173 Difference from DirectPacket test is that sent packet is ICMP
174 """
175 def runTest(self):
176 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700177
178class DirectTwoPorts(basic.SimpleDataPlane):
179 """
180 Send packet to two egress ports
181
182 Generate a packet
183 Generate and install a matching flow
184 Add action to direct the packet to two egress ports
185 Send the packet to ingress dataplane port
186 Verify the packet is received at the two egress ports
187 """
188 def runTest(self):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700189 of_ports = pa_port_map.keys()
190 of_ports.sort()
191 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
192
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700193 pkt = simple_tcp_packet()
194 match = parse.packet_to_flow_match(pkt)
195 match.wildcards &= ~ofp.OFPFW_IN_PORT
196 self.assertTrue(match is not None,
197 "Could not generate flow match from pkt")
198 act = action.action_output()
199
200 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700201 rv = delete_all_flows(self.controller, pa_logger)
202 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700203
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700204 ingress_port = of_ports[idx]
205 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
206 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
207 pa_logger.info("Ingress " + str(ingress_port) +
208 " to egress " + str(egress_port1) + " and " +
209 str(egress_port2))
210
211 match.in_port = ingress_port
212
213 request = message.flow_mod()
214 request.match = match
215 request.buffer_id = 0xffffffff
216 act.port = egress_port1
217 self.assertTrue(request.actions.add(act), "Could not add action1")
218 act.port = egress_port2
219 self.assertTrue(request.actions.add(act), "Could not add action2")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700220 # pa_logger.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700221
222 pa_logger.info("Inserting flow")
223 rv = self.controller.message_send(request)
224 self.assertTrue(rv != -1, "Error installing flow mod")
225 do_barrier(self.controller)
226
227 pa_logger.info("Sending packet to dp port " +
228 str(ingress_port))
229 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700230 yes_ports = set([egress_port1, egress_port2])
231 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700232
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700233 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700234 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700235
236class DirectMCNonIngress(basic.SimpleDataPlane):
237 """
238 Multicast to all non-ingress ports
239
240 Generate a packet
241 Generate and install a matching flow
242 Add action to direct the packet to all non-ingress ports
243 Send the packet to ingress dataplane port
244 Verify the packet is received at all non-ingress ports
245
246 Does not use the flood action
247 """
248 def runTest(self):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700249 of_ports = pa_port_map.keys()
250 of_ports.sort()
251 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
252
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700253 pkt = simple_tcp_packet()
254 match = parse.packet_to_flow_match(pkt)
255 match.wildcards &= ~ofp.OFPFW_IN_PORT
256 self.assertTrue(match is not None,
257 "Could not generate flow match from pkt")
258 act = action.action_output()
259
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700260 for ingress_port in of_ports:
261 rv = delete_all_flows(self.controller, pa_logger)
262 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700263
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700264 pa_logger.info("Ingress " + str(ingress_port) +
265 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700266 match.in_port = ingress_port
267
268 request = message.flow_mod()
269 request.match = match
270 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700271 for egress_port in of_ports:
272 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700273 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700274 act.port = egress_port
275 self.assertTrue(request.actions.add(act),
276 "Could not add output to " + str(egress_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700277 pa_logger.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700278
279 pa_logger.info("Inserting flow")
280 rv = self.controller.message_send(request)
281 self.assertTrue(rv != -1, "Error installing flow mod")
282 do_barrier(self.controller)
283
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700284 pa_logger.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700285 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700286 yes_ports = set(of_ports).difference([ingress_port])
287 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700288 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700289
Dan Talayco32fa6542010-05-11 15:54:08 -0700290
291class DirectMC(basic.SimpleDataPlane):
292 """
293 Multicast to all ports including ingress
294
295 Generate a packet
296 Generate and install a matching flow
297 Add action to direct the packet to all non-ingress ports
298 Send the packet to ingress dataplane port
299 Verify the packet is received at all ports
300
301 Does not use the flood action
302 """
303 def runTest(self):
Dan Talayco32fa6542010-05-11 15:54:08 -0700304 of_ports = pa_port_map.keys()
305 of_ports.sort()
306 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
307
Dan Talayco32fa6542010-05-11 15:54:08 -0700308 pkt = simple_tcp_packet()
309 match = parse.packet_to_flow_match(pkt)
310 match.wildcards &= ~ofp.OFPFW_IN_PORT
311 self.assertTrue(match is not None,
312 "Could not generate flow match from pkt")
313 act = action.action_output()
314
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700315 for ingress_port in of_ports:
316 rv = delete_all_flows(self.controller, pa_logger)
317 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700318
Dan Talayco32fa6542010-05-11 15:54:08 -0700319 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700320 match.in_port = ingress_port
321
322 request = message.flow_mod()
323 request.match = match
324 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700325 for egress_port in of_ports:
326 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700327 act.port = ofp.OFPP_IN_PORT
328 else:
329 act.port = egress_port
330 self.assertTrue(request.actions.add(act),
331 "Could not add output to " + str(egress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700332 # pa_logger.info(request.show())
333
334 pa_logger.info("Inserting flow")
335 rv = self.controller.message_send(request)
336 self.assertTrue(rv != -1, "Error installing flow mod")
337 do_barrier(self.controller)
338
339 pa_logger.info("Sending packet to dp port " + str(ingress_port))
340 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700341 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700342 pa_logger, pa_config)
Dan Talayco2e77a842010-05-12 15:39:46 -0700343
344class Flood(basic.SimpleDataPlane):
345 """
346 Flood to all ports except ingress
347
348 Generate a packet
349 Generate and install a matching flow
350 Add action to flood the packet
351 Send the packet to ingress dataplane port
352 Verify the packet is received at all other ports
353 """
354 def runTest(self):
Dan Talayco2e77a842010-05-12 15:39:46 -0700355 of_ports = pa_port_map.keys()
356 of_ports.sort()
357 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
358
359 pkt = simple_tcp_packet()
360 match = parse.packet_to_flow_match(pkt)
361 match.wildcards &= ~ofp.OFPFW_IN_PORT
362 self.assertTrue(match is not None,
363 "Could not generate flow match from pkt")
364 act = action.action_output()
365
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700366 for ingress_port in of_ports:
367 rv = delete_all_flows(self.controller, pa_logger)
368 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700369
Dan Talayco2e77a842010-05-12 15:39:46 -0700370 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700371 match.in_port = ingress_port
372
373 request = message.flow_mod()
374 request.match = match
375 request.buffer_id = 0xffffffff
376 act.port = ofp.OFPP_FLOOD
377 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700378 "Could not add flood port action")
Dan Talayco32fa6542010-05-11 15:54:08 -0700379 pa_logger.info(request.show())
380
381 pa_logger.info("Inserting flow")
382 rv = self.controller.message_send(request)
383 self.assertTrue(rv != -1, "Error installing flow mod")
384 do_barrier(self.controller)
385
386 pa_logger.info("Sending packet to dp port " + str(ingress_port))
387 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700388 yes_ports = set(of_ports).difference([ingress_port])
389 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700390 self, pa_logger, pa_config)
Dan Talayco3be5b062010-05-12 15:46:21 -0700391
Dan Talayco3be5b062010-05-12 15:46:21 -0700392class FloodPlusIngress(basic.SimpleDataPlane):
393 """
394 Flood to all ports plus send to ingress port
395
396 Generate a packet
397 Generate and install a matching flow
398 Add action to flood the packet
399 Add action to send to ingress port
400 Send the packet to ingress dataplane port
401 Verify the packet is received at all other ports
402 """
403 def runTest(self):
Dan Talayco3be5b062010-05-12 15:46:21 -0700404 of_ports = pa_port_map.keys()
405 of_ports.sort()
406 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
407
408 pkt = simple_tcp_packet()
409 match = parse.packet_to_flow_match(pkt)
410 match.wildcards &= ~ofp.OFPFW_IN_PORT
411 self.assertTrue(match is not None,
412 "Could not generate flow match from pkt")
413 act = action.action_output()
414
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700415 for ingress_port in of_ports:
416 rv = delete_all_flows(self.controller, pa_logger)
417 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700418
Dan Talayco3be5b062010-05-12 15:46:21 -0700419 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700420 match.in_port = ingress_port
421
422 request = message.flow_mod()
423 request.match = match
424 request.buffer_id = 0xffffffff
425 act.port = ofp.OFPP_FLOOD
426 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700427 "Could not add flood port action")
428 act.port = ofp.OFPP_IN_PORT
429 self.assertTrue(request.actions.add(act),
430 "Could not add ingress port for output")
431 pa_logger.info(request.show())
432
433 pa_logger.info("Inserting flow")
434 rv = self.controller.message_send(request)
435 self.assertTrue(rv != -1, "Error installing flow mod")
436 do_barrier(self.controller)
437
438 pa_logger.info("Sending packet to dp port " + str(ingress_port))
439 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700440 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700441 pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700442
443class All(basic.SimpleDataPlane):
444 """
445 Send to OFPP_ALL port
446
447 Generate a packet
448 Generate and install a matching flow
449 Add action to forward to OFPP_ALL
450 Send the packet to ingress dataplane port
451 Verify the packet is received at all other ports
452 """
453 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700454 of_ports = pa_port_map.keys()
455 of_ports.sort()
456 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
457
458 pkt = simple_tcp_packet()
459 match = parse.packet_to_flow_match(pkt)
460 match.wildcards &= ~ofp.OFPFW_IN_PORT
461 self.assertTrue(match is not None,
462 "Could not generate flow match from pkt")
463 act = action.action_output()
464
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700465 for ingress_port in of_ports:
466 rv = delete_all_flows(self.controller, pa_logger)
467 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700468
Dan Talayco4aa13122010-05-12 15:54:44 -0700469 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700470 match.in_port = ingress_port
471
472 request = message.flow_mod()
473 request.match = match
474 request.buffer_id = 0xffffffff
475 act.port = ofp.OFPP_ALL
476 self.assertTrue(request.actions.add(act),
477 "Could not add ALL port action")
478 pa_logger.info(request.show())
479
480 pa_logger.info("Inserting flow")
481 rv = self.controller.message_send(request)
482 self.assertTrue(rv != -1, "Error installing flow mod")
483 do_barrier(self.controller)
484
485 pa_logger.info("Sending packet to dp port " + str(ingress_port))
486 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700487 yes_ports = set(of_ports).difference([ingress_port])
488 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700489 self, pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700490
491class AllPlusIngress(basic.SimpleDataPlane):
492 """
493 Send to OFPP_ALL port and ingress port
494
495 Generate a packet
496 Generate and install a matching flow
497 Add action to forward to OFPP_ALL
498 Add action to forward to ingress port
499 Send the packet to ingress dataplane port
500 Verify the packet is received at all other ports
501 """
502 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700503 of_ports = pa_port_map.keys()
504 of_ports.sort()
505 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
506
507 pkt = simple_tcp_packet()
508 match = parse.packet_to_flow_match(pkt)
509 match.wildcards &= ~ofp.OFPFW_IN_PORT
510 self.assertTrue(match is not None,
511 "Could not generate flow match from pkt")
512 act = action.action_output()
513
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700514 for ingress_port in of_ports:
515 rv = delete_all_flows(self.controller, pa_logger)
516 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700517
Dan Talayco4aa13122010-05-12 15:54:44 -0700518 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700519 match.in_port = ingress_port
520
521 request = message.flow_mod()
522 request.match = match
523 request.buffer_id = 0xffffffff
524 act.port = ofp.OFPP_ALL
525 self.assertTrue(request.actions.add(act),
526 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700527 act.port = ofp.OFPP_IN_PORT
528 self.assertTrue(request.actions.add(act),
529 "Could not add ingress port for output")
530 pa_logger.info(request.show())
531
532 pa_logger.info("Inserting flow")
533 rv = self.controller.message_send(request)
534 self.assertTrue(rv != -1, "Error installing flow mod")
535 do_barrier(self.controller)
536
537 pa_logger.info("Sending packet to dp port " + str(ingress_port))
538 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700539 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700540 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700541
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700542class FloodMinusPort(basic.SimpleDataPlane):
543 """
544 Config port with No_Flood and test Flood action
545
546 Generate a packet
547 Generate a matching flow
548 Add action to forward to OFPP_ALL
549 Set port to no-flood
550 Send the packet to ingress dataplane port
551 Verify the packet is received at all other ports except
552 the ingress port and the no_flood port
553 """
554 def runTest(self):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700555 of_ports = pa_port_map.keys()
556 of_ports.sort()
557 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
558
559 pkt = simple_tcp_packet()
560 match = parse.packet_to_flow_match(pkt)
561 match.wildcards &= ~ofp.OFPFW_IN_PORT
562 self.assertTrue(match is not None,
563 "Could not generate flow match from pkt")
564 act = action.action_output()
565
566 for idx in range(len(of_ports)):
567 rv = delete_all_flows(self.controller, pa_logger)
568 self.assertEqual(rv, 0, "Failed to delete all flows")
569
570 ingress_port = of_ports[idx]
571 no_flood_idx = (idx + 1) % len(of_ports)
572 no_flood_port = of_ports[no_flood_idx]
573 rv = port_config_set(self.controller, no_flood_port,
574 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
575 pa_logger)
576 self.assertEqual(rv, 0, "Failed to set port config")
577
578 match.in_port = ingress_port
579
580 request = message.flow_mod()
581 request.match = match
582 request.buffer_id = 0xffffffff
583 act.port = ofp.OFPP_FLOOD
584 self.assertTrue(request.actions.add(act),
585 "Could not add flood port action")
586 pa_logger.info(request.show())
587
588 pa_logger.info("Inserting flow")
589 rv = self.controller.message_send(request)
590 self.assertTrue(rv != -1, "Error installing flow mod")
591 do_barrier(self.controller)
592
593 pa_logger.info("Sending packet to dp port " + str(ingress_port))
594 pa_logger.info("No flood port is " + str(no_flood_port))
595 self.dataplane.send(ingress_port, str(pkt))
596 no_ports = set([ingress_port, no_flood_port])
597 yes_ports = set(of_ports).difference(no_ports)
598 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700599 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700600
601 # Turn no flood off again
602 rv = port_config_set(self.controller, no_flood_port,
603 0, ofp.OFPPC_NO_FLOOD, pa_logger)
604 self.assertEqual(rv, 0, "Failed to reset port config")
605
606 #@todo Should check no other packets received
607
Dan Talayco21381562010-07-17 00:34:47 -0700608
609
Dan Talayco551befa2010-07-15 17:05:32 -0700610################################################################
611
612class BaseMatchCase(basic.SimpleDataPlane):
613 def setUp(self):
614 basic.SimpleDataPlane.setUp(self)
615 self.logger = pa_logger
616 def runTest(self):
617 self.logger.info("BaseMatchCase")
618
619class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700620 """
Dan Talayco551befa2010-07-15 17:05:32 -0700621 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700622
623 Generate a packet
624 Generate and install a matching flow without wildcard mask
625 Add action to forward to a port
626 Send the packet to the port
627 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700628 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700629
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700630 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700631 flow_match_test(self, pa_port_map)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700632
Dan Talayco551befa2010-07-15 17:05:32 -0700633class ExactMatchTagged(BaseMatchCase):
634 """
635 Exact match for all port pairs with tagged pkts
636 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700637
Dan Talayco551befa2010-07-15 17:05:32 -0700638 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700639 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700640 flow_match_test(self, pa_port_map, dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700641
Dan Talayco551befa2010-07-15 17:05:32 -0700642class ExactMatchTaggedMany(BaseMatchCase):
643 """
644 ExactMatchTagged with many VLANS
645 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700646
Dan Talayco551befa2010-07-15 17:05:32 -0700647 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700648 for vid in range(2,100,10):
Dan Talayco551befa2010-07-15 17:05:32 -0700649 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
650 for vid in range(100,4000,389):
651 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
652 flow_match_test(self, pa_port_map, dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700653
Dan Talayco551befa2010-07-15 17:05:32 -0700654# Don't run by default
655test_prio["ExactMatchTaggedMany"] = -1
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700656
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700657
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700658class SingleWildcardMatchPriority(BaseMatchCase):
659
660 def runTest(self):
661 self.pkt = simple_tcp_packet()
662 self.flowMsgs = {}
663
664 of_ports = pa_port_map.keys()
665 of_ports.sort()
666
667 # Delete the initial flow table
668 rc = delete_all_flows(self.controller, self.logger)
669 self.assertEqual(rc, 0, "Failed to delete all flows")
670 do_barrier(self.controller)
671
672 # Run several combinations, each at lower priority settings.
673 # At the end of each call to runPrioFlows(), the table should
674 # be empty. If its not, we'll catch it as the priorities decreases
675 portA = of_ports[0]
676 portB = of_ports[1]
677 portC = of_ports[2]
678
679 # TODO -- these priority numbers should be validated somehow?
680 self.runPrioFlows(portA, portB, portC, 1000, 999)
681 self.runPrioFlows(portB, portC, portA, 998, 997)
682 self.runPrioFlows(portC, portA, portB, 996, 995)
683 self.runPrioFlows(portA, portC, portB, 994, 993)
684
685
686
687 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower):
688
689 # Sanity check flow at lower priority from pA to pB
690 self.logger.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
691 % (portA, portB, portC, prioHigher, prioLower))
692
693 self.installFlow(prioLower, portA, portB)
694 self.verifyFlow(portA, portB)
695 self.removeFlow(prioLower)
696 # Sanity check flow at lower priority from pA to pC
697 self.installFlow(prioLower, portA, portC)
698 self.verifyFlow(portA, portC)
699 self.removeFlow(prioLower)
700
701 # Install and verify pA->pB @ prioLower
702 self.installFlow(prioLower, portA, portB)
703 self.verifyFlow(portA, portB)
704
705 # Install and verify pA->pC @ prioHigher, should override pA->pB
706 self.installFlow(prioHigher, portA, portC)
707 self.verifyFlow(portA, portC)
708 # remove pA->pC
709 self.removeFlow(prioHigher)
710
711 # Old flow pA -> pB @ prioLower should still be active
712 self.verifyFlow(portA, portB)
713 self.removeFlow(prioLower)
714
715 # Table should be empty at this point, leave it alone as
716 # an assumption for future test runs
717
718
719
720 def installFlow(self, prio, inp, egp, clearTable=False):
721 request = flow_msg_create(self, self.pkt, ing_port=inp,
722 wildcards=ofp.OFPFW_DL_SRC,
723 egr_ports=egp)
724 request.priority = prio
725 flow_msg_install(self, request, clear_table=clearTable)
726 self.flowMsgs[prio] = request
727
728 def removeFlow(self, prio):
729 if self.flowMsgs.has_key(prio):
730 msg = self.flowMsgs[prio]
731 msg.command = ofp.OFPFC_DELETE_STRICT
732 # This *must* be set for DELETE
733 msg.out_port = ofp.OFPP_NONE
734 self.controller.message_send(msg)
735 do_barrier(self.controller)
736
737
738 def verifyFlow(self, inp, egp):
739 self.logger.info("Pkt match test: " + str(inp) +
740 " to " + str(egp))
741 self.logger.debug("Send packet: " + str(inp) + " to "
742 + str(egp))
743 self.dataplane.send(inp, str(self.pkt))
744 receive_pkt_verify(self, egp, self.pkt, inp)
745
746
747
Dan Talayco551befa2010-07-15 17:05:32 -0700748class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700749 """
750 Exercise wildcard matching for all ports
751
752 Generate a packet
753 Generate and install a matching flow with wildcard mask
754 Add action to forward to a port
755 Send the packet to the port
756 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700757 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700758 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700759 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700760 for wc in WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -0700761 if wc & ofp.OFPFW_DL_VLAN:
762 dl_vlan = 0
763 else:
764 dl_vlan = -1
765 flow_match_test(self, pa_port_map, wildcards=wc,
766 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700767
Dan Talayco551befa2010-07-15 17:05:32 -0700768class SingleWildcardMatchTagged(BaseMatchCase):
769 """
770 SingleWildcardMatch with tagged packets
771 """
772 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700773 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700774 for wc in WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700775 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -0700776 max_test=10)
777
778class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700779 """
Dan Talayco80b54ed2010-07-13 09:48:35 -0700780 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700781
782 Generate a packet
783 Generate and install a matching flow with wildcard all except one filed
784 Add action to forward to a port
785 Send the packet to the port
786 Verify the packet is received at all other ports (one port at a time)
787 Verify flow_expiration message is correct when command option is set
788 """
789 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700790 for wc in WILDCARD_VALUES:
791 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco4431d542012-03-21 16:42:16 -0700792 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
793 dl_vlan = 0
794 else:
795 dl_vlan = -1
796 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
797 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700798
Dan Talayco551befa2010-07-15 17:05:32 -0700799class AllExceptOneWildcardMatchTagged(BaseMatchCase):
800 """
801 Match one field with tagged packets
802 """
803 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700804 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700805 for wc in WILDCARD_VALUES:
806 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco21381562010-07-17 00:34:47 -0700807 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
808 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -0700809
810class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700811 """
812 Create Wildcard-all flow and exercise for all ports
813
814 Generate a packet
815 Generate and install a matching flow with wildcard-all
816 Add action to forward to a port
817 Send the packet to the port
818 Verify the packet is received at all other ports (one port at a time)
819 Verify flow_expiration message is correct when command option is set
820 """
821 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700822 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700823
Dan Talayco551befa2010-07-15 17:05:32 -0700824class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700825 """
Dan Talayco551befa2010-07-15 17:05:32 -0700826 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700827 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700828 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700829 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700830 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
831 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700832
Dan Talaycoba3745c2010-07-21 21:51:08 -0700833
Dan Talayco551befa2010-07-15 17:05:32 -0700834class AddVLANTag(BaseMatchCase):
835 """
836 Add a VLAN tag to an untagged packet
837 """
838 def runTest(self):
839 new_vid = 2
840 sup_acts = supported_actions_get(self)
841 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700842 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -0700843 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700844
Dan Talayco551befa2010-07-15 17:05:32 -0700845 len = 100
846 len_w_vid = 104
847 pkt = simple_tcp_packet(pktlen=len)
848 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
849 dl_vlan=new_vid)
850 vid_act = action.action_set_vlan_vid()
851 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700852
Dan Talayco551befa2010-07-15 17:05:32 -0700853 flow_match_test(self, pa_port_map, pkt=pkt,
854 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700855
Dan Talayco551befa2010-07-15 17:05:32 -0700856class PacketOnly(basic.DataPlaneOnly):
857 """
858 Just send a packet thru the switch
859 """
860 def runTest(self):
861 pkt = simple_tcp_packet()
862 of_ports = pa_port_map.keys()
863 of_ports.sort()
864 ing_port = of_ports[0]
865 pa_logger.info("Sending packet to " + str(ing_port))
866 pa_logger.debug("Data: " + str(pkt).encode('hex'))
867 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700868
Dan Talayco551befa2010-07-15 17:05:32 -0700869class PacketOnlyTagged(basic.DataPlaneOnly):
870 """
871 Just send a packet thru the switch
872 """
873 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700874 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700875 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
876 of_ports = pa_port_map.keys()
877 of_ports.sort()
878 ing_port = of_ports[0]
879 pa_logger.info("Sending packet to " + str(ing_port))
880 pa_logger.debug("Data: " + str(pkt).encode('hex'))
881 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700882
Dan Talayco551befa2010-07-15 17:05:32 -0700883test_prio["PacketOnly"] = -1
884test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700885
Dan Talayco551befa2010-07-15 17:05:32 -0700886class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700887 """
888 Modify the VLAN ID in the VLAN tag of a tagged packet
889 """
Dan Talayco551befa2010-07-15 17:05:32 -0700890 def runTest(self):
891 old_vid = 2
892 new_vid = 3
893 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700894 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700895 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700896 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700897
Dan Talayco551befa2010-07-15 17:05:32 -0700898 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
899 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
900 vid_act = action.action_set_vlan_vid()
901 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700902
Dan Talayco551befa2010-07-15 17:05:32 -0700903 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
904 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700905
Dan Talayco551befa2010-07-15 17:05:32 -0700906class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700907 """
908 Strip the VLAN tag from a tagged packet
909 """
Dan Talayco551befa2010-07-15 17:05:32 -0700910 def runTest(self):
911 old_vid = 2
912 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700913 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700914 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700915 return
Dan Talaycof36f1082010-07-13 13:57:17 -0700916
Dan Talayco551befa2010-07-15 17:05:32 -0700917 len_w_vid = 104
918 len = 100
919 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
920 dl_vlan=old_vid)
921 exp_pkt = simple_tcp_packet(pktlen=len)
922 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700923
Dan Talayco551befa2010-07-15 17:05:32 -0700924 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
925 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700926
Dan Talayco4b2bee62010-07-20 14:10:05 -0700927def init_pkt_args():
928 """
929 Pass back a dictionary with default packet arguments
930 """
931 args = {}
932 args["dl_src"] = '00:23:45:67:89:AB'
933
934 dl_vlan_enable=False
935 dl_vlan=-1
936 if pa_config["test-params"]["vid"]:
937 dl_vlan_enable=True
938 dl_vlan = pa_config["test-params"]["vid"]
939
940# Unpack operator is ** on a dictionary
941
942 return args
943
Dan Talayco551befa2010-07-15 17:05:32 -0700944class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700945 """
946 Modify the source MAC address (TP1)
947 """
Dan Talayco551befa2010-07-15 17:05:32 -0700948 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700949 sup_acts = supported_actions_get(self)
950 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700951 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700952 return
953
954 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
955 check_test_params=True)
956 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
957 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700958
Dan Talayco551befa2010-07-15 17:05:32 -0700959class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700960 """
961 Modify the dest MAC address (TP1)
962 """
Dan Talayco551befa2010-07-15 17:05:32 -0700963 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700964 sup_acts = supported_actions_get(self)
965 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700966 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700967 return
968
969 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
970 check_test_params=True)
971 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
972 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700973
Dan Talayco551befa2010-07-15 17:05:32 -0700974class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700975 """
976 Modify the source IP address of an IP packet (TP1)
977 """
Dan Talayco551befa2010-07-15 17:05:32 -0700978 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700979 sup_acts = supported_actions_get(self)
980 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700981 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700982 return
983
984 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
985 check_test_params=True)
986 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
987 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700988
Dan Talayco551befa2010-07-15 17:05:32 -0700989class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700990 """
991 Modify the dest IP address of an IP packet (TP1)
992 """
Dan Talayco551befa2010-07-15 17:05:32 -0700993 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700994 sup_acts = supported_actions_get(self)
995 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700996 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700997 return
998
999 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1000 check_test_params=True)
1001 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1002 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001003
1004class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001005 """
1006 Modify the source TCP port of a TCP packet (TP1)
1007 """
Dan Talayco551befa2010-07-15 17:05:32 -07001008 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001009 sup_acts = supported_actions_get(self)
1010 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001011 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001012 return
1013
1014 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1015 check_test_params=True)
1016 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1017 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001018
1019class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001020 """
1021 Modify the dest TCP port of a TCP packet (TP1)
1022 """
Dan Talayco551befa2010-07-15 17:05:32 -07001023 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001024 sup_acts = supported_actions_get(self)
1025 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001026 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001027 return
1028
1029 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1030 check_test_params=True)
1031 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1032 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001033
1034class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001035 """
1036 Modify the IP type of service of an IP packet (TP1)
1037 """
Dan Talayco551befa2010-07-15 17:05:32 -07001038 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001039 sup_acts = supported_actions_get(self)
1040 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001041 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001042 return
Dan Talayco551befa2010-07-15 17:05:32 -07001043
Dan Talayco4b2bee62010-07-20 14:10:05 -07001044 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1045 check_test_params=True)
1046 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001047 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001048
Dan Talaycof6e76c02012-03-23 10:56:12 -07001049class ModifyL2DstMC(BaseMatchCase):
1050 """
1051 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001052 """
1053 def runTest(self):
1054 sup_acts = supported_actions_get(self)
1055 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001056 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001057 return
1058
Dan Talaycof6e76c02012-03-23 10:56:12 -07001059 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1060 check_test_params=True)
1061 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001062 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001063
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001064class ModifyL2DstIngress(BaseMatchCase):
1065 """
1066 Modify the L2 dest and send to the ingress port
1067 """
1068 def runTest(self):
1069 sup_acts = supported_actions_get(self)
1070 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1071 skip_message_emit(self, "ModifyL2dstMC test")
1072 return
1073
1074 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1075 check_test_params=True)
1076 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1077 action_list=acts, max_test=2, egr_count=0,
1078 ing_port=True)
1079
Dan Talaycod8ae7582012-03-23 12:24:56 -07001080class ModifyL2DstIngressMC(BaseMatchCase):
1081 """
1082 Modify the L2 dest and send to the ingress port
1083 """
1084 def runTest(self):
1085 sup_acts = supported_actions_get(self)
1086 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1087 skip_message_emit(self, "ModifyL2dstMC test")
1088 return
1089
1090 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1091 check_test_params=True)
1092 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1093 action_list=acts, max_test=2, egr_count=-1,
1094 ing_port=True)
1095
Dan Talaycof6e76c02012-03-23 10:56:12 -07001096class ModifyL2SrcMC(BaseMatchCase):
1097 """
1098 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001099 """
1100 def runTest(self):
1101 sup_acts = supported_actions_get(self)
1102 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001103 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001104 return
1105
Dan Talaycof6e76c02012-03-23 10:56:12 -07001106 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1107 check_test_params=True)
1108 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001109 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001110
1111class ModifyL2SrcDstMC(BaseMatchCase):
1112 """
1113 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001114 """
1115 def runTest(self):
1116 sup_acts = supported_actions_get(self)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001117 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1118 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1119 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001120 return
1121
Dan Talaycof6e76c02012-03-23 10:56:12 -07001122 mod_fields = ['dl_dst', 'dl_src']
1123 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1124 check_test_params=True)
1125 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001126 action_list=acts, max_test=2, egr_count=-1)
1127
1128class ModifyL2DstVIDMC(BaseMatchCase):
1129 """
1130 Modify the L2 dest and send to 2 ports
1131 """
1132 def runTest(self):
1133 sup_acts = supported_actions_get(self)
1134 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1135 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1136 skip_message_emit(self, "ModifyL2DstVIDMC test")
1137 return
1138
1139 mod_fields = ['dl_dst', 'dl_vlan']
1140 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1141 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1142 check_test_params=True)
1143 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1144 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001145
1146
Dan Talayco4b2bee62010-07-20 14:10:05 -07001147#@todo Need to implement tagged versions of the above tests
1148#
1149#@todo Implement a test case that strips tag 2, adds tag 3
1150# and modifies tag 4 to tag 5. Then verify (in addition) that
1151# tag 6 does not get modified.
1152
1153class MixedVLAN(BaseMatchCase):
1154 """
1155 Test mixture of VLAN tag actions
1156
1157 Strip tag 2 on port 1, send to port 2
1158 Add tag 3 on port 1, send to port 2
1159 Modify tag 4 to 5 on port 1, send to port 2
1160 All other traffic from port 1, send to port 3
1161 All traffic from port 2 sent to port 4
1162 Use exact matches with different packets for all mods
1163 Verify the following: (port, vid)
1164 (port 1, vid 2) => VLAN tag stripped, out port 2
1165 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1166 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1167 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1168 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1169 (port 2, no tag) => untagged packet out port 4
1170 (port 2, vid 2-6) => unmodified packet out port 4
1171
1172 Variation: Might try sending VID 5 to port 3 and check.
1173 If only VID 5 distinguishes pkt, this will fail on some platforms
1174 """
1175
1176test_prio["MixedVLAN"] = -1
1177
Dan Talayco551befa2010-07-15 17:05:32 -07001178def supported_actions_get(parent, use_cache=True):
1179 """
1180 Get the bitmap of supported actions from the switch
1181 If use_cache is false, the cached value will be updated
1182 """
1183 global cached_supported_actions
1184 if cached_supported_actions is None or not use_cache:
1185 request = message.features_request()
1186 (reply, pkt) = parent.controller.transact(request, timeout=2)
1187 parent.assertTrue(reply is not None, "Did not get response to ftr req")
1188 cached_supported_actions = reply.actions
1189 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
1190
1191 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -07001192
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001193if __name__ == "__main__":
1194 print "Please run through oft script: ./oft --test_spec=basic"