blob: 5357b7ce209c507c7d965728c5daf9ce38f81e4c [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 Talayco21381562010-07-17 00:34:47 -0700670 flow_match_test(self, pa_port_map, wildcards=wc, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700671
Dan Talayco551befa2010-07-15 17:05:32 -0700672class SingleWildcardMatchTagged(BaseMatchCase):
673 """
674 SingleWildcardMatch with tagged packets
675 """
676 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700677 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700678 for wc in WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700679 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -0700680 max_test=10)
681
682class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700683 """
Dan Talayco80b54ed2010-07-13 09:48:35 -0700684 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700685
686 Generate a packet
687 Generate and install a matching flow with wildcard all except one filed
688 Add action to forward to a port
689 Send the packet to the port
690 Verify the packet is received at all other ports (one port at a time)
691 Verify flow_expiration message is correct when command option is set
692 """
693 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700694 for wc in WILDCARD_VALUES:
695 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco21381562010-07-17 00:34:47 -0700696 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700697
Dan Talayco551befa2010-07-15 17:05:32 -0700698class AllExceptOneWildcardMatchTagged(BaseMatchCase):
699 """
700 Match one field with tagged packets
701 """
702 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700703 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700704 for wc in WILDCARD_VALUES:
705 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco21381562010-07-17 00:34:47 -0700706 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
707 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -0700708
709class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700710 """
711 Create Wildcard-all flow and exercise for all ports
712
713 Generate a packet
714 Generate and install a matching flow with wildcard-all
715 Add action to forward to a port
716 Send the packet to the port
717 Verify the packet is received at all other ports (one port at a time)
718 Verify flow_expiration message is correct when command option is set
719 """
720 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700721 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700722
Dan Talayco551befa2010-07-15 17:05:32 -0700723class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700724 """
Dan Talayco551befa2010-07-15 17:05:32 -0700725 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700726 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700727 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700728 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700729 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
730 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700731
Dan Talaycoba3745c2010-07-21 21:51:08 -0700732
Dan Talayco551befa2010-07-15 17:05:32 -0700733class AddVLANTag(BaseMatchCase):
734 """
735 Add a VLAN tag to an untagged packet
736 """
737 def runTest(self):
738 new_vid = 2
739 sup_acts = supported_actions_get(self)
740 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700741 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -0700742 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700743
Dan Talayco551befa2010-07-15 17:05:32 -0700744 len = 100
745 len_w_vid = 104
746 pkt = simple_tcp_packet(pktlen=len)
747 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
748 dl_vlan=new_vid)
749 vid_act = action.action_set_vlan_vid()
750 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700751
Dan Talayco551befa2010-07-15 17:05:32 -0700752 flow_match_test(self, pa_port_map, pkt=pkt,
753 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700754
Dan Talayco551befa2010-07-15 17:05:32 -0700755class PacketOnly(basic.DataPlaneOnly):
756 """
757 Just send a packet thru the switch
758 """
759 def runTest(self):
760 pkt = simple_tcp_packet()
761 of_ports = pa_port_map.keys()
762 of_ports.sort()
763 ing_port = of_ports[0]
764 pa_logger.info("Sending packet to " + str(ing_port))
765 pa_logger.debug("Data: " + str(pkt).encode('hex'))
766 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700767
Dan Talayco551befa2010-07-15 17:05:32 -0700768class PacketOnlyTagged(basic.DataPlaneOnly):
769 """
770 Just send a packet thru the switch
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 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
775 of_ports = pa_port_map.keys()
776 of_ports.sort()
777 ing_port = of_ports[0]
778 pa_logger.info("Sending packet to " + str(ing_port))
779 pa_logger.debug("Data: " + str(pkt).encode('hex'))
780 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700781
Dan Talayco551befa2010-07-15 17:05:32 -0700782test_prio["PacketOnly"] = -1
783test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700784
Dan Talayco551befa2010-07-15 17:05:32 -0700785class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700786 """
787 Modify the VLAN ID in the VLAN tag of a tagged packet
788 """
Dan Talayco551befa2010-07-15 17:05:32 -0700789 def runTest(self):
790 old_vid = 2
791 new_vid = 3
792 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700793 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700794 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700795 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700796
Dan Talayco551befa2010-07-15 17:05:32 -0700797 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
798 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
799 vid_act = action.action_set_vlan_vid()
800 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700801
Dan Talayco551befa2010-07-15 17:05:32 -0700802 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
803 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700804
Dan Talayco551befa2010-07-15 17:05:32 -0700805class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700806 """
807 Strip the VLAN tag from a tagged packet
808 """
Dan Talayco551befa2010-07-15 17:05:32 -0700809 def runTest(self):
810 old_vid = 2
811 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700812 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700813 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700814 return
Dan Talaycof36f1082010-07-13 13:57:17 -0700815
Dan Talayco551befa2010-07-15 17:05:32 -0700816 len_w_vid = 104
817 len = 100
818 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
819 dl_vlan=old_vid)
820 exp_pkt = simple_tcp_packet(pktlen=len)
821 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700822
Dan Talayco551befa2010-07-15 17:05:32 -0700823 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
824 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700825
Dan Talayco4b2bee62010-07-20 14:10:05 -0700826def init_pkt_args():
827 """
828 Pass back a dictionary with default packet arguments
829 """
830 args = {}
831 args["dl_src"] = '00:23:45:67:89:AB'
832
833 dl_vlan_enable=False
834 dl_vlan=-1
835 if pa_config["test-params"]["vid"]:
836 dl_vlan_enable=True
837 dl_vlan = pa_config["test-params"]["vid"]
838
839# Unpack operator is ** on a dictionary
840
841 return args
842
Dan Talayco551befa2010-07-15 17:05:32 -0700843class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700844 """
845 Modify the source MAC address (TP1)
846 """
Dan Talayco551befa2010-07-15 17:05:32 -0700847 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700848 sup_acts = supported_actions_get(self)
849 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700850 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700851 return
852
853 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
854 check_test_params=True)
855 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
856 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700857
Dan Talayco551befa2010-07-15 17:05:32 -0700858class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700859 """
860 Modify the dest MAC address (TP1)
861 """
Dan Talayco551befa2010-07-15 17:05:32 -0700862 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700863 sup_acts = supported_actions_get(self)
864 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700865 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700866 return
867
868 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
869 check_test_params=True)
870 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
871 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700872
Dan Talayco551befa2010-07-15 17:05:32 -0700873class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700874 """
875 Modify the source IP address of an IP packet (TP1)
876 """
Dan Talayco551befa2010-07-15 17:05:32 -0700877 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700878 sup_acts = supported_actions_get(self)
879 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700880 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700881 return
882
883 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
884 check_test_params=True)
885 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
886 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700887
Dan Talayco551befa2010-07-15 17:05:32 -0700888class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700889 """
890 Modify the dest IP address of an IP packet (TP1)
891 """
Dan Talayco551befa2010-07-15 17:05:32 -0700892 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700893 sup_acts = supported_actions_get(self)
894 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700895 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700896 return
897
898 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
899 check_test_params=True)
900 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
901 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -0700902
903class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700904 """
905 Modify the source TCP port of a TCP packet (TP1)
906 """
Dan Talayco551befa2010-07-15 17:05:32 -0700907 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700908 sup_acts = supported_actions_get(self)
909 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700910 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700911 return
912
913 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
914 check_test_params=True)
915 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
916 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -0700917
918class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700919 """
920 Modify the dest TCP port of a TCP packet (TP1)
921 """
Dan Talayco551befa2010-07-15 17:05:32 -0700922 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700923 sup_acts = supported_actions_get(self)
924 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700925 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700926 return
927
928 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
929 check_test_params=True)
930 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
931 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -0700932
933class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700934 """
935 Modify the IP type of service of an IP packet (TP1)
936 """
Dan Talayco551befa2010-07-15 17:05:32 -0700937 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700938 sup_acts = supported_actions_get(self)
939 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700940 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700941 return
Dan Talayco551befa2010-07-15 17:05:32 -0700942
Dan Talayco4b2bee62010-07-20 14:10:05 -0700943 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
944 check_test_params=True)
945 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
946 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -0700947
Dan Talayco4b2bee62010-07-20 14:10:05 -0700948#@todo Need to implement tagged versions of the above tests
949#
950#@todo Implement a test case that strips tag 2, adds tag 3
951# and modifies tag 4 to tag 5. Then verify (in addition) that
952# tag 6 does not get modified.
953
954class MixedVLAN(BaseMatchCase):
955 """
956 Test mixture of VLAN tag actions
957
958 Strip tag 2 on port 1, send to port 2
959 Add tag 3 on port 1, send to port 2
960 Modify tag 4 to 5 on port 1, send to port 2
961 All other traffic from port 1, send to port 3
962 All traffic from port 2 sent to port 4
963 Use exact matches with different packets for all mods
964 Verify the following: (port, vid)
965 (port 1, vid 2) => VLAN tag stripped, out port 2
966 (port 1, no tag) => tagged packet w/ vid 2 out port 2
967 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
968 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
969 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
970 (port 2, no tag) => untagged packet out port 4
971 (port 2, vid 2-6) => unmodified packet out port 4
972
973 Variation: Might try sending VID 5 to port 3 and check.
974 If only VID 5 distinguishes pkt, this will fail on some platforms
975 """
976
977test_prio["MixedVLAN"] = -1
978
Dan Talayco551befa2010-07-15 17:05:32 -0700979def supported_actions_get(parent, use_cache=True):
980 """
981 Get the bitmap of supported actions from the switch
982 If use_cache is false, the cached value will be updated
983 """
984 global cached_supported_actions
985 if cached_supported_actions is None or not use_cache:
986 request = message.features_request()
987 (reply, pkt) = parent.controller.transact(request, timeout=2)
988 parent.assertTrue(reply is not None, "Did not get response to ftr req")
989 cached_supported_actions = reply.actions
990 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
991
992 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -0700993
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700994if __name__ == "__main__":
995 print "Please run through oft script: ./oft --test_spec=basic"