blob: 2ee1968bc8ae19aee627a14bf1248658639c8b04 [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):
658
659 def runTest(self):
660 self.pkt = simple_tcp_packet()
661 self.flowMsgs = {}
662
663 of_ports = pa_port_map.keys()
664 of_ports.sort()
665
666 # Delete the initial flow table
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 # Run several combinations, each at lower priority settings.
672 # At the end of each call to runPrioFlows(), the table should
673 # be empty. If its not, we'll catch it as the priorities decreases
674 portA = of_ports[0]
675 portB = of_ports[1]
676 portC = of_ports[2]
677
678 # TODO -- these priority numbers should be validated somehow?
679 self.runPrioFlows(portA, portB, portC, 1000, 999)
680 self.runPrioFlows(portB, portC, portA, 998, 997)
681 self.runPrioFlows(portC, portA, portB, 996, 995)
682 self.runPrioFlows(portA, portC, portB, 994, 993)
683
684
685
686 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower):
687
688 # Sanity check flow at lower priority from pA to pB
689 self.logger.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
690 % (portA, portB, portC, prioHigher, prioLower))
691
692 self.installFlow(prioLower, portA, portB)
693 self.verifyFlow(portA, portB)
694 self.removeFlow(prioLower)
695 # Sanity check flow at lower priority from pA to pC
696 self.installFlow(prioLower, portA, portC)
697 self.verifyFlow(portA, portC)
698 self.removeFlow(prioLower)
699
700 # Install and verify pA->pB @ prioLower
701 self.installFlow(prioLower, portA, portB)
702 self.verifyFlow(portA, portB)
703
704 # Install and verify pA->pC @ prioHigher, should override pA->pB
705 self.installFlow(prioHigher, portA, portC)
706 self.verifyFlow(portA, portC)
707 # remove pA->pC
708 self.removeFlow(prioHigher)
709
710 # Old flow pA -> pB @ prioLower should still be active
711 self.verifyFlow(portA, portB)
712 self.removeFlow(prioLower)
713
714 # Table should be empty at this point, leave it alone as
715 # an assumption for future test runs
716
717
718
719 def installFlow(self, prio, inp, egp, clearTable=False):
720 request = flow_msg_create(self, self.pkt, ing_port=inp,
721 wildcards=ofp.OFPFW_DL_SRC,
722 egr_ports=egp)
723 request.priority = prio
724 flow_msg_install(self, request, clear_table=clearTable)
725 self.flowMsgs[prio] = request
726
727 def removeFlow(self, prio):
728 if self.flowMsgs.has_key(prio):
729 msg = self.flowMsgs[prio]
730 msg.command = ofp.OFPFC_DELETE_STRICT
731 # This *must* be set for DELETE
732 msg.out_port = ofp.OFPP_NONE
733 self.controller.message_send(msg)
734 do_barrier(self.controller)
735
736
737 def verifyFlow(self, inp, egp):
738 self.logger.info("Pkt match test: " + str(inp) +
739 " to " + str(egp))
740 self.logger.debug("Send packet: " + str(inp) + " to "
741 + str(egp))
742 self.dataplane.send(inp, str(self.pkt))
743 receive_pkt_verify(self, egp, self.pkt, inp)
744
745
746
Dan Talayco551befa2010-07-15 17:05:32 -0700747class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700748 """
749 Exercise wildcard matching for all ports
750
751 Generate a packet
752 Generate and install a matching flow with wildcard mask
753 Add action to forward to a port
754 Send the packet to the port
755 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700756 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700757 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700758 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700759 for wc in WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -0700760 if wc & ofp.OFPFW_DL_VLAN:
761 dl_vlan = 0
762 else:
763 dl_vlan = -1
764 flow_match_test(self, pa_port_map, wildcards=wc,
765 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700766
Dan Talayco551befa2010-07-15 17:05:32 -0700767class SingleWildcardMatchTagged(BaseMatchCase):
768 """
769 SingleWildcardMatch with tagged packets
770 """
771 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700772 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700773 for wc in WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700774 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -0700775 max_test=10)
776
777class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700778 """
Dan Talayco80b54ed2010-07-13 09:48:35 -0700779 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700780
781 Generate a packet
782 Generate and install a matching flow with wildcard all except one filed
783 Add action to forward to a port
784 Send the packet to the port
785 Verify the packet is received at all other ports (one port at a time)
786 Verify flow_expiration message is correct when command option is set
787 """
788 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700789 for wc in WILDCARD_VALUES:
790 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco4431d542012-03-21 16:42:16 -0700791 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
792 dl_vlan = 0
793 else:
794 dl_vlan = -1
795 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
796 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700797
Dan Talayco551befa2010-07-15 17:05:32 -0700798class AllExceptOneWildcardMatchTagged(BaseMatchCase):
799 """
800 Match one field with tagged packets
801 """
802 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -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:
805 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco21381562010-07-17 00:34:47 -0700806 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
807 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -0700808
809class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700810 """
811 Create Wildcard-all flow and exercise for all ports
812
813 Generate a packet
814 Generate and install a matching flow with wildcard-all
815 Add action to forward to a port
816 Send the packet to the port
817 Verify the packet is received at all other ports (one port at a time)
818 Verify flow_expiration message is correct when command option is set
819 """
820 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700821 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700822
Dan Talayco551befa2010-07-15 17:05:32 -0700823class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700824 """
Dan Talayco551befa2010-07-15 17:05:32 -0700825 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700826 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700827 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700828 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700829 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
830 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700831
Dan Talaycoba3745c2010-07-21 21:51:08 -0700832
Dan Talayco551befa2010-07-15 17:05:32 -0700833class AddVLANTag(BaseMatchCase):
834 """
835 Add a VLAN tag to an untagged packet
836 """
837 def runTest(self):
838 new_vid = 2
839 sup_acts = supported_actions_get(self)
840 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700841 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -0700842 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700843
Dan Talayco551befa2010-07-15 17:05:32 -0700844 len = 100
845 len_w_vid = 104
846 pkt = simple_tcp_packet(pktlen=len)
847 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
848 dl_vlan=new_vid)
849 vid_act = action.action_set_vlan_vid()
850 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700851
Dan Talayco551befa2010-07-15 17:05:32 -0700852 flow_match_test(self, pa_port_map, pkt=pkt,
853 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700854
Dan Talayco551befa2010-07-15 17:05:32 -0700855class PacketOnly(basic.DataPlaneOnly):
856 """
857 Just send a packet thru the switch
858 """
859 def runTest(self):
860 pkt = simple_tcp_packet()
861 of_ports = pa_port_map.keys()
862 of_ports.sort()
863 ing_port = of_ports[0]
864 pa_logger.info("Sending packet to " + str(ing_port))
865 pa_logger.debug("Data: " + str(pkt).encode('hex'))
866 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700867
Dan Talayco551befa2010-07-15 17:05:32 -0700868class PacketOnlyTagged(basic.DataPlaneOnly):
869 """
870 Just send a packet thru the switch
871 """
872 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700873 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700874 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
875 of_ports = pa_port_map.keys()
876 of_ports.sort()
877 ing_port = of_ports[0]
878 pa_logger.info("Sending packet to " + str(ing_port))
879 pa_logger.debug("Data: " + str(pkt).encode('hex'))
880 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700881
Dan Talayco551befa2010-07-15 17:05:32 -0700882test_prio["PacketOnly"] = -1
883test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700884
Dan Talayco551befa2010-07-15 17:05:32 -0700885class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700886 """
887 Modify the VLAN ID in the VLAN tag of a tagged packet
888 """
Dan Talayco551befa2010-07-15 17:05:32 -0700889 def runTest(self):
890 old_vid = 2
891 new_vid = 3
892 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700893 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700894 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700895 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700896
Dan Talayco551befa2010-07-15 17:05:32 -0700897 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
898 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
899 vid_act = action.action_set_vlan_vid()
900 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700901
Dan Talayco551befa2010-07-15 17:05:32 -0700902 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
903 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700904
Dan Talayco551befa2010-07-15 17:05:32 -0700905class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700906 """
907 Strip the VLAN tag from a tagged packet
908 """
Dan Talayco551befa2010-07-15 17:05:32 -0700909 def runTest(self):
910 old_vid = 2
911 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700912 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700913 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700914 return
Dan Talaycof36f1082010-07-13 13:57:17 -0700915
Dan Talayco551befa2010-07-15 17:05:32 -0700916 len_w_vid = 104
917 len = 100
918 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
919 dl_vlan=old_vid)
920 exp_pkt = simple_tcp_packet(pktlen=len)
921 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700922
Dan Talayco551befa2010-07-15 17:05:32 -0700923 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
924 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700925
Dan Talayco4b2bee62010-07-20 14:10:05 -0700926def init_pkt_args():
927 """
928 Pass back a dictionary with default packet arguments
929 """
930 args = {}
931 args["dl_src"] = '00:23:45:67:89:AB'
932
933 dl_vlan_enable=False
934 dl_vlan=-1
935 if pa_config["test-params"]["vid"]:
936 dl_vlan_enable=True
937 dl_vlan = pa_config["test-params"]["vid"]
938
939# Unpack operator is ** on a dictionary
940
941 return args
942
Dan Talayco551befa2010-07-15 17:05:32 -0700943class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700944 """
945 Modify the source MAC address (TP1)
946 """
Dan Talayco551befa2010-07-15 17:05:32 -0700947 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700948 sup_acts = supported_actions_get(self)
949 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700950 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700951 return
952
953 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
954 check_test_params=True)
955 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
956 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700957
Dan Talayco551befa2010-07-15 17:05:32 -0700958class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700959 """
960 Modify the dest MAC address (TP1)
961 """
Dan Talayco551befa2010-07-15 17:05:32 -0700962 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700963 sup_acts = supported_actions_get(self)
964 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700965 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700966 return
967
968 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
969 check_test_params=True)
970 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
971 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700972
Dan Talayco551befa2010-07-15 17:05:32 -0700973class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700974 """
975 Modify the source IP address of an IP packet (TP1)
976 """
Dan Talayco551befa2010-07-15 17:05:32 -0700977 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700978 sup_acts = supported_actions_get(self)
979 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700980 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700981 return
982
983 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
984 check_test_params=True)
985 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
986 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700987
Dan Talayco551befa2010-07-15 17:05:32 -0700988class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700989 """
990 Modify the dest IP address of an IP packet (TP1)
991 """
Dan Talayco551befa2010-07-15 17:05:32 -0700992 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700993 sup_acts = supported_actions_get(self)
994 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700995 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700996 return
997
998 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_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)
Dan Talayco551befa2010-07-15 17:05:32 -07001002
1003class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001004 """
1005 Modify the source TCP port of a TCP packet (TP1)
1006 """
Dan Talayco551befa2010-07-15 17:05:32 -07001007 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001008 sup_acts = supported_actions_get(self)
1009 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001010 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001011 return
1012
1013 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1014 check_test_params=True)
1015 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1016 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001017
1018class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001019 """
1020 Modify the dest TCP port of a TCP packet (TP1)
1021 """
Dan Talayco551befa2010-07-15 17:05:32 -07001022 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001023 sup_acts = supported_actions_get(self)
1024 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001025 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001026 return
1027
1028 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1029 check_test_params=True)
1030 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1031 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001032
1033class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001034 """
1035 Modify the IP type of service of an IP packet (TP1)
1036 """
Dan Talayco551befa2010-07-15 17:05:32 -07001037 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001038 sup_acts = supported_actions_get(self)
1039 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001040 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001041 return
Dan Talayco551befa2010-07-15 17:05:32 -07001042
Dan Talayco4b2bee62010-07-20 14:10:05 -07001043 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1044 check_test_params=True)
1045 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001046 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001047
Dan Talaycof6e76c02012-03-23 10:56:12 -07001048class ModifyL2DstMC(BaseMatchCase):
1049 """
1050 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001051 """
1052 def runTest(self):
1053 sup_acts = supported_actions_get(self)
1054 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001055 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001056 return
1057
Dan Talaycof6e76c02012-03-23 10:56:12 -07001058 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1059 check_test_params=True)
1060 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001061 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001062
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001063class ModifyL2DstIngress(BaseMatchCase):
1064 """
1065 Modify the L2 dest and send to the ingress port
1066 """
1067 def runTest(self):
1068 sup_acts = supported_actions_get(self)
1069 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1070 skip_message_emit(self, "ModifyL2dstMC test")
1071 return
1072
1073 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1074 check_test_params=True)
1075 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1076 action_list=acts, max_test=2, egr_count=0,
1077 ing_port=True)
1078
Dan Talaycod8ae7582012-03-23 12:24:56 -07001079class ModifyL2DstIngressMC(BaseMatchCase):
1080 """
1081 Modify the L2 dest and send to the ingress port
1082 """
1083 def runTest(self):
1084 sup_acts = supported_actions_get(self)
1085 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1086 skip_message_emit(self, "ModifyL2dstMC test")
1087 return
1088
1089 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1090 check_test_params=True)
1091 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1092 action_list=acts, max_test=2, egr_count=-1,
1093 ing_port=True)
1094
Dan Talaycof6e76c02012-03-23 10:56:12 -07001095class ModifyL2SrcMC(BaseMatchCase):
1096 """
1097 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001098 """
1099 def runTest(self):
1100 sup_acts = supported_actions_get(self)
1101 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001102 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001103 return
1104
Dan Talaycof6e76c02012-03-23 10:56:12 -07001105 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1106 check_test_params=True)
1107 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001108 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001109
1110class ModifyL2SrcDstMC(BaseMatchCase):
1111 """
1112 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001113 """
1114 def runTest(self):
1115 sup_acts = supported_actions_get(self)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001116 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1117 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1118 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001119 return
1120
Dan Talaycof6e76c02012-03-23 10:56:12 -07001121 mod_fields = ['dl_dst', 'dl_src']
1122 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1123 check_test_params=True)
1124 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001125 action_list=acts, max_test=2, egr_count=-1)
1126
1127class ModifyL2DstVIDMC(BaseMatchCase):
1128 """
1129 Modify the L2 dest and send to 2 ports
1130 """
1131 def runTest(self):
1132 sup_acts = supported_actions_get(self)
1133 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1134 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1135 skip_message_emit(self, "ModifyL2DstVIDMC test")
1136 return
1137
1138 mod_fields = ['dl_dst', 'dl_vlan']
1139 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1140 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1141 check_test_params=True)
1142 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1143 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001144
Dan Talayco8a64e332012-03-28 14:53:20 -07001145# You can pick and choose these by commenting tests in or out
1146iter_classes = [
1147 basic.PacketIn,
1148 basic.PacketOut,
1149 DirectPacket,
1150 DirectTwoPorts,
1151 DirectMC,
1152 AllWildcardMatch,
1153 AllWildcardMatchTagged,
1154 SingleWildcardMatch,
1155 SingleWildcardMatchTagged,
1156 ExactMatch,
1157 ExactMatchTagged,
1158 SingleWildcardMatch,
1159 ModifyL2Src,
1160 ModifyL2Dst,
1161 ModifyL2SrcMC,
1162 ModifyL2DstMC,
1163 ModifyL2SrcDstMC
1164 ]
1165
1166class IterCases(BaseMatchCase):
1167 def runTest(self):
1168 count = test_param_get(self.config, 'iter_count', default=10)
1169 tests_done = 0
1170 pa_logger.info("Running iteration test " + str(count) + " times")
1171 start = time.time()
1172 last = start
1173 for idx in range(count):
1174 pa_logger.info("Iteration " + str(idx + 1))
1175 for cls in iter_classes:
1176 test = cls()
1177 test.inheritSetup(self)
1178 test.runTest()
1179 tests_done += 1
1180 if time.time() - last > 60:
1181 last = time.time()
1182 print("IterCases: Ran %d tests in %d " %
1183 (tests_done, last - start) +
1184 "seconds so far")
1185 stats = all_stats_get(self)
1186 last = time.time()
1187 pa_logger.info("\nIterCases ran %d tests in %d seconds." %
1188 (tests_done, last - start))
1189 pa_logger.info(" flows: %d. packets: %d. bytes: %d" %
1190 (stats["flows"], stats["packets"], stats["bytes"]))
1191 pa_logger.info(" active: %d. lookups: %d. matched %d." %
1192 (stats["active"], stats["lookups"], stats["matched"]))
1193
1194# Don't run by default
1195test_prio["IterCases"] = -1
Dan Talaycof6e76c02012-03-23 10:56:12 -07001196
Dan Talayco4b2bee62010-07-20 14:10:05 -07001197#@todo Need to implement tagged versions of the above tests
1198#
1199#@todo Implement a test case that strips tag 2, adds tag 3
1200# and modifies tag 4 to tag 5. Then verify (in addition) that
1201# tag 6 does not get modified.
1202
1203class MixedVLAN(BaseMatchCase):
1204 """
1205 Test mixture of VLAN tag actions
1206
1207 Strip tag 2 on port 1, send to port 2
1208 Add tag 3 on port 1, send to port 2
1209 Modify tag 4 to 5 on port 1, send to port 2
1210 All other traffic from port 1, send to port 3
1211 All traffic from port 2 sent to port 4
1212 Use exact matches with different packets for all mods
1213 Verify the following: (port, vid)
1214 (port 1, vid 2) => VLAN tag stripped, out port 2
1215 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1216 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1217 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1218 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1219 (port 2, no tag) => untagged packet out port 4
1220 (port 2, vid 2-6) => unmodified packet out port 4
1221
1222 Variation: Might try sending VID 5 to port 3 and check.
1223 If only VID 5 distinguishes pkt, this will fail on some platforms
1224 """
1225
1226test_prio["MixedVLAN"] = -1
1227
Dan Talayco551befa2010-07-15 17:05:32 -07001228def supported_actions_get(parent, use_cache=True):
1229 """
1230 Get the bitmap of supported actions from the switch
1231 If use_cache is false, the cached value will be updated
1232 """
1233 global cached_supported_actions
1234 if cached_supported_actions is None or not use_cache:
1235 request = message.features_request()
1236 (reply, pkt) = parent.controller.transact(request, timeout=2)
1237 parent.assertTrue(reply is not None, "Did not get response to ftr req")
1238 cached_supported_actions = reply.actions
1239 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
1240
1241 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -07001242
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001243if __name__ == "__main__":
1244 print "Please run through oft script: ./oft --test_spec=basic"