blob: 57a5a20c45bf44da7938182c6d46287f8ae0b018 [file] [log] [blame]
Dan Talayco5eba8442010-03-10 13:58:43 -08001"""
2Test cases for testing actions taken on packets
3
4See basic.py for other info.
5
6It is recommended that these definitions be kept in their own
7namespace as different groups of tests will likely define
8similar identifiers.
9
10 The function test_set_init is called with a complete configuration
11dictionary prior to the invocation of any tests from this file.
12
13 The switch is actively attempting to contact the controller at the address
14indicated oin oft_config
15
16"""
17
Dan Talayco9f47f4d2010-06-03 13:54:37 -070018import copy
19
Dan Talayco5eba8442010-03-10 13:58:43 -080020import logging
21
22import unittest
23
24import oftest.controller as controller
25import oftest.cstruct as ofp
26import oftest.message as message
27import oftest.dataplane as dataplane
28import oftest.action as action
29import oftest.parse as parse
30import basic
Dan Talayco8a64e332012-03-28 14:53:20 -070031import time
Dan Talayco5eba8442010-03-10 13:58:43 -080032
33from testutils import *
34
35#@var port_map Local copy of the configuration map from OF port
36# numbers to OS interfaces
37pa_port_map = None
38#@var pa_logger Local logger object
39pa_logger = None
40#@var pa_config Local copy of global configuration data
41pa_config = None
42
Dan Talayco551befa2010-07-15 17:05:32 -070043# For test priority
44#@var test_prio Set test priority for local tests
45test_prio = {}
46
47WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
48 ofp.OFPFW_DL_VLAN,
49 ofp.OFPFW_DL_SRC,
50 ofp.OFPFW_DL_DST,
51 ofp.OFPFW_DL_TYPE,
52 ofp.OFPFW_NW_PROTO,
53 ofp.OFPFW_TP_SRC,
54 ofp.OFPFW_TP_DST,
55 0x3F << ofp.OFPFW_NW_SRC_SHIFT,
56 0x3F << ofp.OFPFW_NW_DST_SHIFT,
57 ofp.OFPFW_DL_VLAN_PCP,
58 ofp.OFPFW_NW_TOS]
59
60MODIFY_ACTION_VALUES = [ofp.OFPAT_SET_VLAN_VID,
61 ofp.OFPAT_SET_VLAN_PCP,
62 ofp.OFPAT_STRIP_VLAN,
63 ofp.OFPAT_SET_DL_SRC,
64 ofp.OFPAT_SET_DL_DST,
65 ofp.OFPAT_SET_NW_SRC,
66 ofp.OFPAT_SET_NW_DST,
67 ofp.OFPAT_SET_NW_TOS,
68 ofp.OFPAT_SET_TP_SRC,
69 ofp.OFPAT_SET_TP_DST]
70
71# Cache supported features to avoid transaction overhead
72cached_supported_actions = None
73
Dan Talayco21381562010-07-17 00:34:47 -070074TEST_VID_DEFAULT = 2
75
Dan Talayco5eba8442010-03-10 13:58:43 -080076def test_set_init(config):
77 """
78 Set up function for packet action test classes
79
80 @param config The configuration dictionary; see oft
81 """
82
83 global pa_port_map
84 global pa_logger
85 global pa_config
86
87 pa_logger = logging.getLogger("pkt_act")
88 pa_logger.info("Initializing test set")
89 pa_port_map = config["port_map"]
90 pa_config = config
91
92class DirectPacket(basic.SimpleDataPlane):
93 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -070094 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -080095
96 Generate a packet
97 Generate and install a matching flow
98 Add action to direct the packet to an egress port
99 Send the packet to ingress dataplane port
100 Verify the packet is received at the egress port only
101 """
102 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700103 self.handleFlow()
104
105 def handleFlow(self, pkttype='TCP'):
Dan Talayco5eba8442010-03-10 13:58:43 -0800106 of_ports = pa_port_map.keys()
107 of_ports.sort()
108 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
109
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700110 if (pkttype == 'ICMP'):
111 pkt = simple_icmp_packet()
112 else:
113 pkt = simple_tcp_packet()
Dan Talayco5eba8442010-03-10 13:58:43 -0800114 match = parse.packet_to_flow_match(pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700115 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800116 self.assertTrue(match is not None,
117 "Could not generate flow match from pkt")
118 act = action.action_output()
119
120 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700121 rv = delete_all_flows(self.controller, pa_logger)
122 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700123
Dan Talayco5eba8442010-03-10 13:58:43 -0800124 ingress_port = of_ports[idx]
125 egress_port = of_ports[(idx + 1) % len(of_ports)]
126 pa_logger.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700127 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800128
129 match.in_port = ingress_port
130
131 request = message.flow_mod()
132 request.match = match
133 request.buffer_id = 0xffffffff
134 act.port = egress_port
135 self.assertTrue(request.actions.add(act), "Could not add action")
136
137 pa_logger.info("Inserting flow")
138 rv = self.controller.message_send(request)
139 self.assertTrue(rv != -1, "Error installing flow mod")
140 do_barrier(self.controller)
141
142 pa_logger.info("Sending packet to dp port " +
143 str(ingress_port))
144 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700145
146 exp_pkt_arg = None
147 exp_port = None
148 if pa_config["relax"]:
149 exp_pkt_arg = pkt
150 exp_port = egress_port
151
152 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(timeout=1,
153 port_number=exp_port,
154 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800155 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700156 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800157 str(rcv_port))
158 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
159 self.assertEqual(str(pkt), str(rcv_pkt),
160 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700161
162class DirectPacketICMP(DirectPacket):
163 """
164 Send ICMP packet to single egress port
165
166 Generate a ICMP packet
167 Generate and install a matching flow
168 Add action to direct the packet to an egress port
169 Send the packet to ingress dataplane port
170 Verify the packet is received at the egress port only
171 Difference from DirectPacket test is that sent packet is ICMP
172 """
173 def runTest(self):
174 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700175
176class DirectTwoPorts(basic.SimpleDataPlane):
177 """
178 Send packet to two egress ports
179
180 Generate a packet
181 Generate and install a matching flow
182 Add action to direct the packet to two egress ports
183 Send the packet to ingress dataplane port
184 Verify the packet is received at the two egress ports
185 """
186 def runTest(self):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700187 of_ports = pa_port_map.keys()
188 of_ports.sort()
189 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
190
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700191 pkt = simple_tcp_packet()
192 match = parse.packet_to_flow_match(pkt)
193 match.wildcards &= ~ofp.OFPFW_IN_PORT
194 self.assertTrue(match is not None,
195 "Could not generate flow match from pkt")
196 act = action.action_output()
197
198 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700199 rv = delete_all_flows(self.controller, pa_logger)
200 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700201
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700202 ingress_port = of_ports[idx]
203 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
204 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
205 pa_logger.info("Ingress " + str(ingress_port) +
206 " to egress " + str(egress_port1) + " and " +
207 str(egress_port2))
208
209 match.in_port = ingress_port
210
211 request = message.flow_mod()
212 request.match = match
213 request.buffer_id = 0xffffffff
214 act.port = egress_port1
215 self.assertTrue(request.actions.add(act), "Could not add action1")
216 act.port = egress_port2
217 self.assertTrue(request.actions.add(act), "Could not add action2")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700218 # pa_logger.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700219
220 pa_logger.info("Inserting flow")
221 rv = self.controller.message_send(request)
222 self.assertTrue(rv != -1, "Error installing flow mod")
223 do_barrier(self.controller)
224
225 pa_logger.info("Sending packet to dp port " +
226 str(ingress_port))
227 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700228 yes_ports = set([egress_port1, egress_port2])
229 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700230
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700231 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700232 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700233
234class DirectMCNonIngress(basic.SimpleDataPlane):
235 """
236 Multicast to all non-ingress ports
237
238 Generate a packet
239 Generate and install a matching flow
240 Add action to direct the packet to all non-ingress ports
241 Send the packet to ingress dataplane port
242 Verify the packet is received at all non-ingress ports
243
244 Does not use the flood action
245 """
246 def runTest(self):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700247 of_ports = pa_port_map.keys()
248 of_ports.sort()
249 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
250
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700251 pkt = simple_tcp_packet()
252 match = parse.packet_to_flow_match(pkt)
253 match.wildcards &= ~ofp.OFPFW_IN_PORT
254 self.assertTrue(match is not None,
255 "Could not generate flow match from pkt")
256 act = action.action_output()
257
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700258 for ingress_port in of_ports:
259 rv = delete_all_flows(self.controller, pa_logger)
260 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700261
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700262 pa_logger.info("Ingress " + str(ingress_port) +
263 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700264 match.in_port = ingress_port
265
266 request = message.flow_mod()
267 request.match = match
268 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700269 for egress_port in of_ports:
270 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700271 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700272 act.port = egress_port
273 self.assertTrue(request.actions.add(act),
274 "Could not add output to " + str(egress_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700275 pa_logger.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700276
277 pa_logger.info("Inserting flow")
278 rv = self.controller.message_send(request)
279 self.assertTrue(rv != -1, "Error installing flow mod")
280 do_barrier(self.controller)
281
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700282 pa_logger.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700283 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700284 yes_ports = set(of_ports).difference([ingress_port])
285 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700286 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700287
Dan Talayco32fa6542010-05-11 15:54:08 -0700288
289class DirectMC(basic.SimpleDataPlane):
290 """
291 Multicast to all ports including ingress
292
293 Generate a packet
294 Generate and install a matching flow
295 Add action to direct the packet to all non-ingress ports
296 Send the packet to ingress dataplane port
297 Verify the packet is received at all ports
298
299 Does not use the flood action
300 """
301 def runTest(self):
Dan Talayco32fa6542010-05-11 15:54:08 -0700302 of_ports = pa_port_map.keys()
303 of_ports.sort()
304 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
305
Dan Talayco32fa6542010-05-11 15:54:08 -0700306 pkt = simple_tcp_packet()
307 match = parse.packet_to_flow_match(pkt)
308 match.wildcards &= ~ofp.OFPFW_IN_PORT
309 self.assertTrue(match is not None,
310 "Could not generate flow match from pkt")
311 act = action.action_output()
312
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700313 for ingress_port in of_ports:
314 rv = delete_all_flows(self.controller, pa_logger)
315 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700316
Dan Talayco32fa6542010-05-11 15:54:08 -0700317 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700318 match.in_port = ingress_port
319
320 request = message.flow_mod()
321 request.match = match
322 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700323 for egress_port in of_ports:
324 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700325 act.port = ofp.OFPP_IN_PORT
326 else:
327 act.port = egress_port
328 self.assertTrue(request.actions.add(act),
329 "Could not add output to " + str(egress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700330 # pa_logger.info(request.show())
331
332 pa_logger.info("Inserting flow")
333 rv = self.controller.message_send(request)
334 self.assertTrue(rv != -1, "Error installing flow mod")
335 do_barrier(self.controller)
336
337 pa_logger.info("Sending packet to dp port " + str(ingress_port))
338 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700339 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700340 pa_logger, pa_config)
Dan Talayco2e77a842010-05-12 15:39:46 -0700341
342class Flood(basic.SimpleDataPlane):
343 """
344 Flood to all ports except ingress
345
346 Generate a packet
347 Generate and install a matching flow
348 Add action to flood the packet
349 Send the packet to ingress dataplane port
350 Verify the packet is received at all other ports
351 """
352 def runTest(self):
Dan Talayco2e77a842010-05-12 15:39:46 -0700353 of_ports = pa_port_map.keys()
354 of_ports.sort()
355 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
356
357 pkt = simple_tcp_packet()
358 match = parse.packet_to_flow_match(pkt)
359 match.wildcards &= ~ofp.OFPFW_IN_PORT
360 self.assertTrue(match is not None,
361 "Could not generate flow match from pkt")
362 act = action.action_output()
363
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700364 for ingress_port in of_ports:
365 rv = delete_all_flows(self.controller, pa_logger)
366 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700367
Dan Talayco2e77a842010-05-12 15:39:46 -0700368 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700369 match.in_port = ingress_port
370
371 request = message.flow_mod()
372 request.match = match
373 request.buffer_id = 0xffffffff
374 act.port = ofp.OFPP_FLOOD
375 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700376 "Could not add flood port action")
Dan Talayco32fa6542010-05-11 15:54:08 -0700377 pa_logger.info(request.show())
378
379 pa_logger.info("Inserting flow")
380 rv = self.controller.message_send(request)
381 self.assertTrue(rv != -1, "Error installing flow mod")
382 do_barrier(self.controller)
383
384 pa_logger.info("Sending packet to dp port " + str(ingress_port))
385 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700386 yes_ports = set(of_ports).difference([ingress_port])
387 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700388 self, pa_logger, pa_config)
Dan Talayco3be5b062010-05-12 15:46:21 -0700389
Dan Talayco3be5b062010-05-12 15:46:21 -0700390class FloodPlusIngress(basic.SimpleDataPlane):
391 """
392 Flood to all ports plus send to ingress port
393
394 Generate a packet
395 Generate and install a matching flow
396 Add action to flood the packet
397 Add action to send to ingress port
398 Send the packet to ingress dataplane port
399 Verify the packet is received at all other ports
400 """
401 def runTest(self):
Dan Talayco3be5b062010-05-12 15:46:21 -0700402 of_ports = pa_port_map.keys()
403 of_ports.sort()
404 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
405
406 pkt = simple_tcp_packet()
407 match = parse.packet_to_flow_match(pkt)
408 match.wildcards &= ~ofp.OFPFW_IN_PORT
409 self.assertTrue(match is not None,
410 "Could not generate flow match from pkt")
411 act = action.action_output()
412
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700413 for ingress_port in of_ports:
414 rv = delete_all_flows(self.controller, pa_logger)
415 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700416
Dan Talayco3be5b062010-05-12 15:46:21 -0700417 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700418 match.in_port = ingress_port
419
420 request = message.flow_mod()
421 request.match = match
422 request.buffer_id = 0xffffffff
423 act.port = ofp.OFPP_FLOOD
424 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700425 "Could not add flood port action")
426 act.port = ofp.OFPP_IN_PORT
427 self.assertTrue(request.actions.add(act),
428 "Could not add ingress port for output")
429 pa_logger.info(request.show())
430
431 pa_logger.info("Inserting flow")
432 rv = self.controller.message_send(request)
433 self.assertTrue(rv != -1, "Error installing flow mod")
434 do_barrier(self.controller)
435
436 pa_logger.info("Sending packet to dp port " + str(ingress_port))
437 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700438 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700439 pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700440
441class All(basic.SimpleDataPlane):
442 """
443 Send to OFPP_ALL port
444
445 Generate a packet
446 Generate and install a matching flow
447 Add action to forward to OFPP_ALL
448 Send the packet to ingress dataplane port
449 Verify the packet is received at all other ports
450 """
451 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700452 of_ports = pa_port_map.keys()
453 of_ports.sort()
454 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
455
456 pkt = simple_tcp_packet()
457 match = parse.packet_to_flow_match(pkt)
458 match.wildcards &= ~ofp.OFPFW_IN_PORT
459 self.assertTrue(match is not None,
460 "Could not generate flow match from pkt")
461 act = action.action_output()
462
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700463 for ingress_port in of_ports:
464 rv = delete_all_flows(self.controller, pa_logger)
465 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700466
Dan Talayco4aa13122010-05-12 15:54:44 -0700467 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700468 match.in_port = ingress_port
469
470 request = message.flow_mod()
471 request.match = match
472 request.buffer_id = 0xffffffff
473 act.port = ofp.OFPP_ALL
474 self.assertTrue(request.actions.add(act),
475 "Could not add ALL port action")
476 pa_logger.info(request.show())
477
478 pa_logger.info("Inserting flow")
479 rv = self.controller.message_send(request)
480 self.assertTrue(rv != -1, "Error installing flow mod")
481 do_barrier(self.controller)
482
483 pa_logger.info("Sending packet to dp port " + str(ingress_port))
484 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700485 yes_ports = set(of_ports).difference([ingress_port])
486 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700487 self, pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700488
489class AllPlusIngress(basic.SimpleDataPlane):
490 """
491 Send to OFPP_ALL port and ingress port
492
493 Generate a packet
494 Generate and install a matching flow
495 Add action to forward to OFPP_ALL
496 Add action to forward to ingress port
497 Send the packet to ingress dataplane port
498 Verify the packet is received at all other ports
499 """
500 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700501 of_ports = pa_port_map.keys()
502 of_ports.sort()
503 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
504
505 pkt = simple_tcp_packet()
506 match = parse.packet_to_flow_match(pkt)
507 match.wildcards &= ~ofp.OFPFW_IN_PORT
508 self.assertTrue(match is not None,
509 "Could not generate flow match from pkt")
510 act = action.action_output()
511
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700512 for ingress_port in of_ports:
513 rv = delete_all_flows(self.controller, pa_logger)
514 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700515
Dan Talayco4aa13122010-05-12 15:54:44 -0700516 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700517 match.in_port = ingress_port
518
519 request = message.flow_mod()
520 request.match = match
521 request.buffer_id = 0xffffffff
522 act.port = ofp.OFPP_ALL
523 self.assertTrue(request.actions.add(act),
524 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700525 act.port = ofp.OFPP_IN_PORT
526 self.assertTrue(request.actions.add(act),
527 "Could not add ingress port for output")
528 pa_logger.info(request.show())
529
530 pa_logger.info("Inserting flow")
531 rv = self.controller.message_send(request)
532 self.assertTrue(rv != -1, "Error installing flow mod")
533 do_barrier(self.controller)
534
535 pa_logger.info("Sending packet to dp port " + str(ingress_port))
536 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700537 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700538 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700539
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700540class FloodMinusPort(basic.SimpleDataPlane):
541 """
542 Config port with No_Flood and test Flood action
543
544 Generate a packet
545 Generate a matching flow
546 Add action to forward to OFPP_ALL
547 Set port to no-flood
548 Send the packet to ingress dataplane port
549 Verify the packet is received at all other ports except
550 the ingress port and the no_flood port
551 """
552 def runTest(self):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700553 of_ports = pa_port_map.keys()
554 of_ports.sort()
555 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
556
557 pkt = simple_tcp_packet()
558 match = parse.packet_to_flow_match(pkt)
559 match.wildcards &= ~ofp.OFPFW_IN_PORT
560 self.assertTrue(match is not None,
561 "Could not generate flow match from pkt")
562 act = action.action_output()
563
564 for idx in range(len(of_ports)):
565 rv = delete_all_flows(self.controller, pa_logger)
566 self.assertEqual(rv, 0, "Failed to delete all flows")
567
568 ingress_port = of_ports[idx]
569 no_flood_idx = (idx + 1) % len(of_ports)
570 no_flood_port = of_ports[no_flood_idx]
571 rv = port_config_set(self.controller, no_flood_port,
572 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
573 pa_logger)
574 self.assertEqual(rv, 0, "Failed to set port config")
575
576 match.in_port = ingress_port
577
578 request = message.flow_mod()
579 request.match = match
580 request.buffer_id = 0xffffffff
581 act.port = ofp.OFPP_FLOOD
582 self.assertTrue(request.actions.add(act),
583 "Could not add flood port action")
584 pa_logger.info(request.show())
585
586 pa_logger.info("Inserting flow")
587 rv = self.controller.message_send(request)
588 self.assertTrue(rv != -1, "Error installing flow mod")
589 do_barrier(self.controller)
590
591 pa_logger.info("Sending packet to dp port " + str(ingress_port))
592 pa_logger.info("No flood port is " + str(no_flood_port))
593 self.dataplane.send(ingress_port, str(pkt))
594 no_ports = set([ingress_port, no_flood_port])
595 yes_ports = set(of_ports).difference(no_ports)
596 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700597 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700598
599 # Turn no flood off again
600 rv = port_config_set(self.controller, no_flood_port,
601 0, ofp.OFPPC_NO_FLOOD, pa_logger)
602 self.assertEqual(rv, 0, "Failed to reset port config")
603
604 #@todo Should check no other packets received
605
Dan Talayco21381562010-07-17 00:34:47 -0700606
607
Dan Talayco551befa2010-07-15 17:05:32 -0700608################################################################
609
610class BaseMatchCase(basic.SimpleDataPlane):
611 def setUp(self):
612 basic.SimpleDataPlane.setUp(self)
613 self.logger = pa_logger
614 def runTest(self):
615 self.logger.info("BaseMatchCase")
616
617class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700618 """
Dan Talayco551befa2010-07-15 17:05:32 -0700619 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700620
621 Generate a packet
622 Generate and install a matching flow without wildcard mask
623 Add action to forward to a port
624 Send the packet to the port
625 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700626 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700627
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700628 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700629 flow_match_test(self, pa_port_map)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700630
Dan Talayco551befa2010-07-15 17:05:32 -0700631class ExactMatchTagged(BaseMatchCase):
632 """
633 Exact match for all port pairs with tagged pkts
634 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700635
Dan Talayco551befa2010-07-15 17:05:32 -0700636 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700637 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700638 flow_match_test(self, pa_port_map, dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700639
Dan Talayco551befa2010-07-15 17:05:32 -0700640class ExactMatchTaggedMany(BaseMatchCase):
641 """
642 ExactMatchTagged with many VLANS
643 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700644
Dan Talayco551befa2010-07-15 17:05:32 -0700645 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700646 for vid in range(2,100,10):
Dan Talayco551befa2010-07-15 17:05:32 -0700647 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
648 for vid in range(100,4000,389):
649 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
650 flow_match_test(self, pa_port_map, dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700651
Dan Talayco551befa2010-07-15 17:05:32 -0700652# Don't run by default
653test_prio["ExactMatchTaggedMany"] = -1
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700654
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700655
Dan Talayco551befa2010-07-15 17:05:32 -0700656class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700657 """
658 Exercise wildcard matching for all ports
659
660 Generate a packet
661 Generate and install a matching flow with wildcard mask
662 Add action to forward to a port
663 Send the packet to the port
664 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700665 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700666 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700667 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700668 for wc in WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -0700669 if wc & ofp.OFPFW_DL_VLAN:
670 dl_vlan = 0
671 else:
672 dl_vlan = -1
673 flow_match_test(self, pa_port_map, wildcards=wc,
674 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700675
Dan Talayco551befa2010-07-15 17:05:32 -0700676class SingleWildcardMatchTagged(BaseMatchCase):
677 """
678 SingleWildcardMatch with tagged packets
679 """
680 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700681 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700682 for wc in WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700683 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -0700684 max_test=10)
685
686class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700687 """
Dan Talayco80b54ed2010-07-13 09:48:35 -0700688 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700689
690 Generate a packet
691 Generate and install a matching flow with wildcard all except one filed
692 Add action to forward to a port
693 Send the packet to the port
694 Verify the packet is received at all other ports (one port at a time)
695 Verify flow_expiration message is correct when command option is set
696 """
697 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700698 for wc in WILDCARD_VALUES:
699 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco4431d542012-03-21 16:42:16 -0700700 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
701 dl_vlan = 0
702 else:
703 dl_vlan = -1
704 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
705 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700706
Dan Talayco551befa2010-07-15 17:05:32 -0700707class AllExceptOneWildcardMatchTagged(BaseMatchCase):
708 """
709 Match one field with tagged packets
710 """
711 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700712 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700713 for wc in WILDCARD_VALUES:
714 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco21381562010-07-17 00:34:47 -0700715 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
716 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -0700717
718class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700719 """
720 Create Wildcard-all flow and exercise for all ports
721
722 Generate a packet
723 Generate and install a matching flow with wildcard-all
724 Add action to forward to a port
725 Send the packet to the port
726 Verify the packet is received at all other ports (one port at a time)
727 Verify flow_expiration message is correct when command option is set
728 """
729 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700730 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700731
Dan Talayco551befa2010-07-15 17:05:32 -0700732class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700733 """
Dan Talayco551befa2010-07-15 17:05:32 -0700734 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700735 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700736 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700737 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700738 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
739 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700740
Dan Talaycoba3745c2010-07-21 21:51:08 -0700741
Dan Talayco551befa2010-07-15 17:05:32 -0700742class AddVLANTag(BaseMatchCase):
743 """
744 Add a VLAN tag to an untagged packet
745 """
746 def runTest(self):
747 new_vid = 2
748 sup_acts = supported_actions_get(self)
749 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700750 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -0700751 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700752
Dan Talayco551befa2010-07-15 17:05:32 -0700753 len = 100
754 len_w_vid = 104
755 pkt = simple_tcp_packet(pktlen=len)
756 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
757 dl_vlan=new_vid)
758 vid_act = action.action_set_vlan_vid()
759 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700760
Dan Talayco551befa2010-07-15 17:05:32 -0700761 flow_match_test(self, pa_port_map, pkt=pkt,
762 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700763
Dan Talayco551befa2010-07-15 17:05:32 -0700764class PacketOnly(basic.DataPlaneOnly):
765 """
766 Just send a packet thru the switch
767 """
768 def runTest(self):
769 pkt = simple_tcp_packet()
770 of_ports = pa_port_map.keys()
771 of_ports.sort()
772 ing_port = of_ports[0]
773 pa_logger.info("Sending packet to " + str(ing_port))
774 pa_logger.debug("Data: " + str(pkt).encode('hex'))
775 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700776
Dan Talayco551befa2010-07-15 17:05:32 -0700777class PacketOnlyTagged(basic.DataPlaneOnly):
778 """
779 Just send a packet thru the switch
780 """
781 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700782 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700783 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
784 of_ports = pa_port_map.keys()
785 of_ports.sort()
786 ing_port = of_ports[0]
787 pa_logger.info("Sending packet to " + str(ing_port))
788 pa_logger.debug("Data: " + str(pkt).encode('hex'))
789 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700790
Dan Talayco551befa2010-07-15 17:05:32 -0700791test_prio["PacketOnly"] = -1
792test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700793
Dan Talayco551befa2010-07-15 17:05:32 -0700794class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700795 """
796 Modify the VLAN ID in the VLAN tag of a tagged packet
797 """
Dan Talayco551befa2010-07-15 17:05:32 -0700798 def runTest(self):
799 old_vid = 2
800 new_vid = 3
801 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700802 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700803 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700804 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700805
Dan Talayco551befa2010-07-15 17:05:32 -0700806 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
807 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
808 vid_act = action.action_set_vlan_vid()
809 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700810
Dan Talayco551befa2010-07-15 17:05:32 -0700811 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
812 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700813
Dan Talayco551befa2010-07-15 17:05:32 -0700814class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700815 """
816 Strip the VLAN tag from a tagged packet
817 """
Dan Talayco551befa2010-07-15 17:05:32 -0700818 def runTest(self):
819 old_vid = 2
820 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700821 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700822 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700823 return
Dan Talaycof36f1082010-07-13 13:57:17 -0700824
Dan Talayco551befa2010-07-15 17:05:32 -0700825 len_w_vid = 104
826 len = 100
827 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
828 dl_vlan=old_vid)
829 exp_pkt = simple_tcp_packet(pktlen=len)
830 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700831
Dan Talayco551befa2010-07-15 17:05:32 -0700832 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
833 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700834
Dan Talayco4b2bee62010-07-20 14:10:05 -0700835def init_pkt_args():
836 """
837 Pass back a dictionary with default packet arguments
838 """
839 args = {}
840 args["dl_src"] = '00:23:45:67:89:AB'
841
842 dl_vlan_enable=False
843 dl_vlan=-1
844 if pa_config["test-params"]["vid"]:
845 dl_vlan_enable=True
846 dl_vlan = pa_config["test-params"]["vid"]
847
848# Unpack operator is ** on a dictionary
849
850 return args
851
Dan Talayco551befa2010-07-15 17:05:32 -0700852class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700853 """
854 Modify the source MAC address (TP1)
855 """
Dan Talayco551befa2010-07-15 17:05:32 -0700856 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700857 sup_acts = supported_actions_get(self)
858 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700859 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700860 return
861
862 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
863 check_test_params=True)
864 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
865 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700866
Dan Talayco551befa2010-07-15 17:05:32 -0700867class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700868 """
869 Modify the dest MAC address (TP1)
870 """
Dan Talayco551befa2010-07-15 17:05:32 -0700871 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700872 sup_acts = supported_actions_get(self)
873 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700874 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700875 return
876
877 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
878 check_test_params=True)
879 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
880 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700881
Dan Talayco551befa2010-07-15 17:05:32 -0700882class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700883 """
884 Modify the source IP address of an IP packet (TP1)
885 """
Dan Talayco551befa2010-07-15 17:05:32 -0700886 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700887 sup_acts = supported_actions_get(self)
888 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700889 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700890 return
891
892 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
893 check_test_params=True)
894 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
895 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700896
Dan Talayco551befa2010-07-15 17:05:32 -0700897class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700898 """
899 Modify the dest IP address of an IP packet (TP1)
900 """
Dan Talayco551befa2010-07-15 17:05:32 -0700901 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700902 sup_acts = supported_actions_get(self)
903 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700904 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700905 return
906
907 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
908 check_test_params=True)
909 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
910 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -0700911
912class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700913 """
914 Modify the source TCP port of a TCP packet (TP1)
915 """
Dan Talayco551befa2010-07-15 17:05:32 -0700916 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700917 sup_acts = supported_actions_get(self)
918 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700919 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700920 return
921
922 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
923 check_test_params=True)
924 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
925 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -0700926
927class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700928 """
929 Modify the dest TCP port of a TCP packet (TP1)
930 """
Dan Talayco551befa2010-07-15 17:05:32 -0700931 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700932 sup_acts = supported_actions_get(self)
933 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700934 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700935 return
936
937 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
938 check_test_params=True)
939 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
940 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -0700941
942class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700943 """
944 Modify the IP type of service of an IP packet (TP1)
945 """
Dan Talayco551befa2010-07-15 17:05:32 -0700946 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700947 sup_acts = supported_actions_get(self)
948 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700949 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700950 return
Dan Talayco551befa2010-07-15 17:05:32 -0700951
Dan Talayco4b2bee62010-07-20 14:10:05 -0700952 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
953 check_test_params=True)
954 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -0700955 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -0700956
Dan Talaycof6e76c02012-03-23 10:56:12 -0700957class ModifyL2DstMC(BaseMatchCase):
958 """
959 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -0700960 """
961 def runTest(self):
962 sup_acts = supported_actions_get(self)
963 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -0700964 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -0700965 return
966
Dan Talaycof6e76c02012-03-23 10:56:12 -0700967 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
968 check_test_params=True)
969 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -0700970 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -0700971
Dan Talaycoc948d0b2012-03-23 12:17:54 -0700972class ModifyL2DstIngress(BaseMatchCase):
973 """
974 Modify the L2 dest and send to the ingress port
975 """
976 def runTest(self):
977 sup_acts = supported_actions_get(self)
978 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
979 skip_message_emit(self, "ModifyL2dstMC test")
980 return
981
982 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
983 check_test_params=True)
984 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
985 action_list=acts, max_test=2, egr_count=0,
986 ing_port=True)
987
Dan Talaycod8ae7582012-03-23 12:24:56 -0700988class ModifyL2DstIngressMC(BaseMatchCase):
989 """
990 Modify the L2 dest and send to the ingress port
991 """
992 def runTest(self):
993 sup_acts = supported_actions_get(self)
994 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
995 skip_message_emit(self, "ModifyL2dstMC test")
996 return
997
998 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
999 check_test_params=True)
1000 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1001 action_list=acts, max_test=2, egr_count=-1,
1002 ing_port=True)
1003
Dan Talaycof6e76c02012-03-23 10:56:12 -07001004class ModifyL2SrcMC(BaseMatchCase):
1005 """
1006 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001007 """
1008 def runTest(self):
1009 sup_acts = supported_actions_get(self)
1010 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001011 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001012 return
1013
Dan Talaycof6e76c02012-03-23 10:56:12 -07001014 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1015 check_test_params=True)
1016 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001017 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001018
1019class ModifyL2SrcDstMC(BaseMatchCase):
1020 """
1021 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001022 """
1023 def runTest(self):
1024 sup_acts = supported_actions_get(self)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001025 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1026 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1027 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001028 return
1029
Dan Talaycof6e76c02012-03-23 10:56:12 -07001030 mod_fields = ['dl_dst', 'dl_src']
1031 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1032 check_test_params=True)
1033 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001034 action_list=acts, max_test=2, egr_count=-1)
1035
1036class ModifyL2DstVIDMC(BaseMatchCase):
1037 """
1038 Modify the L2 dest and send to 2 ports
1039 """
1040 def runTest(self):
1041 sup_acts = supported_actions_get(self)
1042 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1043 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1044 skip_message_emit(self, "ModifyL2DstVIDMC test")
1045 return
1046
1047 mod_fields = ['dl_dst', 'dl_vlan']
1048 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1049 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1050 check_test_params=True)
1051 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1052 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001053
Dan Talayco8a64e332012-03-28 14:53:20 -07001054# You can pick and choose these by commenting tests in or out
1055iter_classes = [
1056 basic.PacketIn,
1057 basic.PacketOut,
1058 DirectPacket,
1059 DirectTwoPorts,
1060 DirectMC,
1061 AllWildcardMatch,
1062 AllWildcardMatchTagged,
1063 SingleWildcardMatch,
1064 SingleWildcardMatchTagged,
1065 ExactMatch,
1066 ExactMatchTagged,
1067 SingleWildcardMatch,
1068 ModifyL2Src,
1069 ModifyL2Dst,
1070 ModifyL2SrcMC,
1071 ModifyL2DstMC,
1072 ModifyL2SrcDstMC
1073 ]
1074
1075class IterCases(BaseMatchCase):
1076 def runTest(self):
1077 count = test_param_get(self.config, 'iter_count', default=10)
1078 tests_done = 0
1079 pa_logger.info("Running iteration test " + str(count) + " times")
1080 start = time.time()
1081 last = start
1082 for idx in range(count):
1083 pa_logger.info("Iteration " + str(idx + 1))
1084 for cls in iter_classes:
1085 test = cls()
1086 test.inheritSetup(self)
1087 test.runTest()
1088 tests_done += 1
1089 if time.time() - last > 60:
1090 last = time.time()
1091 print("IterCases: Ran %d tests in %d " %
1092 (tests_done, last - start) +
1093 "seconds so far")
1094 stats = all_stats_get(self)
1095 last = time.time()
1096 pa_logger.info("\nIterCases ran %d tests in %d seconds." %
1097 (tests_done, last - start))
1098 pa_logger.info(" flows: %d. packets: %d. bytes: %d" %
1099 (stats["flows"], stats["packets"], stats["bytes"]))
1100 pa_logger.info(" active: %d. lookups: %d. matched %d." %
1101 (stats["active"], stats["lookups"], stats["matched"]))
1102
1103# Don't run by default
1104test_prio["IterCases"] = -1
Dan Talaycof6e76c02012-03-23 10:56:12 -07001105
Dan Talayco4b2bee62010-07-20 14:10:05 -07001106#@todo Need to implement tagged versions of the above tests
1107#
1108#@todo Implement a test case that strips tag 2, adds tag 3
1109# and modifies tag 4 to tag 5. Then verify (in addition) that
1110# tag 6 does not get modified.
1111
1112class MixedVLAN(BaseMatchCase):
1113 """
1114 Test mixture of VLAN tag actions
1115
1116 Strip tag 2 on port 1, send to port 2
1117 Add tag 3 on port 1, send to port 2
1118 Modify tag 4 to 5 on port 1, send to port 2
1119 All other traffic from port 1, send to port 3
1120 All traffic from port 2 sent to port 4
1121 Use exact matches with different packets for all mods
1122 Verify the following: (port, vid)
1123 (port 1, vid 2) => VLAN tag stripped, out port 2
1124 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1125 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1126 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1127 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1128 (port 2, no tag) => untagged packet out port 4
1129 (port 2, vid 2-6) => unmodified packet out port 4
1130
1131 Variation: Might try sending VID 5 to port 3 and check.
1132 If only VID 5 distinguishes pkt, this will fail on some platforms
1133 """
1134
1135test_prio["MixedVLAN"] = -1
1136
Dan Talayco551befa2010-07-15 17:05:32 -07001137def supported_actions_get(parent, use_cache=True):
1138 """
1139 Get the bitmap of supported actions from the switch
1140 If use_cache is false, the cached value will be updated
1141 """
1142 global cached_supported_actions
1143 if cached_supported_actions is None or not use_cache:
1144 request = message.features_request()
1145 (reply, pkt) = parent.controller.transact(request, timeout=2)
1146 parent.assertTrue(reply is not None, "Did not get response to ftr req")
1147 cached_supported_actions = reply.actions
1148 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
1149
1150 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -07001151
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001152if __name__ == "__main__":
1153 print "Please run through oft script: ./oft --test_spec=basic"