blob: 129f96d8749cf7f4594f63a58924ff1c9d170e06 [file] [log] [blame]
Dan Talayco5eba8442010-03-10 13:58:43 -08001"""
2Test cases for testing actions taken on packets
3
4See basic.py for other info.
5
6It is recommended that these definitions be kept in their own
7namespace as different groups of tests will likely define
8similar identifiers.
9
10 The function test_set_init is called with a complete configuration
11dictionary prior to the invocation of any tests from this file.
12
13 The switch is actively attempting to contact the controller at the address
14indicated oin oft_config
15
16"""
17
Dan Talayco9f47f4d2010-06-03 13:54:37 -070018import copy
19
Dan Talayco5eba8442010-03-10 13:58:43 -080020import logging
21
22import unittest
23
24import oftest.controller as controller
25import oftest.cstruct as ofp
26import oftest.message as message
27import oftest.dataplane as dataplane
28import oftest.action as action
29import oftest.parse as parse
30import basic
Dan Talayco8a64e332012-03-28 14:53:20 -070031import time
Dan Talayco5eba8442010-03-10 13:58:43 -080032
33from testutils import *
34
35#@var port_map Local copy of the configuration map from OF port
36# numbers to OS interfaces
37pa_port_map = None
38#@var pa_logger Local logger object
39pa_logger = None
40#@var pa_config Local copy of global configuration data
41pa_config = None
42
Dan Talayco551befa2010-07-15 17:05:32 -070043# For test priority
44#@var test_prio Set test priority for local tests
45test_prio = {}
46
47WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
48 ofp.OFPFW_DL_VLAN,
49 ofp.OFPFW_DL_SRC,
50 ofp.OFPFW_DL_DST,
51 ofp.OFPFW_DL_TYPE,
52 ofp.OFPFW_NW_PROTO,
53 ofp.OFPFW_TP_SRC,
54 ofp.OFPFW_TP_DST,
55 0x3F << ofp.OFPFW_NW_SRC_SHIFT,
56 0x3F << ofp.OFPFW_NW_DST_SHIFT,
57 ofp.OFPFW_DL_VLAN_PCP,
58 ofp.OFPFW_NW_TOS]
59
60MODIFY_ACTION_VALUES = [ofp.OFPAT_SET_VLAN_VID,
61 ofp.OFPAT_SET_VLAN_PCP,
62 ofp.OFPAT_STRIP_VLAN,
63 ofp.OFPAT_SET_DL_SRC,
64 ofp.OFPAT_SET_DL_DST,
65 ofp.OFPAT_SET_NW_SRC,
66 ofp.OFPAT_SET_NW_DST,
67 ofp.OFPAT_SET_NW_TOS,
68 ofp.OFPAT_SET_TP_SRC,
69 ofp.OFPAT_SET_TP_DST]
70
71# Cache supported features to avoid transaction overhead
72cached_supported_actions = None
73
Dan Talayco21381562010-07-17 00:34:47 -070074TEST_VID_DEFAULT = 2
75
Dan Talayco5eba8442010-03-10 13:58:43 -080076def test_set_init(config):
77 """
78 Set up function for packet action test classes
79
80 @param config The configuration dictionary; see oft
81 """
82
83 global pa_port_map
84 global pa_logger
85 global pa_config
86
87 pa_logger = logging.getLogger("pkt_act")
88 pa_logger.info("Initializing test set")
89 pa_port_map = config["port_map"]
90 pa_config = config
91
92class DirectPacket(basic.SimpleDataPlane):
93 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -070094 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -080095
96 Generate a packet
97 Generate and install a matching flow
98 Add action to direct the packet to an egress port
99 Send the packet to ingress dataplane port
100 Verify the packet is received at the egress port only
101 """
102 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700103 self.handleFlow()
104
105 def handleFlow(self, pkttype='TCP'):
Dan Talayco5eba8442010-03-10 13:58:43 -0800106 of_ports = pa_port_map.keys()
107 of_ports.sort()
108 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
109
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700110 if (pkttype == 'ICMP'):
111 pkt = simple_icmp_packet()
112 else:
113 pkt = simple_tcp_packet()
Dan Talayco5eba8442010-03-10 13:58:43 -0800114 match = parse.packet_to_flow_match(pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700115 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800116 self.assertTrue(match is not None,
117 "Could not generate flow match from pkt")
118 act = action.action_output()
119
120 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700121 rv = delete_all_flows(self.controller, pa_logger)
122 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700123
Dan Talayco5eba8442010-03-10 13:58:43 -0800124 ingress_port = of_ports[idx]
125 egress_port = of_ports[(idx + 1) % len(of_ports)]
126 pa_logger.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700127 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800128
129 match.in_port = ingress_port
130
131 request = message.flow_mod()
132 request.match = match
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700133
Dan Talayco5eba8442010-03-10 13:58:43 -0800134 request.buffer_id = 0xffffffff
135 act.port = egress_port
136 self.assertTrue(request.actions.add(act), "Could not add action")
137
138 pa_logger.info("Inserting flow")
139 rv = self.controller.message_send(request)
140 self.assertTrue(rv != -1, "Error installing flow mod")
141 do_barrier(self.controller)
142
143 pa_logger.info("Sending packet to dp port " +
144 str(ingress_port))
145 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700146
147 exp_pkt_arg = None
148 exp_port = None
149 if pa_config["relax"]:
150 exp_pkt_arg = pkt
151 exp_port = egress_port
152
153 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(timeout=1,
154 port_number=exp_port,
155 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800156 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700157 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800158 str(rcv_port))
159 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
160 self.assertEqual(str(pkt), str(rcv_pkt),
161 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700162
163class DirectPacketICMP(DirectPacket):
164 """
165 Send ICMP packet to single egress port
166
167 Generate a ICMP packet
168 Generate and install a matching flow
169 Add action to direct the packet to an egress port
170 Send the packet to ingress dataplane port
171 Verify the packet is received at the egress port only
172 Difference from DirectPacket test is that sent packet is ICMP
173 """
174 def runTest(self):
175 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700176
177class DirectTwoPorts(basic.SimpleDataPlane):
178 """
179 Send packet to two egress ports
180
181 Generate a packet
182 Generate and install a matching flow
183 Add action to direct the packet to two egress ports
184 Send the packet to ingress dataplane port
185 Verify the packet is received at the two egress ports
186 """
187 def runTest(self):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700188 of_ports = pa_port_map.keys()
189 of_ports.sort()
190 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
191
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700192 pkt = simple_tcp_packet()
193 match = parse.packet_to_flow_match(pkt)
194 match.wildcards &= ~ofp.OFPFW_IN_PORT
195 self.assertTrue(match is not None,
196 "Could not generate flow match from pkt")
197 act = action.action_output()
198
199 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700200 rv = delete_all_flows(self.controller, pa_logger)
201 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700202
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700203 ingress_port = of_ports[idx]
204 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
205 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
206 pa_logger.info("Ingress " + str(ingress_port) +
207 " to egress " + str(egress_port1) + " and " +
208 str(egress_port2))
209
210 match.in_port = ingress_port
211
212 request = message.flow_mod()
213 request.match = match
214 request.buffer_id = 0xffffffff
215 act.port = egress_port1
216 self.assertTrue(request.actions.add(act), "Could not add action1")
217 act.port = egress_port2
218 self.assertTrue(request.actions.add(act), "Could not add action2")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700219 # pa_logger.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700220
221 pa_logger.info("Inserting flow")
222 rv = self.controller.message_send(request)
223 self.assertTrue(rv != -1, "Error installing flow mod")
224 do_barrier(self.controller)
225
226 pa_logger.info("Sending packet to dp port " +
227 str(ingress_port))
228 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700229 yes_ports = set([egress_port1, egress_port2])
230 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700231
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700232 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700233 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700234
235class DirectMCNonIngress(basic.SimpleDataPlane):
236 """
237 Multicast to all non-ingress ports
238
239 Generate a packet
240 Generate and install a matching flow
241 Add action to direct the packet to all non-ingress ports
242 Send the packet to ingress dataplane port
243 Verify the packet is received at all non-ingress ports
244
245 Does not use the flood action
246 """
247 def runTest(self):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700248 of_ports = pa_port_map.keys()
249 of_ports.sort()
250 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
251
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700252 pkt = simple_tcp_packet()
253 match = parse.packet_to_flow_match(pkt)
254 match.wildcards &= ~ofp.OFPFW_IN_PORT
255 self.assertTrue(match is not None,
256 "Could not generate flow match from pkt")
257 act = action.action_output()
258
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700259 for ingress_port in of_ports:
260 rv = delete_all_flows(self.controller, pa_logger)
261 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700262
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700263 pa_logger.info("Ingress " + str(ingress_port) +
264 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700265 match.in_port = ingress_port
266
267 request = message.flow_mod()
268 request.match = match
269 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700270 for egress_port in of_ports:
271 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700272 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700273 act.port = egress_port
274 self.assertTrue(request.actions.add(act),
275 "Could not add output to " + str(egress_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700276 pa_logger.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700277
278 pa_logger.info("Inserting flow")
279 rv = self.controller.message_send(request)
280 self.assertTrue(rv != -1, "Error installing flow mod")
281 do_barrier(self.controller)
282
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700283 pa_logger.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700284 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700285 yes_ports = set(of_ports).difference([ingress_port])
286 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700287 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700288
Dan Talayco32fa6542010-05-11 15:54:08 -0700289
290class DirectMC(basic.SimpleDataPlane):
291 """
292 Multicast to all ports including ingress
293
294 Generate a packet
295 Generate and install a matching flow
296 Add action to direct the packet to all non-ingress ports
297 Send the packet to ingress dataplane port
298 Verify the packet is received at all ports
299
300 Does not use the flood action
301 """
302 def runTest(self):
Dan Talayco32fa6542010-05-11 15:54:08 -0700303 of_ports = pa_port_map.keys()
304 of_ports.sort()
305 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
306
Dan Talayco32fa6542010-05-11 15:54:08 -0700307 pkt = simple_tcp_packet()
308 match = parse.packet_to_flow_match(pkt)
309 match.wildcards &= ~ofp.OFPFW_IN_PORT
310 self.assertTrue(match is not None,
311 "Could not generate flow match from pkt")
312 act = action.action_output()
313
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700314 for ingress_port in of_ports:
315 rv = delete_all_flows(self.controller, pa_logger)
316 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700317
Dan Talayco32fa6542010-05-11 15:54:08 -0700318 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700319 match.in_port = ingress_port
320
321 request = message.flow_mod()
322 request.match = match
323 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700324 for egress_port in of_ports:
325 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700326 act.port = ofp.OFPP_IN_PORT
327 else:
328 act.port = egress_port
329 self.assertTrue(request.actions.add(act),
330 "Could not add output to " + str(egress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700331 # pa_logger.info(request.show())
332
333 pa_logger.info("Inserting flow")
334 rv = self.controller.message_send(request)
335 self.assertTrue(rv != -1, "Error installing flow mod")
336 do_barrier(self.controller)
337
338 pa_logger.info("Sending packet to dp port " + str(ingress_port))
339 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700340 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700341 pa_logger, pa_config)
Dan Talayco2e77a842010-05-12 15:39:46 -0700342
343class Flood(basic.SimpleDataPlane):
344 """
345 Flood to all ports except ingress
346
347 Generate a packet
348 Generate and install a matching flow
349 Add action to flood the packet
350 Send the packet to ingress dataplane port
351 Verify the packet is received at all other ports
352 """
353 def runTest(self):
Dan Talayco2e77a842010-05-12 15:39:46 -0700354 of_ports = pa_port_map.keys()
355 of_ports.sort()
356 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
357
358 pkt = simple_tcp_packet()
359 match = parse.packet_to_flow_match(pkt)
360 match.wildcards &= ~ofp.OFPFW_IN_PORT
361 self.assertTrue(match is not None,
362 "Could not generate flow match from pkt")
363 act = action.action_output()
364
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700365 for ingress_port in of_ports:
366 rv = delete_all_flows(self.controller, pa_logger)
367 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700368
Dan Talayco2e77a842010-05-12 15:39:46 -0700369 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700370 match.in_port = ingress_port
371
372 request = message.flow_mod()
373 request.match = match
374 request.buffer_id = 0xffffffff
375 act.port = ofp.OFPP_FLOOD
376 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700377 "Could not add flood port action")
Dan Talayco32fa6542010-05-11 15:54:08 -0700378 pa_logger.info(request.show())
379
380 pa_logger.info("Inserting flow")
381 rv = self.controller.message_send(request)
382 self.assertTrue(rv != -1, "Error installing flow mod")
383 do_barrier(self.controller)
384
385 pa_logger.info("Sending packet to dp port " + str(ingress_port))
386 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700387 yes_ports = set(of_ports).difference([ingress_port])
388 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700389 self, pa_logger, pa_config)
Dan Talayco3be5b062010-05-12 15:46:21 -0700390
Dan Talayco3be5b062010-05-12 15:46:21 -0700391class FloodPlusIngress(basic.SimpleDataPlane):
392 """
393 Flood to all ports plus send to ingress port
394
395 Generate a packet
396 Generate and install a matching flow
397 Add action to flood the packet
398 Add action to send to ingress port
399 Send the packet to ingress dataplane port
400 Verify the packet is received at all other ports
401 """
402 def runTest(self):
Dan Talayco3be5b062010-05-12 15:46:21 -0700403 of_ports = pa_port_map.keys()
404 of_ports.sort()
405 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
406
407 pkt = simple_tcp_packet()
408 match = parse.packet_to_flow_match(pkt)
409 match.wildcards &= ~ofp.OFPFW_IN_PORT
410 self.assertTrue(match is not None,
411 "Could not generate flow match from pkt")
412 act = action.action_output()
413
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700414 for ingress_port in of_ports:
415 rv = delete_all_flows(self.controller, pa_logger)
416 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700417
Dan Talayco3be5b062010-05-12 15:46:21 -0700418 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700419 match.in_port = ingress_port
420
421 request = message.flow_mod()
422 request.match = match
423 request.buffer_id = 0xffffffff
424 act.port = ofp.OFPP_FLOOD
425 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700426 "Could not add flood port action")
427 act.port = ofp.OFPP_IN_PORT
428 self.assertTrue(request.actions.add(act),
429 "Could not add ingress port for output")
430 pa_logger.info(request.show())
431
432 pa_logger.info("Inserting flow")
433 rv = self.controller.message_send(request)
434 self.assertTrue(rv != -1, "Error installing flow mod")
435 do_barrier(self.controller)
436
437 pa_logger.info("Sending packet to dp port " + str(ingress_port))
438 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700439 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700440 pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700441
442class All(basic.SimpleDataPlane):
443 """
444 Send to OFPP_ALL port
445
446 Generate a packet
447 Generate and install a matching flow
448 Add action to forward to OFPP_ALL
449 Send the packet to ingress dataplane port
450 Verify the packet is received at all other ports
451 """
452 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700453 of_ports = pa_port_map.keys()
454 of_ports.sort()
455 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
456
457 pkt = simple_tcp_packet()
458 match = parse.packet_to_flow_match(pkt)
459 match.wildcards &= ~ofp.OFPFW_IN_PORT
460 self.assertTrue(match is not None,
461 "Could not generate flow match from pkt")
462 act = action.action_output()
463
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700464 for ingress_port in of_ports:
465 rv = delete_all_flows(self.controller, pa_logger)
466 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700467
Dan Talayco4aa13122010-05-12 15:54:44 -0700468 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700469 match.in_port = ingress_port
470
471 request = message.flow_mod()
472 request.match = match
473 request.buffer_id = 0xffffffff
474 act.port = ofp.OFPP_ALL
475 self.assertTrue(request.actions.add(act),
476 "Could not add ALL port action")
477 pa_logger.info(request.show())
478
479 pa_logger.info("Inserting flow")
480 rv = self.controller.message_send(request)
481 self.assertTrue(rv != -1, "Error installing flow mod")
482 do_barrier(self.controller)
483
484 pa_logger.info("Sending packet to dp port " + str(ingress_port))
485 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700486 yes_ports = set(of_ports).difference([ingress_port])
487 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700488 self, pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700489
490class AllPlusIngress(basic.SimpleDataPlane):
491 """
492 Send to OFPP_ALL port and ingress port
493
494 Generate a packet
495 Generate and install a matching flow
496 Add action to forward to OFPP_ALL
497 Add action to forward to ingress port
498 Send the packet to ingress dataplane port
499 Verify the packet is received at all other ports
500 """
501 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700502 of_ports = pa_port_map.keys()
503 of_ports.sort()
504 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
505
506 pkt = simple_tcp_packet()
507 match = parse.packet_to_flow_match(pkt)
508 match.wildcards &= ~ofp.OFPFW_IN_PORT
509 self.assertTrue(match is not None,
510 "Could not generate flow match from pkt")
511 act = action.action_output()
512
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700513 for ingress_port in of_ports:
514 rv = delete_all_flows(self.controller, pa_logger)
515 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700516
Dan Talayco4aa13122010-05-12 15:54:44 -0700517 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700518 match.in_port = ingress_port
519
520 request = message.flow_mod()
521 request.match = match
522 request.buffer_id = 0xffffffff
523 act.port = ofp.OFPP_ALL
524 self.assertTrue(request.actions.add(act),
525 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700526 act.port = ofp.OFPP_IN_PORT
527 self.assertTrue(request.actions.add(act),
528 "Could not add ingress port for output")
529 pa_logger.info(request.show())
530
531 pa_logger.info("Inserting flow")
532 rv = self.controller.message_send(request)
533 self.assertTrue(rv != -1, "Error installing flow mod")
534 do_barrier(self.controller)
535
536 pa_logger.info("Sending packet to dp port " + str(ingress_port))
537 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700538 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700539 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700540
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700541class FloodMinusPort(basic.SimpleDataPlane):
542 """
543 Config port with No_Flood and test Flood action
544
545 Generate a packet
546 Generate a matching flow
547 Add action to forward to OFPP_ALL
548 Set port to no-flood
549 Send the packet to ingress dataplane port
550 Verify the packet is received at all other ports except
551 the ingress port and the no_flood port
552 """
553 def runTest(self):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700554 of_ports = pa_port_map.keys()
555 of_ports.sort()
556 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
557
558 pkt = simple_tcp_packet()
559 match = parse.packet_to_flow_match(pkt)
560 match.wildcards &= ~ofp.OFPFW_IN_PORT
561 self.assertTrue(match is not None,
562 "Could not generate flow match from pkt")
563 act = action.action_output()
564
565 for idx in range(len(of_ports)):
566 rv = delete_all_flows(self.controller, pa_logger)
567 self.assertEqual(rv, 0, "Failed to delete all flows")
568
569 ingress_port = of_ports[idx]
570 no_flood_idx = (idx + 1) % len(of_ports)
571 no_flood_port = of_ports[no_flood_idx]
572 rv = port_config_set(self.controller, no_flood_port,
573 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
574 pa_logger)
575 self.assertEqual(rv, 0, "Failed to set port config")
576
577 match.in_port = ingress_port
578
579 request = message.flow_mod()
580 request.match = match
581 request.buffer_id = 0xffffffff
582 act.port = ofp.OFPP_FLOOD
583 self.assertTrue(request.actions.add(act),
584 "Could not add flood port action")
585 pa_logger.info(request.show())
586
587 pa_logger.info("Inserting flow")
588 rv = self.controller.message_send(request)
589 self.assertTrue(rv != -1, "Error installing flow mod")
590 do_barrier(self.controller)
591
592 pa_logger.info("Sending packet to dp port " + str(ingress_port))
593 pa_logger.info("No flood port is " + str(no_flood_port))
594 self.dataplane.send(ingress_port, str(pkt))
595 no_ports = set([ingress_port, no_flood_port])
596 yes_ports = set(of_ports).difference(no_ports)
597 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700598 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700599
600 # Turn no flood off again
601 rv = port_config_set(self.controller, no_flood_port,
602 0, ofp.OFPPC_NO_FLOOD, pa_logger)
603 self.assertEqual(rv, 0, "Failed to reset port config")
604
605 #@todo Should check no other packets received
606
Dan Talayco21381562010-07-17 00:34:47 -0700607
608
Dan Talayco551befa2010-07-15 17:05:32 -0700609################################################################
610
611class BaseMatchCase(basic.SimpleDataPlane):
612 def setUp(self):
613 basic.SimpleDataPlane.setUp(self)
614 self.logger = pa_logger
615 def runTest(self):
616 self.logger.info("BaseMatchCase")
617
618class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700619 """
Dan Talayco551befa2010-07-15 17:05:32 -0700620 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700621
622 Generate a packet
623 Generate and install a matching flow without wildcard mask
624 Add action to forward to a port
625 Send the packet to the port
626 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700627 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700628
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700629 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700630 flow_match_test(self, pa_port_map)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700631
Dan Talayco551befa2010-07-15 17:05:32 -0700632class ExactMatchTagged(BaseMatchCase):
633 """
634 Exact match for all port pairs with tagged pkts
635 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700636
Dan Talayco551befa2010-07-15 17:05:32 -0700637 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700638 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700639 flow_match_test(self, pa_port_map, dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700640
Dan Talayco551befa2010-07-15 17:05:32 -0700641class ExactMatchTaggedMany(BaseMatchCase):
642 """
643 ExactMatchTagged with many VLANS
644 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700645
Dan Talayco551befa2010-07-15 17:05:32 -0700646 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700647 for vid in range(2,100,10):
Dan Talayco551befa2010-07-15 17:05:32 -0700648 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
649 for vid in range(100,4000,389):
650 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
651 flow_match_test(self, pa_port_map, dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700652
Dan Talayco551befa2010-07-15 17:05:32 -0700653# Don't run by default
654test_prio["ExactMatchTaggedMany"] = -1
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700655
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700656
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700657class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700658 """
659 SingleWildcardMatchPriority
660 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700661
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700662 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700663 self.pkt = simple_tcp_packet()
664 self.flowMsgs = {}
665
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700666 def _ClearTable(self):
667 rc = delete_all_flows(self.controller, self.logger)
668 self.assertEqual(rc, 0, "Failed to delete all flows")
669 do_barrier(self.controller)
670
671 def runTest(self):
672
673 self._Init()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700674 of_ports = pa_port_map.keys()
675 of_ports.sort()
676
677 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700678 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700679
680 # Run several combinations, each at lower priority settings.
681 # At the end of each call to runPrioFlows(), the table should
682 # be empty. If its not, we'll catch it as the priorities decreases
683 portA = of_ports[0]
684 portB = of_ports[1]
685 portC = of_ports[2]
686
687 # TODO -- these priority numbers should be validated somehow?
688 self.runPrioFlows(portA, portB, portC, 1000, 999)
689 self.runPrioFlows(portB, portC, portA, 998, 997)
690 self.runPrioFlows(portC, portA, portB, 996, 995)
691 self.runPrioFlows(portA, portC, portB, 994, 993)
692
693
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700694
695 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
696 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700697
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700698 if clearTable:
699 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700700
701 # Sanity check flow at lower priority from pA to pB
702 self.logger.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
703 % (portA, portB, portC, prioHigher, prioLower))
704
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700705 self.installFlow(prioHigher, portA, portC)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700706 self.installFlow(prioLower, portA, portB)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700707
708 return
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700709 self.verifyFlow(portA, portB)
710 self.removeFlow(prioLower)
711 # Sanity check flow at lower priority from pA to pC
712 self.installFlow(prioLower, portA, portC)
713 self.verifyFlow(portA, portC)
714 self.removeFlow(prioLower)
715
716 # Install and verify pA->pB @ prioLower
717 self.installFlow(prioLower, portA, portB)
718 self.verifyFlow(portA, portB)
719
720 # Install and verify pA->pC @ prioHigher, should override pA->pB
721 self.installFlow(prioHigher, portA, portC)
722 self.verifyFlow(portA, portC)
723 # remove pA->pC
724 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700725 # Old flow pA -> pB @ prioLower should still be active
726 self.verifyFlow(portA, portB)
727 self.removeFlow(prioLower)
728
729 # Table should be empty at this point, leave it alone as
730 # an assumption for future test runs
731
732
733
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700734 def installFlow(self, prio, inp, egp):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700735 request = flow_msg_create(self, self.pkt, ing_port=inp,
736 wildcards=ofp.OFPFW_DL_SRC,
737 egr_ports=egp)
738 request.priority = prio
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700739 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700740 self.flowMsgs[prio] = request
741
742 def removeFlow(self, prio):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700743 return
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700744 if self.flowMsgs.has_key(prio):
745 msg = self.flowMsgs[prio]
746 msg.command = ofp.OFPFC_DELETE_STRICT
747 # This *must* be set for DELETE
748 msg.out_port = ofp.OFPP_NONE
749 self.controller.message_send(msg)
750 do_barrier(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700751 else:
752 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700753
754
755 def verifyFlow(self, inp, egp):
756 self.logger.info("Pkt match test: " + str(inp) +
757 " to " + str(egp))
758 self.logger.debug("Send packet: " + str(inp) + " to "
759 + str(egp))
760 self.dataplane.send(inp, str(self.pkt))
761 receive_pkt_verify(self, egp, self.pkt, inp)
762
763
764
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700765class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
766
767 def runTest(self):
768
769 self._Init()
770
771 of_ports = pa_port_map.keys()
772 of_ports.sort()
773
774 # Install an entry from 0 -> 1 @ prio 1000
775 self._ClearTable()
776 self.installFlow(1000, of_ports[0], of_ports[1])
777 self.verifyFlow(of_ports[0], of_ports[1])
778 self.installFlow(1000, of_ports[1], of_ports[0])
779 self.verifyFlow(of_ports[1], of_ports[0])
780 self.installFlow(1001, of_ports[0], of_ports[1])
781 self.verifyFlow(of_ports[0], of_ports[1])
782 self.installFlow(1001, of_ports[1], of_ports[0])
783 self.verifyFlow(of_ports[1], of_ports[0])
784 self.removeFlow(1001)
785 self.verifyFlow(of_ports[0], of_ports[1])
786 self.removeFlow(1000)
787
788
789
790
Dan Talayco551befa2010-07-15 17:05:32 -0700791class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700792 """
793 Exercise wildcard matching for all ports
794
795 Generate a packet
796 Generate and install a matching flow with wildcard mask
797 Add action to forward to a port
798 Send the packet to the port
799 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700800 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700801 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700802 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700803 for wc in WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -0700804 if wc & ofp.OFPFW_DL_VLAN:
805 dl_vlan = 0
806 else:
807 dl_vlan = -1
808 flow_match_test(self, pa_port_map, wildcards=wc,
809 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700810
Dan Talayco551befa2010-07-15 17:05:32 -0700811class SingleWildcardMatchTagged(BaseMatchCase):
812 """
813 SingleWildcardMatch with tagged packets
814 """
815 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700816 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700817 for wc in WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700818 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -0700819 max_test=10)
820
821class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700822 """
Dan Talayco80b54ed2010-07-13 09:48:35 -0700823 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700824
825 Generate a packet
826 Generate and install a matching flow with wildcard all except one filed
827 Add action to forward to a port
828 Send the packet to the port
829 Verify the packet is received at all other ports (one port at a time)
830 Verify flow_expiration message is correct when command option is set
831 """
832 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700833 for wc in WILDCARD_VALUES:
834 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco4431d542012-03-21 16:42:16 -0700835 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
836 dl_vlan = 0
837 else:
838 dl_vlan = -1
839 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
840 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700841
Dan Talayco551befa2010-07-15 17:05:32 -0700842class AllExceptOneWildcardMatchTagged(BaseMatchCase):
843 """
844 Match one field with tagged packets
845 """
846 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700847 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700848 for wc in WILDCARD_VALUES:
849 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco21381562010-07-17 00:34:47 -0700850 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
851 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -0700852
853class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700854 """
855 Create Wildcard-all flow and exercise for all ports
856
857 Generate a packet
858 Generate and install a matching flow with wildcard-all
859 Add action to forward to a port
860 Send the packet to the port
861 Verify the packet is received at all other ports (one port at a time)
862 Verify flow_expiration message is correct when command option is set
863 """
864 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700865 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700866
Dan Talayco551befa2010-07-15 17:05:32 -0700867class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700868 """
Dan Talayco551befa2010-07-15 17:05:32 -0700869 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700870 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700871 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700872 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700873 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
874 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700875
Dan Talaycoba3745c2010-07-21 21:51:08 -0700876
Dan Talayco551befa2010-07-15 17:05:32 -0700877class AddVLANTag(BaseMatchCase):
878 """
879 Add a VLAN tag to an untagged packet
880 """
881 def runTest(self):
882 new_vid = 2
883 sup_acts = supported_actions_get(self)
884 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700885 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -0700886 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700887
Dan Talayco551befa2010-07-15 17:05:32 -0700888 len = 100
889 len_w_vid = 104
890 pkt = simple_tcp_packet(pktlen=len)
891 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
892 dl_vlan=new_vid)
893 vid_act = action.action_set_vlan_vid()
894 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700895
Dan Talayco551befa2010-07-15 17:05:32 -0700896 flow_match_test(self, pa_port_map, pkt=pkt,
897 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700898
Dan Talayco551befa2010-07-15 17:05:32 -0700899class PacketOnly(basic.DataPlaneOnly):
900 """
901 Just send a packet thru the switch
902 """
903 def runTest(self):
904 pkt = simple_tcp_packet()
905 of_ports = pa_port_map.keys()
906 of_ports.sort()
907 ing_port = of_ports[0]
908 pa_logger.info("Sending packet to " + str(ing_port))
909 pa_logger.debug("Data: " + str(pkt).encode('hex'))
910 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700911
Dan Talayco551befa2010-07-15 17:05:32 -0700912class PacketOnlyTagged(basic.DataPlaneOnly):
913 """
914 Just send a packet thru the switch
915 """
916 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700917 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700918 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
919 of_ports = pa_port_map.keys()
920 of_ports.sort()
921 ing_port = of_ports[0]
922 pa_logger.info("Sending packet to " + str(ing_port))
923 pa_logger.debug("Data: " + str(pkt).encode('hex'))
924 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700925
Dan Talayco551befa2010-07-15 17:05:32 -0700926test_prio["PacketOnly"] = -1
927test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700928
Dan Talayco551befa2010-07-15 17:05:32 -0700929class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700930 """
931 Modify the VLAN ID in the VLAN tag of a tagged packet
932 """
Dan Talayco551befa2010-07-15 17:05:32 -0700933 def runTest(self):
934 old_vid = 2
935 new_vid = 3
936 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700937 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700938 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700939 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700940
Dan Talayco551befa2010-07-15 17:05:32 -0700941 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
942 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
943 vid_act = action.action_set_vlan_vid()
944 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700945
Dan Talayco551befa2010-07-15 17:05:32 -0700946 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
947 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700948
Dan Talayco551befa2010-07-15 17:05:32 -0700949class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700950 """
951 Strip the VLAN tag from a tagged packet
952 """
Dan Talayco551befa2010-07-15 17:05:32 -0700953 def runTest(self):
954 old_vid = 2
955 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700956 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700957 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700958 return
Dan Talaycof36f1082010-07-13 13:57:17 -0700959
Dan Talayco551befa2010-07-15 17:05:32 -0700960 len_w_vid = 104
961 len = 100
962 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
963 dl_vlan=old_vid)
964 exp_pkt = simple_tcp_packet(pktlen=len)
965 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700966
Dan Talayco551befa2010-07-15 17:05:32 -0700967 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
968 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700969
Dan Talayco4b2bee62010-07-20 14:10:05 -0700970def init_pkt_args():
971 """
972 Pass back a dictionary with default packet arguments
973 """
974 args = {}
975 args["dl_src"] = '00:23:45:67:89:AB'
976
977 dl_vlan_enable=False
978 dl_vlan=-1
979 if pa_config["test-params"]["vid"]:
980 dl_vlan_enable=True
981 dl_vlan = pa_config["test-params"]["vid"]
982
983# Unpack operator is ** on a dictionary
984
985 return args
986
Dan Talayco551befa2010-07-15 17:05:32 -0700987class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700988 """
989 Modify the source MAC address (TP1)
990 """
Dan Talayco551befa2010-07-15 17:05:32 -0700991 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700992 sup_acts = supported_actions_get(self)
993 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700994 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700995 return
996
997 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
998 check_test_params=True)
999 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1000 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001001
Dan Talayco551befa2010-07-15 17:05:32 -07001002class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001003 """
1004 Modify the dest MAC address (TP1)
1005 """
Dan Talayco551befa2010-07-15 17:05:32 -07001006 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001007 sup_acts = supported_actions_get(self)
1008 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001009 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001010 return
1011
1012 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1013 check_test_params=True)
1014 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1015 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001016
Dan Talayco551befa2010-07-15 17:05:32 -07001017class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001018 """
1019 Modify the source IP address of an IP packet (TP1)
1020 """
Dan Talayco551befa2010-07-15 17:05:32 -07001021 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001022 sup_acts = supported_actions_get(self)
1023 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001024 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001025 return
1026
1027 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1028 check_test_params=True)
1029 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1030 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001031
Dan Talayco551befa2010-07-15 17:05:32 -07001032class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001033 """
1034 Modify the dest IP address of an IP packet (TP1)
1035 """
Dan Talayco551befa2010-07-15 17:05:32 -07001036 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001037 sup_acts = supported_actions_get(self)
1038 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001039 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001040 return
1041
1042 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1043 check_test_params=True)
1044 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1045 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001046
1047class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001048 """
1049 Modify the source TCP port of a TCP packet (TP1)
1050 """
Dan Talayco551befa2010-07-15 17:05:32 -07001051 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001052 sup_acts = supported_actions_get(self)
1053 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001054 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001055 return
1056
1057 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1058 check_test_params=True)
1059 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1060 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001061
1062class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001063 """
1064 Modify the dest TCP port of a TCP packet (TP1)
1065 """
Dan Talayco551befa2010-07-15 17:05:32 -07001066 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001067 sup_acts = supported_actions_get(self)
1068 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001069 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001070 return
1071
1072 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1073 check_test_params=True)
1074 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1075 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001076
1077class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001078 """
1079 Modify the IP type of service of an IP packet (TP1)
1080 """
Dan Talayco551befa2010-07-15 17:05:32 -07001081 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001082 sup_acts = supported_actions_get(self)
1083 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001084 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001085 return
Dan Talayco551befa2010-07-15 17:05:32 -07001086
Dan Talayco4b2bee62010-07-20 14:10:05 -07001087 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1088 check_test_params=True)
1089 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001090 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001091
Dan Talaycof6e76c02012-03-23 10:56:12 -07001092class ModifyL2DstMC(BaseMatchCase):
1093 """
1094 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001095 """
1096 def runTest(self):
1097 sup_acts = supported_actions_get(self)
1098 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001099 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001100 return
1101
Dan Talaycof6e76c02012-03-23 10:56:12 -07001102 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1103 check_test_params=True)
1104 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001105 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001106
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001107class ModifyL2DstIngress(BaseMatchCase):
1108 """
1109 Modify the L2 dest and send to the ingress port
1110 """
1111 def runTest(self):
1112 sup_acts = supported_actions_get(self)
1113 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1114 skip_message_emit(self, "ModifyL2dstMC test")
1115 return
1116
1117 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1118 check_test_params=True)
1119 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1120 action_list=acts, max_test=2, egr_count=0,
1121 ing_port=True)
1122
Dan Talaycod8ae7582012-03-23 12:24:56 -07001123class ModifyL2DstIngressMC(BaseMatchCase):
1124 """
1125 Modify the L2 dest and send to the ingress port
1126 """
1127 def runTest(self):
1128 sup_acts = supported_actions_get(self)
1129 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1130 skip_message_emit(self, "ModifyL2dstMC test")
1131 return
1132
1133 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1134 check_test_params=True)
1135 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1136 action_list=acts, max_test=2, egr_count=-1,
1137 ing_port=True)
1138
Dan Talaycof6e76c02012-03-23 10:56:12 -07001139class ModifyL2SrcMC(BaseMatchCase):
1140 """
1141 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001142 """
1143 def runTest(self):
1144 sup_acts = supported_actions_get(self)
1145 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001146 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001147 return
1148
Dan Talaycof6e76c02012-03-23 10:56:12 -07001149 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1150 check_test_params=True)
1151 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001152 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001153
1154class ModifyL2SrcDstMC(BaseMatchCase):
1155 """
1156 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001157 """
1158 def runTest(self):
1159 sup_acts = supported_actions_get(self)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001160 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1161 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1162 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001163 return
1164
Dan Talaycof6e76c02012-03-23 10:56:12 -07001165 mod_fields = ['dl_dst', 'dl_src']
1166 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1167 check_test_params=True)
1168 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001169 action_list=acts, max_test=2, egr_count=-1)
1170
1171class ModifyL2DstVIDMC(BaseMatchCase):
1172 """
1173 Modify the L2 dest and send to 2 ports
1174 """
1175 def runTest(self):
1176 sup_acts = supported_actions_get(self)
1177 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1178 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1179 skip_message_emit(self, "ModifyL2DstVIDMC test")
1180 return
1181
1182 mod_fields = ['dl_dst', 'dl_vlan']
1183 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1184 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1185 check_test_params=True)
1186 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1187 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001188
Dan Talayco8a64e332012-03-28 14:53:20 -07001189# You can pick and choose these by commenting tests in or out
1190iter_classes = [
1191 basic.PacketIn,
1192 basic.PacketOut,
1193 DirectPacket,
1194 DirectTwoPorts,
1195 DirectMC,
1196 AllWildcardMatch,
1197 AllWildcardMatchTagged,
1198 SingleWildcardMatch,
1199 SingleWildcardMatchTagged,
1200 ExactMatch,
1201 ExactMatchTagged,
1202 SingleWildcardMatch,
1203 ModifyL2Src,
1204 ModifyL2Dst,
1205 ModifyL2SrcMC,
1206 ModifyL2DstMC,
1207 ModifyL2SrcDstMC
1208 ]
1209
1210class IterCases(BaseMatchCase):
1211 def runTest(self):
1212 count = test_param_get(self.config, 'iter_count', default=10)
1213 tests_done = 0
1214 pa_logger.info("Running iteration test " + str(count) + " times")
1215 start = time.time()
1216 last = start
1217 for idx in range(count):
1218 pa_logger.info("Iteration " + str(idx + 1))
1219 for cls in iter_classes:
1220 test = cls()
1221 test.inheritSetup(self)
1222 test.runTest()
1223 tests_done += 1
1224 if time.time() - last > 60:
1225 last = time.time()
1226 print("IterCases: Ran %d tests in %d " %
1227 (tests_done, last - start) +
1228 "seconds so far")
1229 stats = all_stats_get(self)
1230 last = time.time()
1231 pa_logger.info("\nIterCases ran %d tests in %d seconds." %
1232 (tests_done, last - start))
1233 pa_logger.info(" flows: %d. packets: %d. bytes: %d" %
1234 (stats["flows"], stats["packets"], stats["bytes"]))
1235 pa_logger.info(" active: %d. lookups: %d. matched %d." %
1236 (stats["active"], stats["lookups"], stats["matched"]))
1237
1238# Don't run by default
1239test_prio["IterCases"] = -1
Dan Talaycof6e76c02012-03-23 10:56:12 -07001240
Dan Talayco4b2bee62010-07-20 14:10:05 -07001241#@todo Need to implement tagged versions of the above tests
1242#
1243#@todo Implement a test case that strips tag 2, adds tag 3
1244# and modifies tag 4 to tag 5. Then verify (in addition) that
1245# tag 6 does not get modified.
1246
1247class MixedVLAN(BaseMatchCase):
1248 """
1249 Test mixture of VLAN tag actions
1250
1251 Strip tag 2 on port 1, send to port 2
1252 Add tag 3 on port 1, send to port 2
1253 Modify tag 4 to 5 on port 1, send to port 2
1254 All other traffic from port 1, send to port 3
1255 All traffic from port 2 sent to port 4
1256 Use exact matches with different packets for all mods
1257 Verify the following: (port, vid)
1258 (port 1, vid 2) => VLAN tag stripped, out port 2
1259 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1260 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1261 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1262 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1263 (port 2, no tag) => untagged packet out port 4
1264 (port 2, vid 2-6) => unmodified packet out port 4
1265
1266 Variation: Might try sending VID 5 to port 3 and check.
1267 If only VID 5 distinguishes pkt, this will fail on some platforms
1268 """
1269
1270test_prio["MixedVLAN"] = -1
1271
Dan Talayco551befa2010-07-15 17:05:32 -07001272def supported_actions_get(parent, use_cache=True):
1273 """
1274 Get the bitmap of supported actions from the switch
1275 If use_cache is false, the cached value will be updated
1276 """
1277 global cached_supported_actions
1278 if cached_supported_actions is None or not use_cache:
1279 request = message.features_request()
1280 (reply, pkt) = parent.controller.transact(request, timeout=2)
1281 parent.assertTrue(reply is not None, "Did not get response to ftr req")
1282 cached_supported_actions = reply.actions
1283 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
1284
1285 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -07001286
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001287if __name__ == "__main__":
1288 print "Please run through oft script: ./oft --test_spec=basic"