blob: b79c633984186c3708356550408c53be6d8dc86f [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
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700133
Dan Talayco5eba8442010-03-10 13:58:43 -0800134 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
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700657class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700658 """
659 SingleWildcardMatchPriority
660 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700661
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700662 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700663 self.pkt = simple_tcp_packet()
664 self.flowMsgs = {}
665
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700666 def _ClearTable(self):
667 rc = delete_all_flows(self.controller, self.logger)
668 self.assertEqual(rc, 0, "Failed to delete all flows")
669 do_barrier(self.controller)
670
671 def runTest(self):
672
673 self._Init()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700674 of_ports = pa_port_map.keys()
675 of_ports.sort()
676
677 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700678 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700679
680 # Run several combinations, each at lower priority settings.
681 # At the end of each call to runPrioFlows(), the table should
682 # be empty. If its not, we'll catch it as the priorities decreases
683 portA = of_ports[0]
684 portB = of_ports[1]
685 portC = of_ports[2]
686
687 # TODO -- these priority numbers should be validated somehow?
688 self.runPrioFlows(portA, portB, portC, 1000, 999)
689 self.runPrioFlows(portB, portC, portA, 998, 997)
690 self.runPrioFlows(portC, portA, portB, 996, 995)
691 self.runPrioFlows(portA, portC, portB, 994, 993)
692
693
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700694
695 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
696 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700697
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700698 if clearTable:
699 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700700
701 # Sanity check flow at lower priority from pA to pB
702 self.logger.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
703 % (portA, portB, portC, prioHigher, prioLower))
704
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700705 self.installFlow(prioHigher, portA, portC)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700706 self.installFlow(prioLower, portA, portB)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700707
708 return
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700709 self.verifyFlow(portA, portB)
710 self.removeFlow(prioLower)
711 # Sanity check flow at lower priority from pA to pC
712 self.installFlow(prioLower, portA, portC)
713 self.verifyFlow(portA, portC)
714 self.removeFlow(prioLower)
715
716 # Install and verify pA->pB @ prioLower
717 self.installFlow(prioLower, portA, portB)
718 self.verifyFlow(portA, portB)
719
720 # Install and verify pA->pC @ prioHigher, should override pA->pB
721 self.installFlow(prioHigher, portA, portC)
722 self.verifyFlow(portA, portC)
723 # remove pA->pC
724 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700725 # Old flow pA -> pB @ prioLower should still be active
726 self.verifyFlow(portA, portB)
727 self.removeFlow(prioLower)
728
729 # Table should be empty at this point, leave it alone as
730 # an assumption for future test runs
731
732
733
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700734 def installFlow(self, prio, inp, egp):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700735 request = flow_msg_create(self, self.pkt, ing_port=inp,
736 wildcards=ofp.OFPFW_DL_SRC,
737 egr_ports=egp)
738 request.priority = prio
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700739 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700740 self.flowMsgs[prio] = request
741
742 def removeFlow(self, prio):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700743 return
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700744 if self.flowMsgs.has_key(prio):
745 msg = self.flowMsgs[prio]
746 msg.command = ofp.OFPFC_DELETE_STRICT
747 # This *must* be set for DELETE
748 msg.out_port = ofp.OFPP_NONE
749 self.controller.message_send(msg)
750 do_barrier(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700751 else:
752 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700753
754
755 def verifyFlow(self, inp, egp):
756 self.logger.info("Pkt match test: " + str(inp) +
757 " to " + str(egp))
758 self.logger.debug("Send packet: " + str(inp) + " to "
759 + str(egp))
760 self.dataplane.send(inp, str(self.pkt))
761 receive_pkt_verify(self, egp, self.pkt, inp)
762
763
764
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700765class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
766
767 def runTest(self):
768
769 self._Init()
770
771 of_ports = pa_port_map.keys()
772 of_ports.sort()
773
774 # Install an entry from 0 -> 1 @ prio 1000
775 self._ClearTable()
776 self.installFlow(1000, of_ports[0], of_ports[1])
777 self.verifyFlow(of_ports[0], of_ports[1])
778 self.installFlow(1000, of_ports[1], of_ports[0])
779 self.verifyFlow(of_ports[1], of_ports[0])
780 self.installFlow(1001, of_ports[0], of_ports[1])
781 self.verifyFlow(of_ports[0], of_ports[1])
782 self.installFlow(1001, of_ports[1], of_ports[0])
783 self.verifyFlow(of_ports[1], of_ports[0])
784 self.removeFlow(1001)
785 self.verifyFlow(of_ports[0], of_ports[1])
786 self.removeFlow(1000)
787
788
789
790
Dan Talayco551befa2010-07-15 17:05:32 -0700791class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700792 """
793 Exercise wildcard matching for all ports
794
795 Generate a packet
796 Generate and install a matching flow with wildcard mask
797 Add action to forward to a port
798 Send the packet to the port
799 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700800 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700801 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700802 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -0700803 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700804 for wc in WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -0700805 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -0700806 # Set nonzero VLAN id to avoid sending priority-tagged packet
807 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -0700808 else:
809 dl_vlan = -1
810 flow_match_test(self, pa_port_map, wildcards=wc,
811 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700812
Dan Talayco551befa2010-07-15 17:05:32 -0700813class SingleWildcardMatchTagged(BaseMatchCase):
814 """
815 SingleWildcardMatch with tagged packets
816 """
817 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700818 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700819 for wc in WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700820 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -0700821 max_test=10)
822
823class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700824 """
Dan Talayco80b54ed2010-07-13 09:48:35 -0700825 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700826
827 Generate a packet
828 Generate and install a matching flow with wildcard all except one filed
829 Add action to forward to a port
830 Send the packet to the port
831 Verify the packet is received at all other ports (one port at a time)
832 Verify flow_expiration message is correct when command option is set
833 """
834 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -0700835 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700836 for wc in WILDCARD_VALUES:
837 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco4431d542012-03-21 16:42:16 -0700838 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -0700839 # Set nonzero VLAN id to avoid sending priority-tagged packet
840 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -0700841 else:
842 dl_vlan = -1
843 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
844 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700845
Dan Talayco551befa2010-07-15 17:05:32 -0700846class AllExceptOneWildcardMatchTagged(BaseMatchCase):
847 """
848 Match one field with tagged packets
849 """
850 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700851 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700852 for wc in WILDCARD_VALUES:
853 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco21381562010-07-17 00:34:47 -0700854 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
855 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -0700856
857class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700858 """
859 Create Wildcard-all flow and exercise for all ports
860
861 Generate a packet
862 Generate and install a matching flow with wildcard-all
863 Add action to forward to a port
864 Send the packet to the port
865 Verify the packet is received at all other ports (one port at a time)
866 Verify flow_expiration message is correct when command option is set
867 """
868 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700869 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700870
Dan Talayco551befa2010-07-15 17:05:32 -0700871class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700872 """
Dan Talayco551befa2010-07-15 17:05:32 -0700873 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700874 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700875 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700876 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700877 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
878 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700879
Dan Talaycoba3745c2010-07-21 21:51:08 -0700880
Dan Talayco551befa2010-07-15 17:05:32 -0700881class AddVLANTag(BaseMatchCase):
882 """
883 Add a VLAN tag to an untagged packet
884 """
885 def runTest(self):
886 new_vid = 2
887 sup_acts = supported_actions_get(self)
888 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700889 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -0700890 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700891
Dan Talayco551befa2010-07-15 17:05:32 -0700892 len = 100
893 len_w_vid = 104
894 pkt = simple_tcp_packet(pktlen=len)
895 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
896 dl_vlan=new_vid)
897 vid_act = action.action_set_vlan_vid()
898 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700899
Dan Talayco551befa2010-07-15 17:05:32 -0700900 flow_match_test(self, pa_port_map, pkt=pkt,
901 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700902
Dan Talayco551befa2010-07-15 17:05:32 -0700903class PacketOnly(basic.DataPlaneOnly):
904 """
905 Just send a packet thru the switch
906 """
907 def runTest(self):
908 pkt = simple_tcp_packet()
909 of_ports = pa_port_map.keys()
910 of_ports.sort()
911 ing_port = of_ports[0]
912 pa_logger.info("Sending packet to " + str(ing_port))
913 pa_logger.debug("Data: " + str(pkt).encode('hex'))
914 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700915
Dan Talayco551befa2010-07-15 17:05:32 -0700916class PacketOnlyTagged(basic.DataPlaneOnly):
917 """
918 Just send a packet thru the switch
919 """
920 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700921 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700922 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
923 of_ports = pa_port_map.keys()
924 of_ports.sort()
925 ing_port = of_ports[0]
926 pa_logger.info("Sending packet to " + str(ing_port))
927 pa_logger.debug("Data: " + str(pkt).encode('hex'))
928 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700929
Dan Talayco551befa2010-07-15 17:05:32 -0700930test_prio["PacketOnly"] = -1
931test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700932
Dan Talayco551befa2010-07-15 17:05:32 -0700933class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700934 """
935 Modify the VLAN ID in the VLAN tag of a tagged packet
936 """
Dan Talayco551befa2010-07-15 17:05:32 -0700937 def runTest(self):
938 old_vid = 2
939 new_vid = 3
940 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700941 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700942 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700943 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700944
Dan Talayco551befa2010-07-15 17:05:32 -0700945 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
946 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
947 vid_act = action.action_set_vlan_vid()
948 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700949
Dan Talayco551befa2010-07-15 17:05:32 -0700950 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
951 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700952
Dan Talayco551befa2010-07-15 17:05:32 -0700953class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700954 """
955 Strip the VLAN tag from a tagged packet
956 """
Dan Talayco551befa2010-07-15 17:05:32 -0700957 def runTest(self):
958 old_vid = 2
959 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700960 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700961 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700962 return
Dan Talaycof36f1082010-07-13 13:57:17 -0700963
Dan Talayco551befa2010-07-15 17:05:32 -0700964 len_w_vid = 104
965 len = 100
966 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
967 dl_vlan=old_vid)
968 exp_pkt = simple_tcp_packet(pktlen=len)
969 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700970
Dan Talayco551befa2010-07-15 17:05:32 -0700971 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
972 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700973
Dan Talayco4b2bee62010-07-20 14:10:05 -0700974def init_pkt_args():
975 """
976 Pass back a dictionary with default packet arguments
977 """
978 args = {}
979 args["dl_src"] = '00:23:45:67:89:AB'
980
981 dl_vlan_enable=False
982 dl_vlan=-1
983 if pa_config["test-params"]["vid"]:
984 dl_vlan_enable=True
985 dl_vlan = pa_config["test-params"]["vid"]
986
987# Unpack operator is ** on a dictionary
988
989 return args
990
Dan Talayco551befa2010-07-15 17:05:32 -0700991class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700992 """
993 Modify the source MAC address (TP1)
994 """
Dan Talayco551befa2010-07-15 17:05:32 -0700995 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700996 sup_acts = supported_actions_get(self)
997 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700998 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700999 return
1000
1001 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1002 check_test_params=True)
1003 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1004 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001005
Dan Talayco551befa2010-07-15 17:05:32 -07001006class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001007 """
1008 Modify the dest MAC address (TP1)
1009 """
Dan Talayco551befa2010-07-15 17:05:32 -07001010 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001011 sup_acts = supported_actions_get(self)
1012 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001013 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001014 return
1015
1016 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1017 check_test_params=True)
1018 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1019 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001020
Dan Talayco551befa2010-07-15 17:05:32 -07001021class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001022 """
1023 Modify the source IP address of an IP packet (TP1)
1024 """
Dan Talayco551befa2010-07-15 17:05:32 -07001025 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001026 sup_acts = supported_actions_get(self)
1027 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001028 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001029 return
1030
1031 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1032 check_test_params=True)
1033 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1034 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001035
Dan Talayco551befa2010-07-15 17:05:32 -07001036class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001037 """
1038 Modify the dest IP address of an IP packet (TP1)
1039 """
Dan Talayco551befa2010-07-15 17:05:32 -07001040 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001041 sup_acts = supported_actions_get(self)
1042 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001043 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001044 return
1045
1046 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1047 check_test_params=True)
1048 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1049 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001050
1051class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001052 """
1053 Modify the source TCP port of a TCP packet (TP1)
1054 """
Dan Talayco551befa2010-07-15 17:05:32 -07001055 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001056 sup_acts = supported_actions_get(self)
1057 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001058 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001059 return
1060
1061 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1062 check_test_params=True)
1063 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1064 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001065
1066class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001067 """
1068 Modify the dest TCP port of a TCP packet (TP1)
1069 """
Dan Talayco551befa2010-07-15 17:05:32 -07001070 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001071 sup_acts = supported_actions_get(self)
1072 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001073 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001074 return
1075
1076 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1077 check_test_params=True)
1078 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1079 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001080
1081class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001082 """
1083 Modify the IP type of service of an IP packet (TP1)
1084 """
Dan Talayco551befa2010-07-15 17:05:32 -07001085 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001086 sup_acts = supported_actions_get(self)
1087 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001088 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001089 return
Dan Talayco551befa2010-07-15 17:05:32 -07001090
Dan Talayco4b2bee62010-07-20 14:10:05 -07001091 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1092 check_test_params=True)
1093 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001094 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001095
Dan Talaycof6e76c02012-03-23 10:56:12 -07001096class ModifyL2DstMC(BaseMatchCase):
1097 """
1098 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001099 """
1100 def runTest(self):
1101 sup_acts = supported_actions_get(self)
1102 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001103 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001104 return
1105
Dan Talaycof6e76c02012-03-23 10:56:12 -07001106 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1107 check_test_params=True)
1108 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001109 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001110
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001111class ModifyL2DstIngress(BaseMatchCase):
1112 """
1113 Modify the L2 dest and send to the ingress port
1114 """
1115 def runTest(self):
1116 sup_acts = supported_actions_get(self)
1117 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1118 skip_message_emit(self, "ModifyL2dstMC test")
1119 return
1120
1121 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1122 check_test_params=True)
1123 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1124 action_list=acts, max_test=2, egr_count=0,
1125 ing_port=True)
1126
Dan Talaycod8ae7582012-03-23 12:24:56 -07001127class ModifyL2DstIngressMC(BaseMatchCase):
1128 """
1129 Modify the L2 dest and send to the ingress port
1130 """
1131 def runTest(self):
1132 sup_acts = supported_actions_get(self)
1133 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1134 skip_message_emit(self, "ModifyL2dstMC test")
1135 return
1136
1137 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1138 check_test_params=True)
1139 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1140 action_list=acts, max_test=2, egr_count=-1,
1141 ing_port=True)
1142
Dan Talaycof6e76c02012-03-23 10:56:12 -07001143class ModifyL2SrcMC(BaseMatchCase):
1144 """
1145 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001146 """
1147 def runTest(self):
1148 sup_acts = supported_actions_get(self)
1149 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001150 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001151 return
1152
Dan Talaycof6e76c02012-03-23 10:56:12 -07001153 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1154 check_test_params=True)
1155 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001156 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001157
1158class ModifyL2SrcDstMC(BaseMatchCase):
1159 """
1160 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001161 """
1162 def runTest(self):
1163 sup_acts = supported_actions_get(self)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001164 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1165 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1166 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001167 return
1168
Dan Talaycof6e76c02012-03-23 10:56:12 -07001169 mod_fields = ['dl_dst', 'dl_src']
1170 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1171 check_test_params=True)
1172 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001173 action_list=acts, max_test=2, egr_count=-1)
1174
1175class ModifyL2DstVIDMC(BaseMatchCase):
1176 """
1177 Modify the L2 dest and send to 2 ports
1178 """
1179 def runTest(self):
1180 sup_acts = supported_actions_get(self)
1181 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1182 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1183 skip_message_emit(self, "ModifyL2DstVIDMC test")
1184 return
1185
1186 mod_fields = ['dl_dst', 'dl_vlan']
1187 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1188 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1189 check_test_params=True)
1190 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1191 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001192
Dan Talayco8a64e332012-03-28 14:53:20 -07001193# You can pick and choose these by commenting tests in or out
1194iter_classes = [
1195 basic.PacketIn,
1196 basic.PacketOut,
1197 DirectPacket,
1198 DirectTwoPorts,
1199 DirectMC,
1200 AllWildcardMatch,
1201 AllWildcardMatchTagged,
1202 SingleWildcardMatch,
1203 SingleWildcardMatchTagged,
1204 ExactMatch,
1205 ExactMatchTagged,
1206 SingleWildcardMatch,
1207 ModifyL2Src,
1208 ModifyL2Dst,
1209 ModifyL2SrcMC,
1210 ModifyL2DstMC,
1211 ModifyL2SrcDstMC
1212 ]
1213
1214class IterCases(BaseMatchCase):
1215 def runTest(self):
1216 count = test_param_get(self.config, 'iter_count', default=10)
1217 tests_done = 0
1218 pa_logger.info("Running iteration test " + str(count) + " times")
1219 start = time.time()
1220 last = start
1221 for idx in range(count):
1222 pa_logger.info("Iteration " + str(idx + 1))
1223 for cls in iter_classes:
1224 test = cls()
1225 test.inheritSetup(self)
1226 test.runTest()
1227 tests_done += 1
1228 if time.time() - last > 60:
1229 last = time.time()
1230 print("IterCases: Ran %d tests in %d " %
1231 (tests_done, last - start) +
1232 "seconds so far")
1233 stats = all_stats_get(self)
1234 last = time.time()
1235 pa_logger.info("\nIterCases ran %d tests in %d seconds." %
1236 (tests_done, last - start))
1237 pa_logger.info(" flows: %d. packets: %d. bytes: %d" %
1238 (stats["flows"], stats["packets"], stats["bytes"]))
1239 pa_logger.info(" active: %d. lookups: %d. matched %d." %
1240 (stats["active"], stats["lookups"], stats["matched"]))
1241
1242# Don't run by default
1243test_prio["IterCases"] = -1
Dan Talaycof6e76c02012-03-23 10:56:12 -07001244
Dan Talayco4b2bee62010-07-20 14:10:05 -07001245#@todo Need to implement tagged versions of the above tests
1246#
1247#@todo Implement a test case that strips tag 2, adds tag 3
1248# and modifies tag 4 to tag 5. Then verify (in addition) that
1249# tag 6 does not get modified.
1250
1251class MixedVLAN(BaseMatchCase):
1252 """
1253 Test mixture of VLAN tag actions
1254
1255 Strip tag 2 on port 1, send to port 2
1256 Add tag 3 on port 1, send to port 2
1257 Modify tag 4 to 5 on port 1, send to port 2
1258 All other traffic from port 1, send to port 3
1259 All traffic from port 2 sent to port 4
1260 Use exact matches with different packets for all mods
1261 Verify the following: (port, vid)
1262 (port 1, vid 2) => VLAN tag stripped, out port 2
1263 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1264 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1265 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1266 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1267 (port 2, no tag) => untagged packet out port 4
1268 (port 2, vid 2-6) => unmodified packet out port 4
1269
1270 Variation: Might try sending VID 5 to port 3 and check.
1271 If only VID 5 distinguishes pkt, this will fail on some platforms
1272 """
1273
1274test_prio["MixedVLAN"] = -1
1275
Dan Talayco551befa2010-07-15 17:05:32 -07001276def supported_actions_get(parent, use_cache=True):
1277 """
1278 Get the bitmap of supported actions from the switch
1279 If use_cache is false, the cached value will be updated
1280 """
1281 global cached_supported_actions
1282 if cached_supported_actions is None or not use_cache:
1283 request = message.features_request()
1284 (reply, pkt) = parent.controller.transact(request, timeout=2)
1285 parent.assertTrue(reply is not None, "Did not get response to ftr req")
1286 cached_supported_actions = reply.actions
1287 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
1288
1289 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -07001290
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001291if __name__ == "__main__":
1292 print "Please run through oft script: ./oft --test_spec=basic"