blob: 0bd21dc1b04e5c28a24e628d00671a253f47da1c [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
134 request.buffer_id = 0xffffffff
135 act.port = egress_port
136 self.assertTrue(request.actions.add(act), "Could not add action")
137
138 pa_logger.info("Inserting flow")
139 rv = self.controller.message_send(request)
140 self.assertTrue(rv != -1, "Error installing flow mod")
141 do_barrier(self.controller)
142
143 pa_logger.info("Sending packet to dp port " +
144 str(ingress_port))
145 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700146
147 exp_pkt_arg = None
148 exp_port = None
149 if pa_config["relax"]:
150 exp_pkt_arg = pkt
151 exp_port = egress_port
152
153 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(timeout=1,
154 port_number=exp_port,
155 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800156 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700157 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800158 str(rcv_port))
159 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
160 self.assertEqual(str(pkt), str(rcv_pkt),
161 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700162
163class DirectPacketICMP(DirectPacket):
164 """
165 Send ICMP packet to single egress port
166
167 Generate a ICMP packet
168 Generate and install a matching flow
169 Add action to direct the packet to an egress port
170 Send the packet to ingress dataplane port
171 Verify the packet is received at the egress port only
172 Difference from DirectPacket test is that sent packet is ICMP
173 """
174 def runTest(self):
175 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700176
177class DirectTwoPorts(basic.SimpleDataPlane):
178 """
179 Send packet to two egress ports
180
181 Generate a packet
182 Generate and install a matching flow
183 Add action to direct the packet to two egress ports
184 Send the packet to ingress dataplane port
185 Verify the packet is received at the two egress ports
186 """
187 def runTest(self):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700188 of_ports = pa_port_map.keys()
189 of_ports.sort()
190 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
191
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700192 pkt = simple_tcp_packet()
193 match = parse.packet_to_flow_match(pkt)
194 match.wildcards &= ~ofp.OFPFW_IN_PORT
195 self.assertTrue(match is not None,
196 "Could not generate flow match from pkt")
197 act = action.action_output()
198
199 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700200 rv = delete_all_flows(self.controller, pa_logger)
201 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700202
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700203 ingress_port = of_ports[idx]
204 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
205 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
206 pa_logger.info("Ingress " + str(ingress_port) +
207 " to egress " + str(egress_port1) + " and " +
208 str(egress_port2))
209
210 match.in_port = ingress_port
211
212 request = message.flow_mod()
213 request.match = match
214 request.buffer_id = 0xffffffff
215 act.port = egress_port1
216 self.assertTrue(request.actions.add(act), "Could not add action1")
217 act.port = egress_port2
218 self.assertTrue(request.actions.add(act), "Could not add action2")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700219 # pa_logger.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700220
221 pa_logger.info("Inserting flow")
222 rv = self.controller.message_send(request)
223 self.assertTrue(rv != -1, "Error installing flow mod")
224 do_barrier(self.controller)
225
226 pa_logger.info("Sending packet to dp port " +
227 str(ingress_port))
228 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700229 yes_ports = set([egress_port1, egress_port2])
230 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700231
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700232 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700233 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700234
235class DirectMCNonIngress(basic.SimpleDataPlane):
236 """
237 Multicast to all non-ingress ports
238
239 Generate a packet
240 Generate and install a matching flow
241 Add action to direct the packet to all non-ingress ports
242 Send the packet to ingress dataplane port
243 Verify the packet is received at all non-ingress ports
244
245 Does not use the flood action
246 """
247 def runTest(self):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700248 of_ports = pa_port_map.keys()
249 of_ports.sort()
250 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
251
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700252 pkt = simple_tcp_packet()
253 match = parse.packet_to_flow_match(pkt)
254 match.wildcards &= ~ofp.OFPFW_IN_PORT
255 self.assertTrue(match is not None,
256 "Could not generate flow match from pkt")
257 act = action.action_output()
258
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700259 for ingress_port in of_ports:
260 rv = delete_all_flows(self.controller, pa_logger)
261 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700262
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700263 pa_logger.info("Ingress " + str(ingress_port) +
264 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700265 match.in_port = ingress_port
266
267 request = message.flow_mod()
268 request.match = match
269 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700270 for egress_port in of_ports:
271 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700272 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700273 act.port = egress_port
274 self.assertTrue(request.actions.add(act),
275 "Could not add output to " + str(egress_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700276 pa_logger.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700277
278 pa_logger.info("Inserting flow")
279 rv = self.controller.message_send(request)
280 self.assertTrue(rv != -1, "Error installing flow mod")
281 do_barrier(self.controller)
282
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700283 pa_logger.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700284 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700285 yes_ports = set(of_ports).difference([ingress_port])
286 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700287 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700288
Dan Talayco32fa6542010-05-11 15:54:08 -0700289
290class DirectMC(basic.SimpleDataPlane):
291 """
292 Multicast to all ports including ingress
293
294 Generate a packet
295 Generate and install a matching flow
296 Add action to direct the packet to all non-ingress ports
297 Send the packet to ingress dataplane port
298 Verify the packet is received at all ports
299
300 Does not use the flood action
301 """
302 def runTest(self):
Dan Talayco32fa6542010-05-11 15:54:08 -0700303 of_ports = pa_port_map.keys()
304 of_ports.sort()
305 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
306
Dan Talayco32fa6542010-05-11 15:54:08 -0700307 pkt = simple_tcp_packet()
308 match = parse.packet_to_flow_match(pkt)
309 match.wildcards &= ~ofp.OFPFW_IN_PORT
310 self.assertTrue(match is not None,
311 "Could not generate flow match from pkt")
312 act = action.action_output()
313
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700314 for ingress_port in of_ports:
315 rv = delete_all_flows(self.controller, pa_logger)
316 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700317
Dan Talayco32fa6542010-05-11 15:54:08 -0700318 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700319 match.in_port = ingress_port
320
321 request = message.flow_mod()
322 request.match = match
323 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700324 for egress_port in of_ports:
325 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700326 act.port = ofp.OFPP_IN_PORT
327 else:
328 act.port = egress_port
329 self.assertTrue(request.actions.add(act),
330 "Could not add output to " + str(egress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700331 # pa_logger.info(request.show())
332
333 pa_logger.info("Inserting flow")
334 rv = self.controller.message_send(request)
335 self.assertTrue(rv != -1, "Error installing flow mod")
336 do_barrier(self.controller)
337
338 pa_logger.info("Sending packet to dp port " + str(ingress_port))
339 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700340 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700341 pa_logger, pa_config)
Dan Talayco2e77a842010-05-12 15:39:46 -0700342
343class Flood(basic.SimpleDataPlane):
344 """
345 Flood to all ports except ingress
346
347 Generate a packet
348 Generate and install a matching flow
349 Add action to flood the packet
350 Send the packet to ingress dataplane port
351 Verify the packet is received at all other ports
352 """
353 def runTest(self):
Dan Talayco2e77a842010-05-12 15:39:46 -0700354 of_ports = pa_port_map.keys()
355 of_ports.sort()
356 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
357
358 pkt = simple_tcp_packet()
359 match = parse.packet_to_flow_match(pkt)
360 match.wildcards &= ~ofp.OFPFW_IN_PORT
361 self.assertTrue(match is not None,
362 "Could not generate flow match from pkt")
363 act = action.action_output()
364
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700365 for ingress_port in of_ports:
366 rv = delete_all_flows(self.controller, pa_logger)
367 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700368
Dan Talayco2e77a842010-05-12 15:39:46 -0700369 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700370 match.in_port = ingress_port
371
372 request = message.flow_mod()
373 request.match = match
374 request.buffer_id = 0xffffffff
375 act.port = ofp.OFPP_FLOOD
376 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700377 "Could not add flood port action")
Dan Talayco32fa6542010-05-11 15:54:08 -0700378 pa_logger.info(request.show())
379
380 pa_logger.info("Inserting flow")
381 rv = self.controller.message_send(request)
382 self.assertTrue(rv != -1, "Error installing flow mod")
383 do_barrier(self.controller)
384
385 pa_logger.info("Sending packet to dp port " + str(ingress_port))
386 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700387 yes_ports = set(of_ports).difference([ingress_port])
388 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700389 self, pa_logger, pa_config)
Dan Talayco3be5b062010-05-12 15:46:21 -0700390
Dan Talayco3be5b062010-05-12 15:46:21 -0700391class FloodPlusIngress(basic.SimpleDataPlane):
392 """
393 Flood to all ports plus send to ingress port
394
395 Generate a packet
396 Generate and install a matching flow
397 Add action to flood the packet
398 Add action to send to ingress port
399 Send the packet to ingress dataplane port
400 Verify the packet is received at all other ports
401 """
402 def runTest(self):
Dan Talayco3be5b062010-05-12 15:46:21 -0700403 of_ports = pa_port_map.keys()
404 of_ports.sort()
405 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
406
407 pkt = simple_tcp_packet()
408 match = parse.packet_to_flow_match(pkt)
409 match.wildcards &= ~ofp.OFPFW_IN_PORT
410 self.assertTrue(match is not None,
411 "Could not generate flow match from pkt")
412 act = action.action_output()
413
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700414 for ingress_port in of_ports:
415 rv = delete_all_flows(self.controller, pa_logger)
416 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700417
Dan Talayco3be5b062010-05-12 15:46:21 -0700418 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700419 match.in_port = ingress_port
420
421 request = message.flow_mod()
422 request.match = match
423 request.buffer_id = 0xffffffff
424 act.port = ofp.OFPP_FLOOD
425 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700426 "Could not add flood port action")
427 act.port = ofp.OFPP_IN_PORT
428 self.assertTrue(request.actions.add(act),
429 "Could not add ingress port for output")
430 pa_logger.info(request.show())
431
432 pa_logger.info("Inserting flow")
433 rv = self.controller.message_send(request)
434 self.assertTrue(rv != -1, "Error installing flow mod")
435 do_barrier(self.controller)
436
437 pa_logger.info("Sending packet to dp port " + str(ingress_port))
438 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700439 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700440 pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700441
442class All(basic.SimpleDataPlane):
443 """
444 Send to OFPP_ALL port
445
446 Generate a packet
447 Generate and install a matching flow
448 Add action to forward to OFPP_ALL
449 Send the packet to ingress dataplane port
450 Verify the packet is received at all other ports
451 """
452 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700453 of_ports = pa_port_map.keys()
454 of_ports.sort()
455 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
456
457 pkt = simple_tcp_packet()
458 match = parse.packet_to_flow_match(pkt)
459 match.wildcards &= ~ofp.OFPFW_IN_PORT
460 self.assertTrue(match is not None,
461 "Could not generate flow match from pkt")
462 act = action.action_output()
463
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700464 for ingress_port in of_ports:
465 rv = delete_all_flows(self.controller, pa_logger)
466 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700467
Dan Talayco4aa13122010-05-12 15:54:44 -0700468 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700469 match.in_port = ingress_port
470
471 request = message.flow_mod()
472 request.match = match
473 request.buffer_id = 0xffffffff
474 act.port = ofp.OFPP_ALL
475 self.assertTrue(request.actions.add(act),
476 "Could not add ALL port action")
477 pa_logger.info(request.show())
478
479 pa_logger.info("Inserting flow")
480 rv = self.controller.message_send(request)
481 self.assertTrue(rv != -1, "Error installing flow mod")
482 do_barrier(self.controller)
483
484 pa_logger.info("Sending packet to dp port " + str(ingress_port))
485 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700486 yes_ports = set(of_ports).difference([ingress_port])
487 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700488 self, pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700489
490class AllPlusIngress(basic.SimpleDataPlane):
491 """
492 Send to OFPP_ALL port and ingress port
493
494 Generate a packet
495 Generate and install a matching flow
496 Add action to forward to OFPP_ALL
497 Add action to forward to ingress port
498 Send the packet to ingress dataplane port
499 Verify the packet is received at all other ports
500 """
501 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700502 of_ports = pa_port_map.keys()
503 of_ports.sort()
504 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
505
506 pkt = simple_tcp_packet()
507 match = parse.packet_to_flow_match(pkt)
508 match.wildcards &= ~ofp.OFPFW_IN_PORT
509 self.assertTrue(match is not None,
510 "Could not generate flow match from pkt")
511 act = action.action_output()
512
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700513 for ingress_port in of_ports:
514 rv = delete_all_flows(self.controller, pa_logger)
515 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700516
Dan Talayco4aa13122010-05-12 15:54:44 -0700517 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700518 match.in_port = ingress_port
519
520 request = message.flow_mod()
521 request.match = match
522 request.buffer_id = 0xffffffff
523 act.port = ofp.OFPP_ALL
524 self.assertTrue(request.actions.add(act),
525 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700526 act.port = ofp.OFPP_IN_PORT
527 self.assertTrue(request.actions.add(act),
528 "Could not add ingress port for output")
529 pa_logger.info(request.show())
530
531 pa_logger.info("Inserting flow")
532 rv = self.controller.message_send(request)
533 self.assertTrue(rv != -1, "Error installing flow mod")
534 do_barrier(self.controller)
535
536 pa_logger.info("Sending packet to dp port " + str(ingress_port))
537 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700538 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700539 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700540
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700541class FloodMinusPort(basic.SimpleDataPlane):
542 """
543 Config port with No_Flood and test Flood action
544
545 Generate a packet
546 Generate a matching flow
547 Add action to forward to OFPP_ALL
548 Set port to no-flood
549 Send the packet to ingress dataplane port
550 Verify the packet is received at all other ports except
551 the ingress port and the no_flood port
552 """
553 def runTest(self):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700554 of_ports = pa_port_map.keys()
555 of_ports.sort()
556 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
557
558 pkt = simple_tcp_packet()
559 match = parse.packet_to_flow_match(pkt)
560 match.wildcards &= ~ofp.OFPFW_IN_PORT
561 self.assertTrue(match is not None,
562 "Could not generate flow match from pkt")
563 act = action.action_output()
564
565 for idx in range(len(of_ports)):
566 rv = delete_all_flows(self.controller, pa_logger)
567 self.assertEqual(rv, 0, "Failed to delete all flows")
568
569 ingress_port = of_ports[idx]
570 no_flood_idx = (idx + 1) % len(of_ports)
571 no_flood_port = of_ports[no_flood_idx]
572 rv = port_config_set(self.controller, no_flood_port,
573 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
574 pa_logger)
575 self.assertEqual(rv, 0, "Failed to set port config")
576
577 match.in_port = ingress_port
578
579 request = message.flow_mod()
580 request.match = match
581 request.buffer_id = 0xffffffff
582 act.port = ofp.OFPP_FLOOD
583 self.assertTrue(request.actions.add(act),
584 "Could not add flood port action")
585 pa_logger.info(request.show())
586
587 pa_logger.info("Inserting flow")
588 rv = self.controller.message_send(request)
589 self.assertTrue(rv != -1, "Error installing flow mod")
590 do_barrier(self.controller)
591
592 pa_logger.info("Sending packet to dp port " + str(ingress_port))
593 pa_logger.info("No flood port is " + str(no_flood_port))
594 self.dataplane.send(ingress_port, str(pkt))
595 no_ports = set([ingress_port, no_flood_port])
596 yes_ports = set(of_ports).difference(no_ports)
597 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700598 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700599
600 # Turn no flood off again
601 rv = port_config_set(self.controller, no_flood_port,
602 0, ofp.OFPPC_NO_FLOOD, pa_logger)
603 self.assertEqual(rv, 0, "Failed to reset port config")
604
605 #@todo Should check no other packets received
606
Dan Talayco21381562010-07-17 00:34:47 -0700607
608
Dan Talayco551befa2010-07-15 17:05:32 -0700609################################################################
610
611class BaseMatchCase(basic.SimpleDataPlane):
612 def setUp(self):
613 basic.SimpleDataPlane.setUp(self)
614 self.logger = pa_logger
615 def runTest(self):
616 self.logger.info("BaseMatchCase")
617
618class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700619 """
Dan Talayco551befa2010-07-15 17:05:32 -0700620 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700621
622 Generate a packet
623 Generate and install a matching flow without wildcard mask
624 Add action to forward to a port
625 Send the packet to the port
626 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700627 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700628
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700629 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700630 flow_match_test(self, pa_port_map)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700631
Dan Talayco551befa2010-07-15 17:05:32 -0700632class ExactMatchTagged(BaseMatchCase):
633 """
634 Exact match for all port pairs with tagged pkts
635 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700636
Dan Talayco551befa2010-07-15 17:05:32 -0700637 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700638 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700639 flow_match_test(self, pa_port_map, dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700640
Dan Talayco551befa2010-07-15 17:05:32 -0700641class ExactMatchTaggedMany(BaseMatchCase):
642 """
643 ExactMatchTagged with many VLANS
644 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700645
Dan Talayco551befa2010-07-15 17:05:32 -0700646 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700647 for vid in range(2,100,10):
Dan Talayco551befa2010-07-15 17:05:32 -0700648 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
649 for vid in range(100,4000,389):
650 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
651 flow_match_test(self, pa_port_map, dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700652
Dan Talayco551befa2010-07-15 17:05:32 -0700653# Don't run by default
654test_prio["ExactMatchTaggedMany"] = -1
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700655
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700656
Dan Talayco551befa2010-07-15 17:05:32 -0700657class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700658 """
659 Exercise wildcard matching for all ports
660
661 Generate a packet
662 Generate and install a matching flow with wildcard mask
663 Add action to forward to a port
664 Send the packet to the port
665 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700666 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700667 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700668 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700669 for wc in WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -0700670 if wc & ofp.OFPFW_DL_VLAN:
671 dl_vlan = 0
672 else:
673 dl_vlan = -1
674 flow_match_test(self, pa_port_map, wildcards=wc,
675 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700676
Dan Talayco551befa2010-07-15 17:05:32 -0700677class SingleWildcardMatchTagged(BaseMatchCase):
678 """
679 SingleWildcardMatch with tagged packets
680 """
681 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700682 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700683 for wc in WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700684 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -0700685 max_test=10)
686
687class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700688 """
Dan Talayco80b54ed2010-07-13 09:48:35 -0700689 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700690
691 Generate a packet
692 Generate and install a matching flow with wildcard all except one filed
693 Add action to forward to a port
694 Send the packet to the port
695 Verify the packet is received at all other ports (one port at a time)
696 Verify flow_expiration message is correct when command option is set
697 """
698 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700699 for wc in WILDCARD_VALUES:
700 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco4431d542012-03-21 16:42:16 -0700701 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
702 dl_vlan = 0
703 else:
704 dl_vlan = -1
705 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
706 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700707
Dan Talayco551befa2010-07-15 17:05:32 -0700708class AllExceptOneWildcardMatchTagged(BaseMatchCase):
709 """
710 Match one field with tagged packets
711 """
712 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700713 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700714 for wc in WILDCARD_VALUES:
715 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco21381562010-07-17 00:34:47 -0700716 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
717 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -0700718
719class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700720 """
721 Create Wildcard-all flow and exercise for all ports
722
723 Generate a packet
724 Generate and install a matching flow with wildcard-all
725 Add action to forward to a port
726 Send the packet to the port
727 Verify the packet is received at all other ports (one port at a time)
728 Verify flow_expiration message is correct when command option is set
729 """
730 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700731 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700732
Dan Talayco551befa2010-07-15 17:05:32 -0700733class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700734 """
Dan Talayco551befa2010-07-15 17:05:32 -0700735 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700736 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700737 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700738 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700739 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
740 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700741
Dan Talaycoba3745c2010-07-21 21:51:08 -0700742
Dan Talayco551befa2010-07-15 17:05:32 -0700743class AddVLANTag(BaseMatchCase):
744 """
745 Add a VLAN tag to an untagged packet
746 """
747 def runTest(self):
748 new_vid = 2
749 sup_acts = supported_actions_get(self)
750 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700751 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -0700752 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700753
Dan Talayco551befa2010-07-15 17:05:32 -0700754 len = 100
755 len_w_vid = 104
756 pkt = simple_tcp_packet(pktlen=len)
757 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
758 dl_vlan=new_vid)
759 vid_act = action.action_set_vlan_vid()
760 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700761
Dan Talayco551befa2010-07-15 17:05:32 -0700762 flow_match_test(self, pa_port_map, pkt=pkt,
763 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700764
Dan Talayco551befa2010-07-15 17:05:32 -0700765class PacketOnly(basic.DataPlaneOnly):
766 """
767 Just send a packet thru the switch
768 """
769 def runTest(self):
770 pkt = simple_tcp_packet()
771 of_ports = pa_port_map.keys()
772 of_ports.sort()
773 ing_port = of_ports[0]
774 pa_logger.info("Sending packet to " + str(ing_port))
775 pa_logger.debug("Data: " + str(pkt).encode('hex'))
776 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700777
Dan Talayco551befa2010-07-15 17:05:32 -0700778class PacketOnlyTagged(basic.DataPlaneOnly):
779 """
780 Just send a packet thru the switch
781 """
782 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700783 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700784 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
785 of_ports = pa_port_map.keys()
786 of_ports.sort()
787 ing_port = of_ports[0]
788 pa_logger.info("Sending packet to " + str(ing_port))
789 pa_logger.debug("Data: " + str(pkt).encode('hex'))
790 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700791
Dan Talayco551befa2010-07-15 17:05:32 -0700792test_prio["PacketOnly"] = -1
793test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700794
Dan Talayco551befa2010-07-15 17:05:32 -0700795class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700796 """
797 Modify the VLAN ID in the VLAN tag of a tagged packet
798 """
Dan Talayco551befa2010-07-15 17:05:32 -0700799 def runTest(self):
800 old_vid = 2
801 new_vid = 3
802 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700803 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700804 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700805 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700806
Dan Talayco551befa2010-07-15 17:05:32 -0700807 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
808 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
809 vid_act = action.action_set_vlan_vid()
810 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700811
Dan Talayco551befa2010-07-15 17:05:32 -0700812 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
813 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700814
Dan Talayco551befa2010-07-15 17:05:32 -0700815class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700816 """
817 Strip the VLAN tag from a tagged packet
818 """
Dan Talayco551befa2010-07-15 17:05:32 -0700819 def runTest(self):
820 old_vid = 2
821 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700822 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700823 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700824 return
Dan Talaycof36f1082010-07-13 13:57:17 -0700825
Dan Talayco551befa2010-07-15 17:05:32 -0700826 len_w_vid = 104
827 len = 100
828 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
829 dl_vlan=old_vid)
830 exp_pkt = simple_tcp_packet(pktlen=len)
831 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700832
Dan Talayco551befa2010-07-15 17:05:32 -0700833 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
834 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700835
Dan Talayco4b2bee62010-07-20 14:10:05 -0700836def init_pkt_args():
837 """
838 Pass back a dictionary with default packet arguments
839 """
840 args = {}
841 args["dl_src"] = '00:23:45:67:89:AB'
842
843 dl_vlan_enable=False
844 dl_vlan=-1
845 if pa_config["test-params"]["vid"]:
846 dl_vlan_enable=True
847 dl_vlan = pa_config["test-params"]["vid"]
848
849# Unpack operator is ** on a dictionary
850
851 return args
852
Dan Talayco551befa2010-07-15 17:05:32 -0700853class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700854 """
855 Modify the source MAC address (TP1)
856 """
Dan Talayco551befa2010-07-15 17:05:32 -0700857 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700858 sup_acts = supported_actions_get(self)
859 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700860 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700861 return
862
863 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
864 check_test_params=True)
865 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
866 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700867
Dan Talayco551befa2010-07-15 17:05:32 -0700868class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700869 """
870 Modify the dest MAC address (TP1)
871 """
Dan Talayco551befa2010-07-15 17:05:32 -0700872 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700873 sup_acts = supported_actions_get(self)
874 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700875 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700876 return
877
878 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
879 check_test_params=True)
880 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
881 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700882
Dan Talayco551befa2010-07-15 17:05:32 -0700883class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700884 """
885 Modify the source IP address of an IP packet (TP1)
886 """
Dan Talayco551befa2010-07-15 17:05:32 -0700887 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700888 sup_acts = supported_actions_get(self)
889 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700890 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700891 return
892
893 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
894 check_test_params=True)
895 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
896 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700897
Dan Talayco551befa2010-07-15 17:05:32 -0700898class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700899 """
900 Modify the dest IP address of an IP packet (TP1)
901 """
Dan Talayco551befa2010-07-15 17:05:32 -0700902 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700903 sup_acts = supported_actions_get(self)
904 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700905 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700906 return
907
908 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
909 check_test_params=True)
910 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
911 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -0700912
913class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700914 """
915 Modify the source TCP port of a TCP packet (TP1)
916 """
Dan Talayco551befa2010-07-15 17:05:32 -0700917 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700918 sup_acts = supported_actions_get(self)
919 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700920 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700921 return
922
923 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
924 check_test_params=True)
925 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
926 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -0700927
928class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700929 """
930 Modify the dest TCP port of a TCP packet (TP1)
931 """
Dan Talayco551befa2010-07-15 17:05:32 -0700932 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700933 sup_acts = supported_actions_get(self)
934 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700935 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700936 return
937
938 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
939 check_test_params=True)
940 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
941 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -0700942
943class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700944 """
945 Modify the IP type of service of an IP packet (TP1)
946 """
Dan Talayco551befa2010-07-15 17:05:32 -0700947 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700948 sup_acts = supported_actions_get(self)
949 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700950 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700951 return
Dan Talayco551befa2010-07-15 17:05:32 -0700952
Dan Talayco4b2bee62010-07-20 14:10:05 -0700953 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
954 check_test_params=True)
955 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -0700956 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -0700957
Dan Talaycof6e76c02012-03-23 10:56:12 -0700958class ModifyL2DstMC(BaseMatchCase):
959 """
960 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -0700961 """
962 def runTest(self):
963 sup_acts = supported_actions_get(self)
964 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -0700965 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -0700966 return
967
Dan Talaycof6e76c02012-03-23 10:56:12 -0700968 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
969 check_test_params=True)
970 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -0700971 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -0700972
973class ModifyL2SrcMC(BaseMatchCase):
974 """
975 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -0700976 """
977 def runTest(self):
978 sup_acts = supported_actions_get(self)
979 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -0700980 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -0700981 return
982
Dan Talaycof6e76c02012-03-23 10:56:12 -0700983 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
984 check_test_params=True)
985 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -0700986 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -0700987
988class ModifyL2SrcDstMC(BaseMatchCase):
989 """
990 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -0700991 """
992 def runTest(self):
993 sup_acts = supported_actions_get(self)
Dan Talaycocfa172f2012-03-23 12:03:00 -0700994 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
995 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
996 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -0700997 return
998
Dan Talaycof6e76c02012-03-23 10:56:12 -0700999 mod_fields = ['dl_dst', 'dl_src']
1000 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1001 check_test_params=True)
1002 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001003 action_list=acts, max_test=2, egr_count=-1)
1004
1005class ModifyL2DstVIDMC(BaseMatchCase):
1006 """
1007 Modify the L2 dest and send to 2 ports
1008 """
1009 def runTest(self):
1010 sup_acts = supported_actions_get(self)
1011 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1012 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1013 skip_message_emit(self, "ModifyL2DstVIDMC test")
1014 return
1015
1016 mod_fields = ['dl_dst', 'dl_vlan']
1017 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1018 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1019 check_test_params=True)
1020 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1021 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001022
1023
Dan Talayco4b2bee62010-07-20 14:10:05 -07001024#@todo Need to implement tagged versions of the above tests
1025#
1026#@todo Implement a test case that strips tag 2, adds tag 3
1027# and modifies tag 4 to tag 5. Then verify (in addition) that
1028# tag 6 does not get modified.
1029
1030class MixedVLAN(BaseMatchCase):
1031 """
1032 Test mixture of VLAN tag actions
1033
1034 Strip tag 2 on port 1, send to port 2
1035 Add tag 3 on port 1, send to port 2
1036 Modify tag 4 to 5 on port 1, send to port 2
1037 All other traffic from port 1, send to port 3
1038 All traffic from port 2 sent to port 4
1039 Use exact matches with different packets for all mods
1040 Verify the following: (port, vid)
1041 (port 1, vid 2) => VLAN tag stripped, out port 2
1042 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1043 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1044 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1045 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1046 (port 2, no tag) => untagged packet out port 4
1047 (port 2, vid 2-6) => unmodified packet out port 4
1048
1049 Variation: Might try sending VID 5 to port 3 and check.
1050 If only VID 5 distinguishes pkt, this will fail on some platforms
1051 """
1052
1053test_prio["MixedVLAN"] = -1
1054
Dan Talayco551befa2010-07-15 17:05:32 -07001055def supported_actions_get(parent, use_cache=True):
1056 """
1057 Get the bitmap of supported actions from the switch
1058 If use_cache is false, the cached value will be updated
1059 """
1060 global cached_supported_actions
1061 if cached_supported_actions is None or not use_cache:
1062 request = message.features_request()
1063 (reply, pkt) = parent.controller.transact(request, timeout=2)
1064 parent.assertTrue(reply is not None, "Did not get response to ftr req")
1065 cached_supported_actions = reply.actions
1066 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
1067
1068 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -07001069
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001070if __name__ == "__main__":
1071 print "Please run through oft script: ./oft --test_spec=basic"