blob: a3280a25e49fc23048b4a069de98aaa285611976 [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 Talayco5eba8442010-03-10 13:58:43 -080073def test_set_init(config):
74 """
75 Set up function for packet action test classes
76
77 @param config The configuration dictionary; see oft
78 """
79
80 global pa_port_map
81 global pa_logger
82 global pa_config
83
84 pa_logger = logging.getLogger("pkt_act")
85 pa_logger.info("Initializing test set")
86 pa_port_map = config["port_map"]
87 pa_config = config
88
89class DirectPacket(basic.SimpleDataPlane):
90 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -070091 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -080092
93 Generate a packet
94 Generate and install a matching flow
95 Add action to direct the packet to an egress port
96 Send the packet to ingress dataplane port
97 Verify the packet is received at the egress port only
98 """
99 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700100 self.handleFlow()
101
102 def handleFlow(self, pkttype='TCP'):
Dan Talayco5eba8442010-03-10 13:58:43 -0800103 of_ports = pa_port_map.keys()
104 of_ports.sort()
105 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
106
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700107 if (pkttype == 'ICMP'):
108 pkt = simple_icmp_packet()
109 else:
110 pkt = simple_tcp_packet()
Dan Talayco5eba8442010-03-10 13:58:43 -0800111 match = parse.packet_to_flow_match(pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700112 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800113 self.assertTrue(match is not None,
114 "Could not generate flow match from pkt")
115 act = action.action_output()
116
117 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700118 rv = delete_all_flows(self.controller, pa_logger)
119 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700120
Dan Talayco5eba8442010-03-10 13:58:43 -0800121 ingress_port = of_ports[idx]
122 egress_port = of_ports[(idx + 1) % len(of_ports)]
123 pa_logger.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700124 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800125
126 match.in_port = ingress_port
127
128 request = message.flow_mod()
129 request.match = match
130 request.buffer_id = 0xffffffff
131 act.port = egress_port
132 self.assertTrue(request.actions.add(act), "Could not add action")
133
134 pa_logger.info("Inserting flow")
135 rv = self.controller.message_send(request)
136 self.assertTrue(rv != -1, "Error installing flow mod")
137 do_barrier(self.controller)
138
139 pa_logger.info("Sending packet to dp port " +
140 str(ingress_port))
141 self.dataplane.send(ingress_port, str(pkt))
142 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(timeout=1)
143 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700144 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800145 str(rcv_port))
146 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
147 self.assertEqual(str(pkt), str(rcv_pkt),
148 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700149
150class DirectPacketICMP(DirectPacket):
151 """
152 Send ICMP packet to single egress port
153
154 Generate a ICMP packet
155 Generate and install a matching flow
156 Add action to direct the packet to an egress port
157 Send the packet to ingress dataplane port
158 Verify the packet is received at the egress port only
159 Difference from DirectPacket test is that sent packet is ICMP
160 """
161 def runTest(self):
162 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700163
164class DirectTwoPorts(basic.SimpleDataPlane):
165 """
166 Send packet to two egress ports
167
168 Generate a packet
169 Generate and install a matching flow
170 Add action to direct the packet to two egress ports
171 Send the packet to ingress dataplane port
172 Verify the packet is received at the two egress ports
173 """
174 def runTest(self):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700175 of_ports = pa_port_map.keys()
176 of_ports.sort()
177 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
178
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700179 pkt = simple_tcp_packet()
180 match = parse.packet_to_flow_match(pkt)
181 match.wildcards &= ~ofp.OFPFW_IN_PORT
182 self.assertTrue(match is not None,
183 "Could not generate flow match from pkt")
184 act = action.action_output()
185
186 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700187 rv = delete_all_flows(self.controller, pa_logger)
188 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700189
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700190 ingress_port = of_ports[idx]
191 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
192 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
193 pa_logger.info("Ingress " + str(ingress_port) +
194 " to egress " + str(egress_port1) + " and " +
195 str(egress_port2))
196
197 match.in_port = ingress_port
198
199 request = message.flow_mod()
200 request.match = match
201 request.buffer_id = 0xffffffff
202 act.port = egress_port1
203 self.assertTrue(request.actions.add(act), "Could not add action1")
204 act.port = egress_port2
205 self.assertTrue(request.actions.add(act), "Could not add action2")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700206 # pa_logger.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700207
208 pa_logger.info("Inserting flow")
209 rv = self.controller.message_send(request)
210 self.assertTrue(rv != -1, "Error installing flow mod")
211 do_barrier(self.controller)
212
213 pa_logger.info("Sending packet to dp port " +
214 str(ingress_port))
215 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700216 yes_ports = set([egress_port1, egress_port2])
217 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700218
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700219 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
220 self, pa_logger)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700221
222class DirectMCNonIngress(basic.SimpleDataPlane):
223 """
224 Multicast to all non-ingress ports
225
226 Generate a packet
227 Generate and install a matching flow
228 Add action to direct the packet to all non-ingress ports
229 Send the packet to ingress dataplane port
230 Verify the packet is received at all non-ingress ports
231
232 Does not use the flood action
233 """
234 def runTest(self):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700235 of_ports = pa_port_map.keys()
236 of_ports.sort()
237 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
238
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700239 pkt = simple_tcp_packet()
240 match = parse.packet_to_flow_match(pkt)
241 match.wildcards &= ~ofp.OFPFW_IN_PORT
242 self.assertTrue(match is not None,
243 "Could not generate flow match from pkt")
244 act = action.action_output()
245
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700246 for ingress_port in of_ports:
247 rv = delete_all_flows(self.controller, pa_logger)
248 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700249
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700250 pa_logger.info("Ingress " + str(ingress_port) +
251 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700252 match.in_port = ingress_port
253
254 request = message.flow_mod()
255 request.match = match
256 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700257 for egress_port in of_ports:
258 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700259 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700260 act.port = egress_port
261 self.assertTrue(request.actions.add(act),
262 "Could not add output to " + str(egress_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700263 pa_logger.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700264
265 pa_logger.info("Inserting flow")
266 rv = self.controller.message_send(request)
267 self.assertTrue(rv != -1, "Error installing flow mod")
268 do_barrier(self.controller)
269
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700270 pa_logger.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700271 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700272 yes_ports = set(of_ports).difference([ingress_port])
273 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
274 self, pa_logger)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700275
Dan Talayco32fa6542010-05-11 15:54:08 -0700276
277class DirectMC(basic.SimpleDataPlane):
278 """
279 Multicast to all ports including ingress
280
281 Generate a packet
282 Generate and install a matching flow
283 Add action to direct the packet to all non-ingress ports
284 Send the packet to ingress dataplane port
285 Verify the packet is received at all ports
286
287 Does not use the flood action
288 """
289 def runTest(self):
Dan Talayco32fa6542010-05-11 15:54:08 -0700290 of_ports = pa_port_map.keys()
291 of_ports.sort()
292 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
293
Dan Talayco32fa6542010-05-11 15:54:08 -0700294 pkt = simple_tcp_packet()
295 match = parse.packet_to_flow_match(pkt)
296 match.wildcards &= ~ofp.OFPFW_IN_PORT
297 self.assertTrue(match is not None,
298 "Could not generate flow match from pkt")
299 act = action.action_output()
300
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700301 for ingress_port in of_ports:
302 rv = delete_all_flows(self.controller, pa_logger)
303 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700304
Dan Talayco32fa6542010-05-11 15:54:08 -0700305 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700306 match.in_port = ingress_port
307
308 request = message.flow_mod()
309 request.match = match
310 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700311 for egress_port in of_ports:
312 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700313 act.port = ofp.OFPP_IN_PORT
314 else:
315 act.port = egress_port
316 self.assertTrue(request.actions.add(act),
317 "Could not add output to " + str(egress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700318 # pa_logger.info(request.show())
319
320 pa_logger.info("Inserting flow")
321 rv = self.controller.message_send(request)
322 self.assertTrue(rv != -1, "Error installing flow mod")
323 do_barrier(self.controller)
324
325 pa_logger.info("Sending packet to dp port " + str(ingress_port))
326 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700327 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
328 pa_logger)
Dan Talayco2e77a842010-05-12 15:39:46 -0700329
330class Flood(basic.SimpleDataPlane):
331 """
332 Flood to all ports except ingress
333
334 Generate a packet
335 Generate and install a matching flow
336 Add action to flood the packet
337 Send the packet to ingress dataplane port
338 Verify the packet is received at all other ports
339 """
340 def runTest(self):
Dan Talayco2e77a842010-05-12 15:39:46 -0700341 of_ports = pa_port_map.keys()
342 of_ports.sort()
343 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
344
345 pkt = simple_tcp_packet()
346 match = parse.packet_to_flow_match(pkt)
347 match.wildcards &= ~ofp.OFPFW_IN_PORT
348 self.assertTrue(match is not None,
349 "Could not generate flow match from pkt")
350 act = action.action_output()
351
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700352 for ingress_port in of_ports:
353 rv = delete_all_flows(self.controller, pa_logger)
354 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700355
Dan Talayco2e77a842010-05-12 15:39:46 -0700356 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700357 match.in_port = ingress_port
358
359 request = message.flow_mod()
360 request.match = match
361 request.buffer_id = 0xffffffff
362 act.port = ofp.OFPP_FLOOD
363 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700364 "Could not add flood port action")
Dan Talayco32fa6542010-05-11 15:54:08 -0700365 pa_logger.info(request.show())
366
367 pa_logger.info("Inserting flow")
368 rv = self.controller.message_send(request)
369 self.assertTrue(rv != -1, "Error installing flow mod")
370 do_barrier(self.controller)
371
372 pa_logger.info("Sending packet to dp port " + str(ingress_port))
373 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700374 yes_ports = set(of_ports).difference([ingress_port])
375 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
376 self, pa_logger)
Dan Talayco3be5b062010-05-12 15:46:21 -0700377
Dan Talayco3be5b062010-05-12 15:46:21 -0700378class FloodPlusIngress(basic.SimpleDataPlane):
379 """
380 Flood to all ports plus send to ingress port
381
382 Generate a packet
383 Generate and install a matching flow
384 Add action to flood the packet
385 Add action to send to ingress port
386 Send the packet to ingress dataplane port
387 Verify the packet is received at all other ports
388 """
389 def runTest(self):
Dan Talayco3be5b062010-05-12 15:46:21 -0700390 of_ports = pa_port_map.keys()
391 of_ports.sort()
392 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
393
394 pkt = simple_tcp_packet()
395 match = parse.packet_to_flow_match(pkt)
396 match.wildcards &= ~ofp.OFPFW_IN_PORT
397 self.assertTrue(match is not None,
398 "Could not generate flow match from pkt")
399 act = action.action_output()
400
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700401 for ingress_port in of_ports:
402 rv = delete_all_flows(self.controller, pa_logger)
403 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700404
Dan Talayco3be5b062010-05-12 15:46:21 -0700405 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700406 match.in_port = ingress_port
407
408 request = message.flow_mod()
409 request.match = match
410 request.buffer_id = 0xffffffff
411 act.port = ofp.OFPP_FLOOD
412 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700413 "Could not add flood port action")
414 act.port = ofp.OFPP_IN_PORT
415 self.assertTrue(request.actions.add(act),
416 "Could not add ingress port for output")
417 pa_logger.info(request.show())
418
419 pa_logger.info("Inserting flow")
420 rv = self.controller.message_send(request)
421 self.assertTrue(rv != -1, "Error installing flow mod")
422 do_barrier(self.controller)
423
424 pa_logger.info("Sending packet to dp port " + str(ingress_port))
425 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700426 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
427 pa_logger)
Dan Talayco4aa13122010-05-12 15:54:44 -0700428
429class All(basic.SimpleDataPlane):
430 """
431 Send to OFPP_ALL port
432
433 Generate a packet
434 Generate and install a matching flow
435 Add action to forward to OFPP_ALL
436 Send the packet to ingress dataplane port
437 Verify the packet is received at all other ports
438 """
439 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700440 of_ports = pa_port_map.keys()
441 of_ports.sort()
442 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
443
444 pkt = simple_tcp_packet()
445 match = parse.packet_to_flow_match(pkt)
446 match.wildcards &= ~ofp.OFPFW_IN_PORT
447 self.assertTrue(match is not None,
448 "Could not generate flow match from pkt")
449 act = action.action_output()
450
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700451 for ingress_port in of_ports:
452 rv = delete_all_flows(self.controller, pa_logger)
453 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700454
Dan Talayco4aa13122010-05-12 15:54:44 -0700455 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700456 match.in_port = ingress_port
457
458 request = message.flow_mod()
459 request.match = match
460 request.buffer_id = 0xffffffff
461 act.port = ofp.OFPP_ALL
462 self.assertTrue(request.actions.add(act),
463 "Could not add ALL port action")
464 pa_logger.info(request.show())
465
466 pa_logger.info("Inserting flow")
467 rv = self.controller.message_send(request)
468 self.assertTrue(rv != -1, "Error installing flow mod")
469 do_barrier(self.controller)
470
471 pa_logger.info("Sending packet to dp port " + str(ingress_port))
472 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700473 yes_ports = set(of_ports).difference([ingress_port])
474 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
475 self, pa_logger)
Dan Talayco4aa13122010-05-12 15:54:44 -0700476
477class AllPlusIngress(basic.SimpleDataPlane):
478 """
479 Send to OFPP_ALL port and ingress port
480
481 Generate a packet
482 Generate and install a matching flow
483 Add action to forward to OFPP_ALL
484 Add action to forward to ingress port
485 Send the packet to ingress dataplane port
486 Verify the packet is received at all other ports
487 """
488 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700489 of_ports = pa_port_map.keys()
490 of_ports.sort()
491 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
492
493 pkt = simple_tcp_packet()
494 match = parse.packet_to_flow_match(pkt)
495 match.wildcards &= ~ofp.OFPFW_IN_PORT
496 self.assertTrue(match is not None,
497 "Could not generate flow match from pkt")
498 act = action.action_output()
499
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700500 for ingress_port in of_ports:
501 rv = delete_all_flows(self.controller, pa_logger)
502 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700503
Dan Talayco4aa13122010-05-12 15:54:44 -0700504 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700505 match.in_port = ingress_port
506
507 request = message.flow_mod()
508 request.match = match
509 request.buffer_id = 0xffffffff
510 act.port = ofp.OFPP_ALL
511 self.assertTrue(request.actions.add(act),
512 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700513 act.port = ofp.OFPP_IN_PORT
514 self.assertTrue(request.actions.add(act),
515 "Could not add ingress port for output")
516 pa_logger.info(request.show())
517
518 pa_logger.info("Inserting flow")
519 rv = self.controller.message_send(request)
520 self.assertTrue(rv != -1, "Error installing flow mod")
521 do_barrier(self.controller)
522
523 pa_logger.info("Sending packet to dp port " + str(ingress_port))
524 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700525 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
526 pa_logger)
527
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700528class FloodMinusPort(basic.SimpleDataPlane):
529 """
530 Config port with No_Flood and test Flood action
531
532 Generate a packet
533 Generate a matching flow
534 Add action to forward to OFPP_ALL
535 Set port to no-flood
536 Send the packet to ingress dataplane port
537 Verify the packet is received at all other ports except
538 the ingress port and the no_flood port
539 """
540 def runTest(self):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700541 of_ports = pa_port_map.keys()
542 of_ports.sort()
543 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
544
545 pkt = simple_tcp_packet()
546 match = parse.packet_to_flow_match(pkt)
547 match.wildcards &= ~ofp.OFPFW_IN_PORT
548 self.assertTrue(match is not None,
549 "Could not generate flow match from pkt")
550 act = action.action_output()
551
552 for idx in range(len(of_ports)):
553 rv = delete_all_flows(self.controller, pa_logger)
554 self.assertEqual(rv, 0, "Failed to delete all flows")
555
556 ingress_port = of_ports[idx]
557 no_flood_idx = (idx + 1) % len(of_ports)
558 no_flood_port = of_ports[no_flood_idx]
559 rv = port_config_set(self.controller, no_flood_port,
560 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
561 pa_logger)
562 self.assertEqual(rv, 0, "Failed to set port config")
563
564 match.in_port = ingress_port
565
566 request = message.flow_mod()
567 request.match = match
568 request.buffer_id = 0xffffffff
569 act.port = ofp.OFPP_FLOOD
570 self.assertTrue(request.actions.add(act),
571 "Could not add flood port action")
572 pa_logger.info(request.show())
573
574 pa_logger.info("Inserting flow")
575 rv = self.controller.message_send(request)
576 self.assertTrue(rv != -1, "Error installing flow mod")
577 do_barrier(self.controller)
578
579 pa_logger.info("Sending packet to dp port " + str(ingress_port))
580 pa_logger.info("No flood port is " + str(no_flood_port))
581 self.dataplane.send(ingress_port, str(pkt))
582 no_ports = set([ingress_port, no_flood_port])
583 yes_ports = set(of_ports).difference(no_ports)
584 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self,
585 pa_logger)
586
587 # Turn no flood off again
588 rv = port_config_set(self.controller, no_flood_port,
589 0, ofp.OFPPC_NO_FLOOD, pa_logger)
590 self.assertEqual(rv, 0, "Failed to reset port config")
591
592 #@todo Should check no other packets received
593
Dan Talayco551befa2010-07-15 17:05:32 -0700594################################################################
595
596class BaseMatchCase(basic.SimpleDataPlane):
597 def setUp(self):
598 basic.SimpleDataPlane.setUp(self)
599 self.logger = pa_logger
600 def runTest(self):
601 self.logger.info("BaseMatchCase")
602
603class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700604 """
Dan Talayco551befa2010-07-15 17:05:32 -0700605 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700606
607 Generate a packet
608 Generate and install a matching flow without wildcard mask
609 Add action to forward to a port
610 Send the packet to the port
611 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700612 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700613
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700614 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700615 flow_match_test(self, pa_port_map)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700616
Dan Talayco551befa2010-07-15 17:05:32 -0700617class ExactMatchTagged(BaseMatchCase):
618 """
619 Exact match for all port pairs with tagged pkts
620 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700621
Dan Talayco551befa2010-07-15 17:05:32 -0700622 def runTest(self):
623 flow_match_test(self, pa_port_map, dl_vlan=1)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700624
Dan Talayco551befa2010-07-15 17:05:32 -0700625class ExactMatchTaggedMany(BaseMatchCase):
626 """
627 ExactMatchTagged with many VLANS
628 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700629
Dan Talayco551befa2010-07-15 17:05:32 -0700630 def runTest(self):
631 for vid in range(1,100,10):
632 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
633 for vid in range(100,4000,389):
634 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
635 flow_match_test(self, pa_port_map, dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700636
Dan Talayco551befa2010-07-15 17:05:32 -0700637# Don't run by default
638test_prio["ExactMatchTaggedMany"] = -1
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700639
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700640
Dan Talayco551befa2010-07-15 17:05:32 -0700641class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700642 """
643 Exercise wildcard matching for all ports
644
645 Generate a packet
646 Generate and install a matching flow with wildcard mask
647 Add action to forward to a port
648 Send the packet to the port
649 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700650 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700651 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700652 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700653 for wc in WILDCARD_VALUES:
654 flow_match_test(self, pa_port_map, wildcard=wc, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700655
Dan Talayco551befa2010-07-15 17:05:32 -0700656class SingleWildcardMatchTagged(BaseMatchCase):
657 """
658 SingleWildcardMatch with tagged packets
659 """
660 def runTest(self):
661 for wc in WILDCARD_VALUES:
662 flow_match_test(self, pa_port_map, wildcard=wc, dl_vlan=1,
663 max_test=10)
664
665class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700666 """
Dan Talayco80b54ed2010-07-13 09:48:35 -0700667 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700668
669 Generate a packet
670 Generate and install a matching flow with wildcard all except one filed
671 Add action to forward to a port
672 Send the packet to the port
673 Verify the packet is received at all other ports (one port at a time)
674 Verify flow_expiration message is correct when command option is set
675 """
676 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700677 for wc in WILDCARD_VALUES:
678 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
679 flow_match_test(self, pa_port_map, wildcard=all_exp_one_wildcard)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700680
Dan Talayco551befa2010-07-15 17:05:32 -0700681class AllExceptOneWildcardMatchTagged(BaseMatchCase):
682 """
683 Match one field with tagged packets
684 """
685 def runTest(self):
686 for wc in WILDCARD_VALUES:
687 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
688 flow_match_test(self, pa_port_map, wildcard=all_exp_one_wildcard,
689 dl_vlan=1)
690
691class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700692 """
693 Create Wildcard-all flow and exercise for all ports
694
695 Generate a packet
696 Generate and install a matching flow with wildcard-all
697 Add action to forward to a port
698 Send the packet to the port
699 Verify the packet is received at all other ports (one port at a time)
700 Verify flow_expiration message is correct when command option is set
701 """
702 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700703 flow_match_test(self, pa_port_map, wildcard=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700704
Dan Talayco551befa2010-07-15 17:05:32 -0700705class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700706 """
Dan Talayco551befa2010-07-15 17:05:32 -0700707 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700708 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700709 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700710 flow_match_test(self, pa_port_map, wildcard=ofp.OFPFW_ALL, dl_vlan=1)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700711
Dan Talayco551befa2010-07-15 17:05:32 -0700712class AddVLANTag(BaseMatchCase):
713 """
714 Add a VLAN tag to an untagged packet
715 """
716 def runTest(self):
717 new_vid = 2
718 sup_acts = supported_actions_get(self)
719 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
720 pa_logger.info("Skipping add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -0700721 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700722
Dan Talayco551befa2010-07-15 17:05:32 -0700723 len = 100
724 len_w_vid = 104
725 pkt = simple_tcp_packet(pktlen=len)
726 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
727 dl_vlan=new_vid)
728 vid_act = action.action_set_vlan_vid()
729 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700730
Dan Talayco551befa2010-07-15 17:05:32 -0700731 flow_match_test(self, pa_port_map, pkt=pkt,
732 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700733
Dan Talayco551befa2010-07-15 17:05:32 -0700734class PacketOnly(basic.DataPlaneOnly):
735 """
736 Just send a packet thru the switch
737 """
738 def runTest(self):
739 pkt = simple_tcp_packet()
740 of_ports = pa_port_map.keys()
741 of_ports.sort()
742 ing_port = of_ports[0]
743 pa_logger.info("Sending packet to " + str(ing_port))
744 pa_logger.debug("Data: " + str(pkt).encode('hex'))
745 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700746
Dan Talayco551befa2010-07-15 17:05:32 -0700747class PacketOnlyTagged(basic.DataPlaneOnly):
748 """
749 Just send a packet thru the switch
750 """
751 def runTest(self):
752 vid = 2
753 if pa_config["param"] is not None:
754 vid = pa_config["param"]
755 print "Param is " + str(pa_config["param"])
756 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
757 of_ports = pa_port_map.keys()
758 of_ports.sort()
759 ing_port = of_ports[0]
760 pa_logger.info("Sending packet to " + str(ing_port))
761 pa_logger.debug("Data: " + str(pkt).encode('hex'))
762 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700763
Dan Talayco551befa2010-07-15 17:05:32 -0700764test_prio["PacketOnly"] = -1
765test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700766
Dan Talayco551befa2010-07-15 17:05:32 -0700767class ModifyVID(BaseMatchCase):
768 def runTest(self):
769 old_vid = 2
770 new_vid = 3
771 sup_acts = supported_actions_get(self)
772 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
773 pa_logger.info("Skipping modify VLAN tag test")
774 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700775
Dan Talayco551befa2010-07-15 17:05:32 -0700776 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
777 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
778 vid_act = action.action_set_vlan_vid()
779 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700780
Dan Talayco551befa2010-07-15 17:05:32 -0700781 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
782 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700783
Dan Talayco551befa2010-07-15 17:05:32 -0700784class StripVLANTag(BaseMatchCase):
785 def runTest(self):
786 old_vid = 2
787 sup_acts = supported_actions_get(self)
788 if not(sup_acts & 1<<ofp.OFPAT_STRIP_VLAN):
789 pa_logger.info("Skipping strip VLAN tag test")
790 return
Dan Talaycof36f1082010-07-13 13:57:17 -0700791
Dan Talayco551befa2010-07-15 17:05:32 -0700792 len_w_vid = 104
793 len = 100
794 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
795 dl_vlan=old_vid)
796 exp_pkt = simple_tcp_packet(pktlen=len)
797 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700798
Dan Talayco551befa2010-07-15 17:05:32 -0700799 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
800 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700801
Dan Talayco551befa2010-07-15 17:05:32 -0700802class ModifyL2Src(BaseMatchCase):
803 def runTest(self):
804 pa_logger("To be implemented")
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700805
Dan Talayco551befa2010-07-15 17:05:32 -0700806class ModifyL2Dst(BaseMatchCase):
807 def runTest(self):
808 pa_logger("To be implemented")
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700809
Dan Talayco551befa2010-07-15 17:05:32 -0700810class ModifyL3Src(BaseMatchCase):
811 def runTest(self):
812 pa_logger("To be implemented")
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700813
Dan Talayco551befa2010-07-15 17:05:32 -0700814class ModifyL3Dst(BaseMatchCase):
815 def runTest(self):
816 pa_logger("To be implemented")
817
818class ModifyL4Src(BaseMatchCase):
819 def runTest(self):
820 pa_logger("To be implemented")
821
822class ModifyL4Dst(BaseMatchCase):
823 def runTest(self):
824 pa_logger("To be implemented")
825
826class ModifyTOS(BaseMatchCase):
827 def runTest(self):
828 pa_logger("To be implemented")
829
830test_prio["ModifyL2Src"] = -1
831test_prio["ModifyL2Dst"] = -1
832test_prio["ModifyL3Src"] = -1
833test_prio["ModifyL3Dst"] = -1
834test_prio["ModifyL4Src"] = -1
835test_prio["ModifyL4Dst"] = -1
836test_prio["ModifyTOS"] = -1
837
838def supported_actions_get(parent, use_cache=True):
839 """
840 Get the bitmap of supported actions from the switch
841 If use_cache is false, the cached value will be updated
842 """
843 global cached_supported_actions
844 if cached_supported_actions is None or not use_cache:
845 request = message.features_request()
846 (reply, pkt) = parent.controller.transact(request, timeout=2)
847 parent.assertTrue(reply is not None, "Did not get response to ftr req")
848 cached_supported_actions = reply.actions
849 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
850
851 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -0700852
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700853if __name__ == "__main__":
854 print "Please run through oft script: ./oft --test_spec=basic"