blob: ecd438eb858e81cad1e308c391d1eb4137365cc7 [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
Ed Swierk89f78352012-03-29 12:32:32 -070083 basic.test_set_init(config)
84
Dan Talayco5eba8442010-03-10 13:58:43 -080085 global pa_port_map
86 global pa_logger
87 global pa_config
88
89 pa_logger = logging.getLogger("pkt_act")
90 pa_logger.info("Initializing test set")
91 pa_port_map = config["port_map"]
92 pa_config = config
93
94class DirectPacket(basic.SimpleDataPlane):
95 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -070096 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -080097
98 Generate a packet
99 Generate and install a matching flow
100 Add action to direct the packet to an egress port
101 Send the packet to ingress dataplane port
102 Verify the packet is received at the egress port only
103 """
104 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700105 self.handleFlow()
106
107 def handleFlow(self, pkttype='TCP'):
Dan Talayco5eba8442010-03-10 13:58:43 -0800108 of_ports = pa_port_map.keys()
109 of_ports.sort()
110 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
111
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700112 if (pkttype == 'ICMP'):
113 pkt = simple_icmp_packet()
114 else:
115 pkt = simple_tcp_packet()
Dan Talayco5eba8442010-03-10 13:58:43 -0800116 match = parse.packet_to_flow_match(pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700117 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800118 self.assertTrue(match is not None,
119 "Could not generate flow match from pkt")
120 act = action.action_output()
121
122 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700123 rv = delete_all_flows(self.controller, pa_logger)
124 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700125
Dan Talayco5eba8442010-03-10 13:58:43 -0800126 ingress_port = of_ports[idx]
127 egress_port = of_ports[(idx + 1) % len(of_ports)]
128 pa_logger.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700129 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800130
131 match.in_port = ingress_port
132
133 request = message.flow_mod()
134 request.match = match
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700135
Dan Talayco5eba8442010-03-10 13:58:43 -0800136 request.buffer_id = 0xffffffff
137 act.port = egress_port
138 self.assertTrue(request.actions.add(act), "Could not add action")
139
140 pa_logger.info("Inserting flow")
141 rv = self.controller.message_send(request)
142 self.assertTrue(rv != -1, "Error installing flow mod")
143 do_barrier(self.controller)
144
145 pa_logger.info("Sending packet to dp port " +
146 str(ingress_port))
147 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700148
149 exp_pkt_arg = None
150 exp_port = None
151 if pa_config["relax"]:
152 exp_pkt_arg = pkt
153 exp_port = egress_port
154
155 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(timeout=1,
156 port_number=exp_port,
157 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800158 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700159 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800160 str(rcv_port))
161 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
162 self.assertEqual(str(pkt), str(rcv_pkt),
163 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700164
165class DirectPacketICMP(DirectPacket):
166 """
167 Send ICMP packet to single egress port
168
169 Generate a ICMP packet
170 Generate and install a matching flow
171 Add action to direct the packet to an egress port
172 Send the packet to ingress dataplane port
173 Verify the packet is received at the egress port only
174 Difference from DirectPacket test is that sent packet is ICMP
175 """
176 def runTest(self):
177 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700178
179class DirectTwoPorts(basic.SimpleDataPlane):
180 """
181 Send packet to two egress ports
182
183 Generate a packet
184 Generate and install a matching flow
185 Add action to direct the packet to two egress ports
186 Send the packet to ingress dataplane port
187 Verify the packet is received at the two egress ports
188 """
189 def runTest(self):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700190 of_ports = pa_port_map.keys()
191 of_ports.sort()
192 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
193
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700194 pkt = simple_tcp_packet()
195 match = parse.packet_to_flow_match(pkt)
196 match.wildcards &= ~ofp.OFPFW_IN_PORT
197 self.assertTrue(match is not None,
198 "Could not generate flow match from pkt")
199 act = action.action_output()
200
201 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700202 rv = delete_all_flows(self.controller, pa_logger)
203 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700204
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700205 ingress_port = of_ports[idx]
206 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
207 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
208 pa_logger.info("Ingress " + str(ingress_port) +
209 " to egress " + str(egress_port1) + " and " +
210 str(egress_port2))
211
212 match.in_port = ingress_port
213
214 request = message.flow_mod()
215 request.match = match
216 request.buffer_id = 0xffffffff
217 act.port = egress_port1
218 self.assertTrue(request.actions.add(act), "Could not add action1")
219 act.port = egress_port2
220 self.assertTrue(request.actions.add(act), "Could not add action2")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700221 # pa_logger.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700222
223 pa_logger.info("Inserting flow")
224 rv = self.controller.message_send(request)
225 self.assertTrue(rv != -1, "Error installing flow mod")
226 do_barrier(self.controller)
227
228 pa_logger.info("Sending packet to dp port " +
229 str(ingress_port))
230 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700231 yes_ports = set([egress_port1, egress_port2])
232 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700233
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700234 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700235 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700236
237class DirectMCNonIngress(basic.SimpleDataPlane):
238 """
239 Multicast to all non-ingress ports
240
241 Generate a packet
242 Generate and install a matching flow
243 Add action to direct the packet to all non-ingress ports
244 Send the packet to ingress dataplane port
245 Verify the packet is received at all non-ingress ports
246
247 Does not use the flood action
248 """
249 def runTest(self):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700250 of_ports = pa_port_map.keys()
251 of_ports.sort()
252 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
253
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700254 pkt = simple_tcp_packet()
255 match = parse.packet_to_flow_match(pkt)
256 match.wildcards &= ~ofp.OFPFW_IN_PORT
257 self.assertTrue(match is not None,
258 "Could not generate flow match from pkt")
259 act = action.action_output()
260
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700261 for ingress_port in of_ports:
262 rv = delete_all_flows(self.controller, pa_logger)
263 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700264
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700265 pa_logger.info("Ingress " + str(ingress_port) +
266 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700267 match.in_port = ingress_port
268
269 request = message.flow_mod()
270 request.match = match
271 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700272 for egress_port in of_ports:
273 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700274 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700275 act.port = egress_port
276 self.assertTrue(request.actions.add(act),
277 "Could not add output to " + str(egress_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700278 pa_logger.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700279
280 pa_logger.info("Inserting flow")
281 rv = self.controller.message_send(request)
282 self.assertTrue(rv != -1, "Error installing flow mod")
283 do_barrier(self.controller)
284
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700285 pa_logger.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700286 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700287 yes_ports = set(of_ports).difference([ingress_port])
288 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700289 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700290
Dan Talayco32fa6542010-05-11 15:54:08 -0700291
292class DirectMC(basic.SimpleDataPlane):
293 """
294 Multicast to all ports including ingress
295
296 Generate a packet
297 Generate and install a matching flow
298 Add action to direct the packet to all non-ingress ports
299 Send the packet to ingress dataplane port
300 Verify the packet is received at all ports
301
302 Does not use the flood action
303 """
304 def runTest(self):
Dan Talayco32fa6542010-05-11 15:54:08 -0700305 of_ports = pa_port_map.keys()
306 of_ports.sort()
307 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
308
Dan Talayco32fa6542010-05-11 15:54:08 -0700309 pkt = simple_tcp_packet()
310 match = parse.packet_to_flow_match(pkt)
311 match.wildcards &= ~ofp.OFPFW_IN_PORT
312 self.assertTrue(match is not None,
313 "Could not generate flow match from pkt")
314 act = action.action_output()
315
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700316 for ingress_port in of_ports:
317 rv = delete_all_flows(self.controller, pa_logger)
318 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700319
Dan Talayco32fa6542010-05-11 15:54:08 -0700320 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700321 match.in_port = ingress_port
322
323 request = message.flow_mod()
324 request.match = match
325 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700326 for egress_port in of_ports:
327 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700328 act.port = ofp.OFPP_IN_PORT
329 else:
330 act.port = egress_port
331 self.assertTrue(request.actions.add(act),
332 "Could not add output to " + str(egress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700333 # pa_logger.info(request.show())
334
335 pa_logger.info("Inserting flow")
336 rv = self.controller.message_send(request)
337 self.assertTrue(rv != -1, "Error installing flow mod")
338 do_barrier(self.controller)
339
340 pa_logger.info("Sending packet to dp port " + str(ingress_port))
341 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700342 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700343 pa_logger, pa_config)
Dan Talayco2e77a842010-05-12 15:39:46 -0700344
345class Flood(basic.SimpleDataPlane):
346 """
347 Flood to all ports except ingress
348
349 Generate a packet
350 Generate and install a matching flow
351 Add action to flood the packet
352 Send the packet to ingress dataplane port
353 Verify the packet is received at all other ports
354 """
355 def runTest(self):
Dan Talayco2e77a842010-05-12 15:39:46 -0700356 of_ports = pa_port_map.keys()
357 of_ports.sort()
358 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
359
360 pkt = simple_tcp_packet()
361 match = parse.packet_to_flow_match(pkt)
362 match.wildcards &= ~ofp.OFPFW_IN_PORT
363 self.assertTrue(match is not None,
364 "Could not generate flow match from pkt")
365 act = action.action_output()
366
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700367 for ingress_port in of_ports:
368 rv = delete_all_flows(self.controller, pa_logger)
369 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700370
Dan Talayco2e77a842010-05-12 15:39:46 -0700371 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700372 match.in_port = ingress_port
373
374 request = message.flow_mod()
375 request.match = match
376 request.buffer_id = 0xffffffff
377 act.port = ofp.OFPP_FLOOD
378 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700379 "Could not add flood port action")
Dan Talayco32fa6542010-05-11 15:54:08 -0700380 pa_logger.info(request.show())
381
382 pa_logger.info("Inserting flow")
383 rv = self.controller.message_send(request)
384 self.assertTrue(rv != -1, "Error installing flow mod")
385 do_barrier(self.controller)
386
387 pa_logger.info("Sending packet to dp port " + str(ingress_port))
388 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700389 yes_ports = set(of_ports).difference([ingress_port])
390 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700391 self, pa_logger, pa_config)
Dan Talayco3be5b062010-05-12 15:46:21 -0700392
Dan Talayco3be5b062010-05-12 15:46:21 -0700393class FloodPlusIngress(basic.SimpleDataPlane):
394 """
395 Flood to all ports plus send to ingress port
396
397 Generate a packet
398 Generate and install a matching flow
399 Add action to flood the packet
400 Add action to send to ingress port
401 Send the packet to ingress dataplane port
402 Verify the packet is received at all other ports
403 """
404 def runTest(self):
Dan Talayco3be5b062010-05-12 15:46:21 -0700405 of_ports = pa_port_map.keys()
406 of_ports.sort()
407 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
408
409 pkt = simple_tcp_packet()
410 match = parse.packet_to_flow_match(pkt)
411 match.wildcards &= ~ofp.OFPFW_IN_PORT
412 self.assertTrue(match is not None,
413 "Could not generate flow match from pkt")
414 act = action.action_output()
415
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700416 for ingress_port in of_ports:
417 rv = delete_all_flows(self.controller, pa_logger)
418 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700419
Dan Talayco3be5b062010-05-12 15:46:21 -0700420 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700421 match.in_port = ingress_port
422
423 request = message.flow_mod()
424 request.match = match
425 request.buffer_id = 0xffffffff
426 act.port = ofp.OFPP_FLOOD
427 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700428 "Could not add flood port action")
429 act.port = ofp.OFPP_IN_PORT
430 self.assertTrue(request.actions.add(act),
431 "Could not add ingress port for output")
432 pa_logger.info(request.show())
433
434 pa_logger.info("Inserting flow")
435 rv = self.controller.message_send(request)
436 self.assertTrue(rv != -1, "Error installing flow mod")
437 do_barrier(self.controller)
438
439 pa_logger.info("Sending packet to dp port " + str(ingress_port))
440 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700441 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700442 pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700443
444class All(basic.SimpleDataPlane):
445 """
446 Send to OFPP_ALL port
447
448 Generate a packet
449 Generate and install a matching flow
450 Add action to forward to OFPP_ALL
451 Send the packet to ingress dataplane port
452 Verify the packet is received at all other ports
453 """
454 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700455 of_ports = pa_port_map.keys()
456 of_ports.sort()
457 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
458
459 pkt = simple_tcp_packet()
460 match = parse.packet_to_flow_match(pkt)
461 match.wildcards &= ~ofp.OFPFW_IN_PORT
462 self.assertTrue(match is not None,
463 "Could not generate flow match from pkt")
464 act = action.action_output()
465
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700466 for ingress_port in of_ports:
467 rv = delete_all_flows(self.controller, pa_logger)
468 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700469
Dan Talayco4aa13122010-05-12 15:54:44 -0700470 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700471 match.in_port = ingress_port
472
473 request = message.flow_mod()
474 request.match = match
475 request.buffer_id = 0xffffffff
476 act.port = ofp.OFPP_ALL
477 self.assertTrue(request.actions.add(act),
478 "Could not add ALL port action")
479 pa_logger.info(request.show())
480
481 pa_logger.info("Inserting flow")
482 rv = self.controller.message_send(request)
483 self.assertTrue(rv != -1, "Error installing flow mod")
484 do_barrier(self.controller)
485
486 pa_logger.info("Sending packet to dp port " + str(ingress_port))
487 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700488 yes_ports = set(of_ports).difference([ingress_port])
489 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700490 self, pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700491
492class AllPlusIngress(basic.SimpleDataPlane):
493 """
494 Send to OFPP_ALL port and ingress port
495
496 Generate a packet
497 Generate and install a matching flow
498 Add action to forward to OFPP_ALL
499 Add action to forward to ingress port
500 Send the packet to ingress dataplane port
501 Verify the packet is received at all other ports
502 """
503 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700504 of_ports = pa_port_map.keys()
505 of_ports.sort()
506 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
507
508 pkt = simple_tcp_packet()
509 match = parse.packet_to_flow_match(pkt)
510 match.wildcards &= ~ofp.OFPFW_IN_PORT
511 self.assertTrue(match is not None,
512 "Could not generate flow match from pkt")
513 act = action.action_output()
514
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700515 for ingress_port in of_ports:
516 rv = delete_all_flows(self.controller, pa_logger)
517 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700518
Dan Talayco4aa13122010-05-12 15:54:44 -0700519 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700520 match.in_port = ingress_port
521
522 request = message.flow_mod()
523 request.match = match
524 request.buffer_id = 0xffffffff
525 act.port = ofp.OFPP_ALL
526 self.assertTrue(request.actions.add(act),
527 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700528 act.port = ofp.OFPP_IN_PORT
529 self.assertTrue(request.actions.add(act),
530 "Could not add ingress port for output")
531 pa_logger.info(request.show())
532
533 pa_logger.info("Inserting flow")
534 rv = self.controller.message_send(request)
535 self.assertTrue(rv != -1, "Error installing flow mod")
536 do_barrier(self.controller)
537
538 pa_logger.info("Sending packet to dp port " + str(ingress_port))
539 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700540 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700541 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700542
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700543class FloodMinusPort(basic.SimpleDataPlane):
544 """
545 Config port with No_Flood and test Flood action
546
547 Generate a packet
548 Generate a matching flow
549 Add action to forward to OFPP_ALL
550 Set port to no-flood
551 Send the packet to ingress dataplane port
552 Verify the packet is received at all other ports except
553 the ingress port and the no_flood port
554 """
555 def runTest(self):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700556 of_ports = pa_port_map.keys()
557 of_ports.sort()
558 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
559
560 pkt = simple_tcp_packet()
561 match = parse.packet_to_flow_match(pkt)
562 match.wildcards &= ~ofp.OFPFW_IN_PORT
563 self.assertTrue(match is not None,
564 "Could not generate flow match from pkt")
565 act = action.action_output()
566
567 for idx in range(len(of_ports)):
568 rv = delete_all_flows(self.controller, pa_logger)
569 self.assertEqual(rv, 0, "Failed to delete all flows")
570
571 ingress_port = of_ports[idx]
572 no_flood_idx = (idx + 1) % len(of_ports)
573 no_flood_port = of_ports[no_flood_idx]
574 rv = port_config_set(self.controller, no_flood_port,
575 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
576 pa_logger)
577 self.assertEqual(rv, 0, "Failed to set port config")
578
579 match.in_port = ingress_port
580
581 request = message.flow_mod()
582 request.match = match
583 request.buffer_id = 0xffffffff
584 act.port = ofp.OFPP_FLOOD
585 self.assertTrue(request.actions.add(act),
586 "Could not add flood port action")
587 pa_logger.info(request.show())
588
589 pa_logger.info("Inserting flow")
590 rv = self.controller.message_send(request)
591 self.assertTrue(rv != -1, "Error installing flow mod")
592 do_barrier(self.controller)
593
594 pa_logger.info("Sending packet to dp port " + str(ingress_port))
595 pa_logger.info("No flood port is " + str(no_flood_port))
596 self.dataplane.send(ingress_port, str(pkt))
597 no_ports = set([ingress_port, no_flood_port])
598 yes_ports = set(of_ports).difference(no_ports)
599 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700600 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700601
602 # Turn no flood off again
603 rv = port_config_set(self.controller, no_flood_port,
604 0, ofp.OFPPC_NO_FLOOD, pa_logger)
605 self.assertEqual(rv, 0, "Failed to reset port config")
606
607 #@todo Should check no other packets received
608
Dan Talayco21381562010-07-17 00:34:47 -0700609
610
Dan Talayco551befa2010-07-15 17:05:32 -0700611################################################################
612
613class BaseMatchCase(basic.SimpleDataPlane):
614 def setUp(self):
615 basic.SimpleDataPlane.setUp(self)
616 self.logger = pa_logger
617 def runTest(self):
618 self.logger.info("BaseMatchCase")
619
620class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700621 """
Dan Talayco551befa2010-07-15 17:05:32 -0700622 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700623
624 Generate a packet
625 Generate and install a matching flow without wildcard mask
626 Add action to forward to a port
627 Send the packet to the port
628 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700629 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700630
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700631 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700632 flow_match_test(self, pa_port_map)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700633
Dan Talayco551befa2010-07-15 17:05:32 -0700634class ExactMatchTagged(BaseMatchCase):
635 """
636 Exact match for all port pairs with tagged pkts
637 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700638
Dan Talayco551befa2010-07-15 17:05:32 -0700639 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700640 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700641 flow_match_test(self, pa_port_map, dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700642
Dan Talayco551befa2010-07-15 17:05:32 -0700643class ExactMatchTaggedMany(BaseMatchCase):
644 """
645 ExactMatchTagged with many VLANS
646 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700647
Dan Talayco551befa2010-07-15 17:05:32 -0700648 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700649 for vid in range(2,100,10):
Dan Talayco551befa2010-07-15 17:05:32 -0700650 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
651 for vid in range(100,4000,389):
652 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
653 flow_match_test(self, pa_port_map, dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700654
Dan Talayco551befa2010-07-15 17:05:32 -0700655# Don't run by default
656test_prio["ExactMatchTaggedMany"] = -1
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700657
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700658
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700659class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700660 """
661 SingleWildcardMatchPriority
662 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700663
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700664 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700665 self.pkt = simple_tcp_packet()
666 self.flowMsgs = {}
667
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700668 def _ClearTable(self):
669 rc = delete_all_flows(self.controller, self.logger)
670 self.assertEqual(rc, 0, "Failed to delete all flows")
671 do_barrier(self.controller)
672
673 def runTest(self):
674
675 self._Init()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700676 of_ports = pa_port_map.keys()
677 of_ports.sort()
678
679 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700680 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700681
682 # Run several combinations, each at lower priority settings.
683 # At the end of each call to runPrioFlows(), the table should
684 # be empty. If its not, we'll catch it as the priorities decreases
685 portA = of_ports[0]
686 portB = of_ports[1]
687 portC = of_ports[2]
688
689 # TODO -- these priority numbers should be validated somehow?
690 self.runPrioFlows(portA, portB, portC, 1000, 999)
691 self.runPrioFlows(portB, portC, portA, 998, 997)
692 self.runPrioFlows(portC, portA, portB, 996, 995)
693 self.runPrioFlows(portA, portC, portB, 994, 993)
694
695
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700696
697 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
698 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700699
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700700 if clearTable:
701 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700702
703 # Sanity check flow at lower priority from pA to pB
704 self.logger.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
705 % (portA, portB, portC, prioHigher, prioLower))
706
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700707 self.installFlow(prioHigher, portA, portC)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700708 self.installFlow(prioLower, portA, portB)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700709
710 return
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700711 self.verifyFlow(portA, portB)
712 self.removeFlow(prioLower)
713 # Sanity check flow at lower priority from pA to pC
714 self.installFlow(prioLower, portA, portC)
715 self.verifyFlow(portA, portC)
716 self.removeFlow(prioLower)
717
718 # Install and verify pA->pB @ prioLower
719 self.installFlow(prioLower, portA, portB)
720 self.verifyFlow(portA, portB)
721
722 # Install and verify pA->pC @ prioHigher, should override pA->pB
723 self.installFlow(prioHigher, portA, portC)
724 self.verifyFlow(portA, portC)
725 # remove pA->pC
726 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700727 # Old flow pA -> pB @ prioLower should still be active
728 self.verifyFlow(portA, portB)
729 self.removeFlow(prioLower)
730
731 # Table should be empty at this point, leave it alone as
732 # an assumption for future test runs
733
734
735
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700736 def installFlow(self, prio, inp, egp):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700737 request = flow_msg_create(self, self.pkt, ing_port=inp,
738 wildcards=ofp.OFPFW_DL_SRC,
739 egr_ports=egp)
740 request.priority = prio
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700741 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700742 self.flowMsgs[prio] = request
743
744 def removeFlow(self, prio):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700745 return
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700746 if self.flowMsgs.has_key(prio):
747 msg = self.flowMsgs[prio]
748 msg.command = ofp.OFPFC_DELETE_STRICT
749 # This *must* be set for DELETE
750 msg.out_port = ofp.OFPP_NONE
751 self.controller.message_send(msg)
752 do_barrier(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700753 else:
754 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700755
756
757 def verifyFlow(self, inp, egp):
758 self.logger.info("Pkt match test: " + str(inp) +
759 " to " + str(egp))
760 self.logger.debug("Send packet: " + str(inp) + " to "
761 + str(egp))
762 self.dataplane.send(inp, str(self.pkt))
763 receive_pkt_verify(self, egp, self.pkt, inp)
764
765
766
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700767class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
768
769 def runTest(self):
770
771 self._Init()
772
773 of_ports = pa_port_map.keys()
774 of_ports.sort()
775
776 # Install an entry from 0 -> 1 @ prio 1000
777 self._ClearTable()
778 self.installFlow(1000, of_ports[0], of_ports[1])
779 self.verifyFlow(of_ports[0], of_ports[1])
780 self.installFlow(1000, of_ports[1], of_ports[0])
781 self.verifyFlow(of_ports[1], of_ports[0])
782 self.installFlow(1001, of_ports[0], of_ports[1])
783 self.verifyFlow(of_ports[0], of_ports[1])
784 self.installFlow(1001, of_ports[1], of_ports[0])
785 self.verifyFlow(of_ports[1], of_ports[0])
786 self.removeFlow(1001)
787 self.verifyFlow(of_ports[0], of_ports[1])
788 self.removeFlow(1000)
789
790
791
792
Dan Talayco551befa2010-07-15 17:05:32 -0700793class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700794 """
795 Exercise wildcard matching for all ports
796
797 Generate a packet
798 Generate and install a matching flow with wildcard mask
799 Add action to forward to a port
800 Send the packet to the port
801 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700802 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700803 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700804 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700805 for wc in WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -0700806 if wc & ofp.OFPFW_DL_VLAN:
807 dl_vlan = 0
808 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):
Dan Talayco551befa2010-07-15 17:05:32 -0700835 for wc in WILDCARD_VALUES:
836 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco4431d542012-03-21 16:42:16 -0700837 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
838 dl_vlan = 0
839 else:
840 dl_vlan = -1
841 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
842 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700843
Dan Talayco551befa2010-07-15 17:05:32 -0700844class AllExceptOneWildcardMatchTagged(BaseMatchCase):
845 """
846 Match one field with tagged packets
847 """
848 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700849 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700850 for wc in WILDCARD_VALUES:
851 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco21381562010-07-17 00:34:47 -0700852 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
853 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -0700854
855class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700856 """
857 Create Wildcard-all flow and exercise for all ports
858
859 Generate a packet
860 Generate and install a matching flow with wildcard-all
861 Add action to forward to a port
862 Send the packet to the port
863 Verify the packet is received at all other ports (one port at a time)
864 Verify flow_expiration message is correct when command option is set
865 """
866 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700867 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700868
Dan Talayco551befa2010-07-15 17:05:32 -0700869class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700870 """
Dan Talayco551befa2010-07-15 17:05:32 -0700871 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700872 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700873 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700874 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700875 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
876 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700877
Dan Talaycoba3745c2010-07-21 21:51:08 -0700878
Dan Talayco551befa2010-07-15 17:05:32 -0700879class AddVLANTag(BaseMatchCase):
880 """
881 Add a VLAN tag to an untagged packet
882 """
883 def runTest(self):
884 new_vid = 2
885 sup_acts = supported_actions_get(self)
886 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700887 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -0700888 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700889
Dan Talayco551befa2010-07-15 17:05:32 -0700890 len = 100
891 len_w_vid = 104
892 pkt = simple_tcp_packet(pktlen=len)
893 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
894 dl_vlan=new_vid)
895 vid_act = action.action_set_vlan_vid()
896 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700897
Dan Talayco551befa2010-07-15 17:05:32 -0700898 flow_match_test(self, pa_port_map, pkt=pkt,
899 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700900
Dan Talayco551befa2010-07-15 17:05:32 -0700901class PacketOnly(basic.DataPlaneOnly):
902 """
903 Just send a packet thru the switch
904 """
905 def runTest(self):
906 pkt = simple_tcp_packet()
907 of_ports = pa_port_map.keys()
908 of_ports.sort()
909 ing_port = of_ports[0]
910 pa_logger.info("Sending packet to " + str(ing_port))
911 pa_logger.debug("Data: " + str(pkt).encode('hex'))
912 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700913
Dan Talayco551befa2010-07-15 17:05:32 -0700914class PacketOnlyTagged(basic.DataPlaneOnly):
915 """
916 Just send a packet thru the switch
917 """
918 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700919 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700920 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
921 of_ports = pa_port_map.keys()
922 of_ports.sort()
923 ing_port = of_ports[0]
924 pa_logger.info("Sending packet to " + str(ing_port))
925 pa_logger.debug("Data: " + str(pkt).encode('hex'))
926 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700927
Dan Talayco551befa2010-07-15 17:05:32 -0700928test_prio["PacketOnly"] = -1
929test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700930
Dan Talayco551befa2010-07-15 17:05:32 -0700931class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700932 """
933 Modify the VLAN ID in the VLAN tag of a tagged packet
934 """
Dan Talayco551befa2010-07-15 17:05:32 -0700935 def runTest(self):
936 old_vid = 2
937 new_vid = 3
938 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700939 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700940 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700941 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700942
Dan Talayco551befa2010-07-15 17:05:32 -0700943 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
944 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
945 vid_act = action.action_set_vlan_vid()
946 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700947
Dan Talayco551befa2010-07-15 17:05:32 -0700948 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
949 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700950
Dan Talayco551befa2010-07-15 17:05:32 -0700951class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700952 """
953 Strip the VLAN tag from a tagged packet
954 """
Dan Talayco551befa2010-07-15 17:05:32 -0700955 def runTest(self):
956 old_vid = 2
957 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700958 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700959 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700960 return
Dan Talaycof36f1082010-07-13 13:57:17 -0700961
Dan Talayco551befa2010-07-15 17:05:32 -0700962 len_w_vid = 104
963 len = 100
964 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
965 dl_vlan=old_vid)
966 exp_pkt = simple_tcp_packet(pktlen=len)
967 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700968
Dan Talayco551befa2010-07-15 17:05:32 -0700969 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
970 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700971
Dan Talayco4b2bee62010-07-20 14:10:05 -0700972def init_pkt_args():
973 """
974 Pass back a dictionary with default packet arguments
975 """
976 args = {}
977 args["dl_src"] = '00:23:45:67:89:AB'
978
979 dl_vlan_enable=False
980 dl_vlan=-1
981 if pa_config["test-params"]["vid"]:
982 dl_vlan_enable=True
983 dl_vlan = pa_config["test-params"]["vid"]
984
985# Unpack operator is ** on a dictionary
986
987 return args
988
Dan Talayco551befa2010-07-15 17:05:32 -0700989class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700990 """
991 Modify the source MAC address (TP1)
992 """
Dan Talayco551befa2010-07-15 17:05:32 -0700993 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700994 sup_acts = supported_actions_get(self)
995 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700996 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700997 return
998
999 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1000 check_test_params=True)
1001 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1002 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001003
Dan Talayco551befa2010-07-15 17:05:32 -07001004class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001005 """
1006 Modify the dest MAC address (TP1)
1007 """
Dan Talayco551befa2010-07-15 17:05:32 -07001008 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001009 sup_acts = supported_actions_get(self)
1010 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001011 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001012 return
1013
1014 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1015 check_test_params=True)
1016 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1017 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001018
Dan Talayco551befa2010-07-15 17:05:32 -07001019class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001020 """
1021 Modify the source IP address of an IP packet (TP1)
1022 """
Dan Talayco551befa2010-07-15 17:05:32 -07001023 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001024 sup_acts = supported_actions_get(self)
1025 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001026 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001027 return
1028
1029 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1030 check_test_params=True)
1031 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1032 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001033
Dan Talayco551befa2010-07-15 17:05:32 -07001034class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001035 """
1036 Modify the dest IP address of an IP packet (TP1)
1037 """
Dan Talayco551befa2010-07-15 17:05:32 -07001038 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001039 sup_acts = supported_actions_get(self)
1040 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001041 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001042 return
1043
1044 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1045 check_test_params=True)
1046 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1047 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001048
1049class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001050 """
1051 Modify the source TCP port of a TCP packet (TP1)
1052 """
Dan Talayco551befa2010-07-15 17:05:32 -07001053 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001054 sup_acts = supported_actions_get(self)
1055 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001056 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001057 return
1058
1059 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1060 check_test_params=True)
1061 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1062 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001063
1064class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001065 """
1066 Modify the dest TCP port of a TCP packet (TP1)
1067 """
Dan Talayco551befa2010-07-15 17:05:32 -07001068 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001069 sup_acts = supported_actions_get(self)
1070 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001071 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001072 return
1073
1074 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1075 check_test_params=True)
1076 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1077 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001078
1079class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001080 """
1081 Modify the IP type of service of an IP packet (TP1)
1082 """
Dan Talayco551befa2010-07-15 17:05:32 -07001083 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001084 sup_acts = supported_actions_get(self)
1085 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001086 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001087 return
Dan Talayco551befa2010-07-15 17:05:32 -07001088
Dan Talayco4b2bee62010-07-20 14:10:05 -07001089 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1090 check_test_params=True)
1091 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001092 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001093
Dan Talaycof6e76c02012-03-23 10:56:12 -07001094class ModifyL2DstMC(BaseMatchCase):
1095 """
1096 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001097 """
1098 def runTest(self):
1099 sup_acts = supported_actions_get(self)
1100 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001101 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001102 return
1103
Dan Talaycof6e76c02012-03-23 10:56:12 -07001104 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1105 check_test_params=True)
1106 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001107 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001108
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001109class ModifyL2DstIngress(BaseMatchCase):
1110 """
1111 Modify the L2 dest and send to the ingress port
1112 """
1113 def runTest(self):
1114 sup_acts = supported_actions_get(self)
1115 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1116 skip_message_emit(self, "ModifyL2dstMC test")
1117 return
1118
1119 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1120 check_test_params=True)
1121 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1122 action_list=acts, max_test=2, egr_count=0,
1123 ing_port=True)
1124
Dan Talaycod8ae7582012-03-23 12:24:56 -07001125class ModifyL2DstIngressMC(BaseMatchCase):
1126 """
1127 Modify the L2 dest and send to the ingress port
1128 """
1129 def runTest(self):
1130 sup_acts = supported_actions_get(self)
1131 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1132 skip_message_emit(self, "ModifyL2dstMC test")
1133 return
1134
1135 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1136 check_test_params=True)
1137 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1138 action_list=acts, max_test=2, egr_count=-1,
1139 ing_port=True)
1140
Dan Talaycof6e76c02012-03-23 10:56:12 -07001141class ModifyL2SrcMC(BaseMatchCase):
1142 """
1143 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001144 """
1145 def runTest(self):
1146 sup_acts = supported_actions_get(self)
1147 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001148 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001149 return
1150
Dan Talaycof6e76c02012-03-23 10:56:12 -07001151 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1152 check_test_params=True)
1153 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001154 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001155
1156class ModifyL2SrcDstMC(BaseMatchCase):
1157 """
1158 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001159 """
1160 def runTest(self):
1161 sup_acts = supported_actions_get(self)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001162 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1163 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1164 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001165 return
1166
Dan Talaycof6e76c02012-03-23 10:56:12 -07001167 mod_fields = ['dl_dst', 'dl_src']
1168 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1169 check_test_params=True)
1170 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001171 action_list=acts, max_test=2, egr_count=-1)
1172
1173class ModifyL2DstVIDMC(BaseMatchCase):
1174 """
1175 Modify the L2 dest and send to 2 ports
1176 """
1177 def runTest(self):
1178 sup_acts = supported_actions_get(self)
1179 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1180 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1181 skip_message_emit(self, "ModifyL2DstVIDMC test")
1182 return
1183
1184 mod_fields = ['dl_dst', 'dl_vlan']
1185 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1186 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1187 check_test_params=True)
1188 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1189 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001190
Dan Talayco8a64e332012-03-28 14:53:20 -07001191# You can pick and choose these by commenting tests in or out
1192iter_classes = [
1193 basic.PacketIn,
1194 basic.PacketOut,
1195 DirectPacket,
1196 DirectTwoPorts,
1197 DirectMC,
1198 AllWildcardMatch,
1199 AllWildcardMatchTagged,
1200 SingleWildcardMatch,
1201 SingleWildcardMatchTagged,
1202 ExactMatch,
1203 ExactMatchTagged,
1204 SingleWildcardMatch,
1205 ModifyL2Src,
1206 ModifyL2Dst,
1207 ModifyL2SrcMC,
1208 ModifyL2DstMC,
1209 ModifyL2SrcDstMC
1210 ]
1211
1212class IterCases(BaseMatchCase):
1213 def runTest(self):
1214 count = test_param_get(self.config, 'iter_count', default=10)
1215 tests_done = 0
1216 pa_logger.info("Running iteration test " + str(count) + " times")
1217 start = time.time()
1218 last = start
1219 for idx in range(count):
1220 pa_logger.info("Iteration " + str(idx + 1))
1221 for cls in iter_classes:
1222 test = cls()
1223 test.inheritSetup(self)
1224 test.runTest()
1225 tests_done += 1
1226 if time.time() - last > 60:
1227 last = time.time()
1228 print("IterCases: Ran %d tests in %d " %
1229 (tests_done, last - start) +
1230 "seconds so far")
1231 stats = all_stats_get(self)
1232 last = time.time()
1233 pa_logger.info("\nIterCases ran %d tests in %d seconds." %
1234 (tests_done, last - start))
1235 pa_logger.info(" flows: %d. packets: %d. bytes: %d" %
1236 (stats["flows"], stats["packets"], stats["bytes"]))
1237 pa_logger.info(" active: %d. lookups: %d. matched %d." %
1238 (stats["active"], stats["lookups"], stats["matched"]))
1239
1240# Don't run by default
1241test_prio["IterCases"] = -1
Dan Talaycof6e76c02012-03-23 10:56:12 -07001242
Dan Talayco4b2bee62010-07-20 14:10:05 -07001243#@todo Need to implement tagged versions of the above tests
1244#
1245#@todo Implement a test case that strips tag 2, adds tag 3
1246# and modifies tag 4 to tag 5. Then verify (in addition) that
1247# tag 6 does not get modified.
1248
1249class MixedVLAN(BaseMatchCase):
1250 """
1251 Test mixture of VLAN tag actions
1252
1253 Strip tag 2 on port 1, send to port 2
1254 Add tag 3 on port 1, send to port 2
1255 Modify tag 4 to 5 on port 1, send to port 2
1256 All other traffic from port 1, send to port 3
1257 All traffic from port 2 sent to port 4
1258 Use exact matches with different packets for all mods
1259 Verify the following: (port, vid)
1260 (port 1, vid 2) => VLAN tag stripped, out port 2
1261 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1262 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1263 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1264 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1265 (port 2, no tag) => untagged packet out port 4
1266 (port 2, vid 2-6) => unmodified packet out port 4
1267
1268 Variation: Might try sending VID 5 to port 3 and check.
1269 If only VID 5 distinguishes pkt, this will fail on some platforms
1270 """
1271
1272test_prio["MixedVLAN"] = -1
1273
Dan Talayco551befa2010-07-15 17:05:32 -07001274def supported_actions_get(parent, use_cache=True):
1275 """
1276 Get the bitmap of supported actions from the switch
1277 If use_cache is false, the cached value will be updated
1278 """
1279 global cached_supported_actions
1280 if cached_supported_actions is None or not use_cache:
1281 request = message.features_request()
1282 (reply, pkt) = parent.controller.transact(request, timeout=2)
1283 parent.assertTrue(reply is not None, "Did not get response to ftr req")
1284 cached_supported_actions = reply.actions
1285 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
1286
1287 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -07001288
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001289if __name__ == "__main__":
1290 print "Please run through oft script: ./oft --test_spec=basic"