blob: 222317fa8485b0aeec0f1d3df911dbade8edd606 [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,
Dan Talayco488fbc52012-04-09 16:30:41 -070048 ofp.OFPFW_DL_VLAN | ofp.OFPFW_DL_VLAN_PCP,
Dan Talayco551befa2010-07-15 17:05:32 -070049 ofp.OFPFW_DL_SRC,
50 ofp.OFPFW_DL_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070051 (ofp.OFPFW_DL_TYPE | ofp.OFPFW_NW_SRC_ALL |
52 ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS | ofp.OFPFW_NW_PROTO |
53 ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
54 (ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
Dan Talayco551befa2010-07-15 17:05:32 -070055 ofp.OFPFW_TP_SRC,
56 ofp.OFPFW_TP_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070057 ofp.OFPFW_NW_SRC_MASK,
58 ofp.OFPFW_NW_DST_MASK,
Dan Talayco551befa2010-07-15 17:05:32 -070059 ofp.OFPFW_DL_VLAN_PCP,
60 ofp.OFPFW_NW_TOS]
61
Dan Talayco488fbc52012-04-09 16:30:41 -070062NO_WILDCARD_VALUES = [(ofp.OFPFW_ALL ^ ofp.OFPFW_IN_PORT),
63 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN),
64 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_SRC),
65 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_DST),
66 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE),
67 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO),
68 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
69 ofp.OFPFW_TP_SRC),
70 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
71 ofp.OFPFW_TP_DST),
72 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
73 ofp.OFPFW_NW_SRC_MASK),
74 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
75 ofp.OFPFW_NW_DST_MASK),
76 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN ^ ofp.OFPFW_DL_VLAN_PCP),
77 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
78 ofp.OFPFW_NW_TOS)]
79
Dan Talayco551befa2010-07-15 17:05:32 -070080MODIFY_ACTION_VALUES = [ofp.OFPAT_SET_VLAN_VID,
81 ofp.OFPAT_SET_VLAN_PCP,
82 ofp.OFPAT_STRIP_VLAN,
83 ofp.OFPAT_SET_DL_SRC,
84 ofp.OFPAT_SET_DL_DST,
85 ofp.OFPAT_SET_NW_SRC,
86 ofp.OFPAT_SET_NW_DST,
87 ofp.OFPAT_SET_NW_TOS,
88 ofp.OFPAT_SET_TP_SRC,
89 ofp.OFPAT_SET_TP_DST]
90
91# Cache supported features to avoid transaction overhead
92cached_supported_actions = None
93
Dan Talayco21381562010-07-17 00:34:47 -070094TEST_VID_DEFAULT = 2
95
Dan Talayco5eba8442010-03-10 13:58:43 -080096def test_set_init(config):
97 """
98 Set up function for packet action test classes
99
100 @param config The configuration dictionary; see oft
101 """
102
Ed Swierk89f78352012-03-29 12:32:32 -0700103 basic.test_set_init(config)
104
Dan Talayco5eba8442010-03-10 13:58:43 -0800105 global pa_port_map
106 global pa_logger
107 global pa_config
108
109 pa_logger = logging.getLogger("pkt_act")
110 pa_logger.info("Initializing test set")
111 pa_port_map = config["port_map"]
112 pa_config = config
113
114class DirectPacket(basic.SimpleDataPlane):
115 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700116 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -0800117
118 Generate a packet
119 Generate and install a matching flow
120 Add action to direct the packet to an egress port
121 Send the packet to ingress dataplane port
122 Verify the packet is received at the egress port only
123 """
124 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700125 self.handleFlow()
126
127 def handleFlow(self, pkttype='TCP'):
Dan Talayco5eba8442010-03-10 13:58:43 -0800128 of_ports = pa_port_map.keys()
129 of_ports.sort()
130 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
131
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700132 if (pkttype == 'ICMP'):
133 pkt = simple_icmp_packet()
134 else:
135 pkt = simple_tcp_packet()
Dan Talayco5eba8442010-03-10 13:58:43 -0800136 match = parse.packet_to_flow_match(pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700137 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800138 self.assertTrue(match is not None,
139 "Could not generate flow match from pkt")
140 act = action.action_output()
141
142 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700143 rv = delete_all_flows(self.controller, pa_logger)
144 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700145
Dan Talayco5eba8442010-03-10 13:58:43 -0800146 ingress_port = of_ports[idx]
147 egress_port = of_ports[(idx + 1) % len(of_ports)]
148 pa_logger.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700149 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800150
151 match.in_port = ingress_port
152
153 request = message.flow_mod()
154 request.match = match
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700155
Dan Talayco5eba8442010-03-10 13:58:43 -0800156 request.buffer_id = 0xffffffff
157 act.port = egress_port
158 self.assertTrue(request.actions.add(act), "Could not add action")
159
160 pa_logger.info("Inserting flow")
161 rv = self.controller.message_send(request)
162 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700163 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco5eba8442010-03-10 13:58:43 -0800164
165 pa_logger.info("Sending packet to dp port " +
166 str(ingress_port))
167 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700168
169 exp_pkt_arg = None
170 exp_port = None
171 if pa_config["relax"]:
172 exp_pkt_arg = pkt
173 exp_port = egress_port
174
175 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(timeout=1,
176 port_number=exp_port,
177 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800178 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700179 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800180 str(rcv_port))
181 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
182 self.assertEqual(str(pkt), str(rcv_pkt),
183 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700184
Howard Pershf97840f2012-04-10 16:30:42 -0700185
186class DirectPacketQueue(basic.SimpleDataPlane):
187 """
188 Send packet to single queue on single egress port
189
190 Generate a packet
191 Generate and install a matching flow
192 Add action to direct the packet to an egress port and queue
193 Send the packet to ingress dataplane port
194 Verify the packet is received at the egress port only
195 """
196 def runTest(self):
197 self.handleFlow()
198
199 def handleFlow(self, pkttype='TCP'):
200 of_ports = pa_port_map.keys()
201 of_ports.sort()
202 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
203
204 if (pkttype == 'ICMP'):
205 pkt = simple_icmp_packet()
206 else:
207 pkt = simple_tcp_packet()
208 match = parse.packet_to_flow_match(pkt)
209 match.wildcards &= ~ofp.OFPFW_IN_PORT
210 self.assertTrue(match is not None,
211 "Could not generate flow match from pkt")
212
213 act = action.action_enqueue()
214 egress_queue_id = 0 # For the time being, always queue 0
215
216 for idx in range(len(of_ports)):
217 rv = delete_all_flows(self.controller, pa_logger)
218 self.assertEqual(rv, 0, "Failed to delete all flows")
219
220 ingress_port = of_ports[idx]
221 egress_port = of_ports[(idx + 1) % len(of_ports)]
222 pa_logger.info("Ingress " + str(ingress_port)
223 + " to egress " + str(egress_port)
224 + " queue " + str(egress_queue_id)
225 )
226
227 match.in_port = ingress_port
228
229 request = message.flow_mod()
230 request.match = match
231
232 request.buffer_id = 0xffffffff
233 act.port = egress_port
234 act.queue_id = egress_queue_id
235 self.assertTrue(request.actions.add(act), "Could not add action")
236
237 pa_logger.info("Inserting flow")
238 rv = self.controller.message_send(request)
239 self.assertTrue(rv != -1, "Error installing flow mod")
240 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
241
242 pa_logger.info("Sending packet to dp port " +
243 str(ingress_port))
244 self.dataplane.send(ingress_port, str(pkt))
245
246 exp_pkt_arg = None
247 exp_port = None
248 if pa_config["relax"]:
249 exp_pkt_arg = pkt
250 exp_port = egress_port
251
252 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(timeout=1,
253 port_number=exp_port,
254 exp_pkt=exp_pkt_arg)
255 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
256 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
257 str(rcv_port))
258 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
259 self.assertEqual(str(pkt), str(rcv_pkt),
260 'Response packet does not match send packet')
261
262
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700263class DirectPacketICMP(DirectPacket):
264 """
265 Send ICMP packet to single egress port
266
267 Generate a ICMP packet
268 Generate and install a matching flow
269 Add action to direct the packet to an egress port
270 Send the packet to ingress dataplane port
271 Verify the packet is received at the egress port only
272 Difference from DirectPacket test is that sent packet is ICMP
273 """
274 def runTest(self):
275 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700276
277class DirectTwoPorts(basic.SimpleDataPlane):
278 """
279 Send packet to two egress ports
280
281 Generate a packet
282 Generate and install a matching flow
283 Add action to direct the packet to two egress ports
284 Send the packet to ingress dataplane port
285 Verify the packet is received at the two egress ports
286 """
287 def runTest(self):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700288 of_ports = pa_port_map.keys()
289 of_ports.sort()
290 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
291
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700292 pkt = simple_tcp_packet()
293 match = parse.packet_to_flow_match(pkt)
294 match.wildcards &= ~ofp.OFPFW_IN_PORT
295 self.assertTrue(match is not None,
296 "Could not generate flow match from pkt")
297 act = action.action_output()
298
299 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700300 rv = delete_all_flows(self.controller, pa_logger)
301 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700302
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700303 ingress_port = of_ports[idx]
304 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
305 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
306 pa_logger.info("Ingress " + str(ingress_port) +
307 " to egress " + str(egress_port1) + " and " +
308 str(egress_port2))
309
310 match.in_port = ingress_port
311
312 request = message.flow_mod()
313 request.match = match
314 request.buffer_id = 0xffffffff
315 act.port = egress_port1
316 self.assertTrue(request.actions.add(act), "Could not add action1")
317 act.port = egress_port2
318 self.assertTrue(request.actions.add(act), "Could not add action2")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700319 # pa_logger.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700320
321 pa_logger.info("Inserting flow")
322 rv = self.controller.message_send(request)
323 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700324 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700325
326 pa_logger.info("Sending packet to dp port " +
327 str(ingress_port))
328 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700329 yes_ports = set([egress_port1, egress_port2])
330 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700331
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700332 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700333 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700334
335class DirectMCNonIngress(basic.SimpleDataPlane):
336 """
337 Multicast to all non-ingress ports
338
339 Generate a packet
340 Generate and install a matching flow
341 Add action to direct the packet to all non-ingress ports
342 Send the packet to ingress dataplane port
343 Verify the packet is received at all non-ingress ports
344
345 Does not use the flood action
346 """
347 def runTest(self):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700348 of_ports = pa_port_map.keys()
349 of_ports.sort()
350 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
351
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700352 pkt = simple_tcp_packet()
353 match = parse.packet_to_flow_match(pkt)
354 match.wildcards &= ~ofp.OFPFW_IN_PORT
355 self.assertTrue(match is not None,
356 "Could not generate flow match from pkt")
357 act = action.action_output()
358
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700359 for ingress_port in of_ports:
360 rv = delete_all_flows(self.controller, pa_logger)
361 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700362
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700363 pa_logger.info("Ingress " + str(ingress_port) +
364 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700365 match.in_port = ingress_port
366
367 request = message.flow_mod()
368 request.match = match
369 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700370 for egress_port in of_ports:
371 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700372 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700373 act.port = egress_port
374 self.assertTrue(request.actions.add(act),
375 "Could not add output to " + str(egress_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700376 pa_logger.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700377
378 pa_logger.info("Inserting flow")
379 rv = self.controller.message_send(request)
380 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700381 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700382
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700383 pa_logger.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700384 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700385 yes_ports = set(of_ports).difference([ingress_port])
386 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700387 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700388
Dan Talayco32fa6542010-05-11 15:54:08 -0700389
390class DirectMC(basic.SimpleDataPlane):
391 """
392 Multicast to all ports including ingress
393
394 Generate a packet
395 Generate and install a matching flow
396 Add action to direct the packet to all non-ingress ports
397 Send the packet to ingress dataplane port
398 Verify the packet is received at all ports
399
400 Does not use the flood action
401 """
402 def runTest(self):
Dan Talayco32fa6542010-05-11 15:54:08 -0700403 of_ports = pa_port_map.keys()
404 of_ports.sort()
405 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
406
Dan Talayco32fa6542010-05-11 15:54:08 -0700407 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 Talayco2e77a842010-05-12 15:39:46 -0700417
Dan Talayco32fa6542010-05-11 15:54:08 -0700418 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700419 match.in_port = ingress_port
420
421 request = message.flow_mod()
422 request.match = match
423 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700424 for egress_port in of_ports:
425 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700426 act.port = ofp.OFPP_IN_PORT
427 else:
428 act.port = egress_port
429 self.assertTrue(request.actions.add(act),
430 "Could not add output to " + str(egress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700431 # pa_logger.info(request.show())
432
433 pa_logger.info("Inserting flow")
434 rv = self.controller.message_send(request)
435 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700436 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2e77a842010-05-12 15:39:46 -0700437
438 pa_logger.info("Sending packet to dp port " + str(ingress_port))
439 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700440 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700441 pa_logger, pa_config)
Dan Talayco2e77a842010-05-12 15:39:46 -0700442
443class Flood(basic.SimpleDataPlane):
444 """
445 Flood to all ports except ingress
446
447 Generate a packet
448 Generate and install a matching flow
449 Add action to flood the packet
450 Send the packet to ingress dataplane port
451 Verify the packet is received at all other ports
452 """
453 def runTest(self):
Dan Talayco2e77a842010-05-12 15:39:46 -0700454 of_ports = pa_port_map.keys()
455 of_ports.sort()
456 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
457
458 pkt = simple_tcp_packet()
459 match = parse.packet_to_flow_match(pkt)
460 match.wildcards &= ~ofp.OFPFW_IN_PORT
461 self.assertTrue(match is not None,
462 "Could not generate flow match from pkt")
463 act = action.action_output()
464
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700465 for ingress_port in of_ports:
466 rv = delete_all_flows(self.controller, pa_logger)
467 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700468
Dan Talayco2e77a842010-05-12 15:39:46 -0700469 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700470 match.in_port = ingress_port
471
472 request = message.flow_mod()
473 request.match = match
474 request.buffer_id = 0xffffffff
475 act.port = ofp.OFPP_FLOOD
476 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700477 "Could not add flood port action")
Dan Talayco32fa6542010-05-11 15:54:08 -0700478 pa_logger.info(request.show())
479
480 pa_logger.info("Inserting flow")
481 rv = self.controller.message_send(request)
482 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700483 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco32fa6542010-05-11 15:54:08 -0700484
485 pa_logger.info("Sending packet to dp port " + str(ingress_port))
486 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700487 yes_ports = set(of_ports).difference([ingress_port])
488 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700489 self, pa_logger, pa_config)
Dan Talayco3be5b062010-05-12 15:46:21 -0700490
Dan Talayco3be5b062010-05-12 15:46:21 -0700491class FloodPlusIngress(basic.SimpleDataPlane):
492 """
493 Flood to all ports plus send to ingress port
494
495 Generate a packet
496 Generate and install a matching flow
497 Add action to flood the packet
498 Add action to send to ingress port
499 Send the packet to ingress dataplane port
500 Verify the packet is received at all other ports
501 """
502 def runTest(self):
Dan Talayco3be5b062010-05-12 15:46:21 -0700503 of_ports = pa_port_map.keys()
504 of_ports.sort()
505 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
506
507 pkt = simple_tcp_packet()
508 match = parse.packet_to_flow_match(pkt)
509 match.wildcards &= ~ofp.OFPFW_IN_PORT
510 self.assertTrue(match is not None,
511 "Could not generate flow match from pkt")
512 act = action.action_output()
513
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700514 for ingress_port in of_ports:
515 rv = delete_all_flows(self.controller, pa_logger)
516 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700517
Dan Talayco3be5b062010-05-12 15:46:21 -0700518 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700519 match.in_port = ingress_port
520
521 request = message.flow_mod()
522 request.match = match
523 request.buffer_id = 0xffffffff
524 act.port = ofp.OFPP_FLOOD
525 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700526 "Could not add flood port action")
527 act.port = ofp.OFPP_IN_PORT
528 self.assertTrue(request.actions.add(act),
529 "Could not add ingress port for output")
530 pa_logger.info(request.show())
531
532 pa_logger.info("Inserting flow")
533 rv = self.controller.message_send(request)
534 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700535 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700536
537 pa_logger.info("Sending packet to dp port " + str(ingress_port))
538 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700539 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700540 pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700541
542class All(basic.SimpleDataPlane):
543 """
544 Send to OFPP_ALL port
545
546 Generate a packet
547 Generate and install a matching flow
548 Add action to forward to OFPP_ALL
549 Send the packet to ingress dataplane port
550 Verify the packet is received at all other ports
551 """
552 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700553 of_ports = pa_port_map.keys()
554 of_ports.sort()
555 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
556
557 pkt = simple_tcp_packet()
558 match = parse.packet_to_flow_match(pkt)
559 match.wildcards &= ~ofp.OFPFW_IN_PORT
560 self.assertTrue(match is not None,
561 "Could not generate flow match from pkt")
562 act = action.action_output()
563
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700564 for ingress_port in of_ports:
565 rv = delete_all_flows(self.controller, pa_logger)
566 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700567
Dan Talayco4aa13122010-05-12 15:54:44 -0700568 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700569 match.in_port = ingress_port
570
571 request = message.flow_mod()
572 request.match = match
573 request.buffer_id = 0xffffffff
574 act.port = ofp.OFPP_ALL
575 self.assertTrue(request.actions.add(act),
576 "Could not add ALL port action")
577 pa_logger.info(request.show())
578
579 pa_logger.info("Inserting flow")
580 rv = self.controller.message_send(request)
581 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700582 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700583
584 pa_logger.info("Sending packet to dp port " + str(ingress_port))
585 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700586 yes_ports = set(of_ports).difference([ingress_port])
587 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700588 self, pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700589
590class AllPlusIngress(basic.SimpleDataPlane):
591 """
592 Send to OFPP_ALL port and ingress port
593
594 Generate a packet
595 Generate and install a matching flow
596 Add action to forward to OFPP_ALL
597 Add action to forward to ingress port
598 Send the packet to ingress dataplane port
599 Verify the packet is received at all other ports
600 """
601 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700602 of_ports = pa_port_map.keys()
603 of_ports.sort()
604 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
605
606 pkt = simple_tcp_packet()
607 match = parse.packet_to_flow_match(pkt)
608 match.wildcards &= ~ofp.OFPFW_IN_PORT
609 self.assertTrue(match is not None,
610 "Could not generate flow match from pkt")
611 act = action.action_output()
612
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700613 for ingress_port in of_ports:
614 rv = delete_all_flows(self.controller, pa_logger)
615 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700616
Dan Talayco4aa13122010-05-12 15:54:44 -0700617 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700618 match.in_port = ingress_port
619
620 request = message.flow_mod()
621 request.match = match
622 request.buffer_id = 0xffffffff
623 act.port = ofp.OFPP_ALL
624 self.assertTrue(request.actions.add(act),
625 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700626 act.port = ofp.OFPP_IN_PORT
627 self.assertTrue(request.actions.add(act),
628 "Could not add ingress port for output")
629 pa_logger.info(request.show())
630
631 pa_logger.info("Inserting flow")
632 rv = self.controller.message_send(request)
633 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700634 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco3be5b062010-05-12 15:46:21 -0700635
636 pa_logger.info("Sending packet to dp port " + str(ingress_port))
637 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700638 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700639 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700640
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700641class FloodMinusPort(basic.SimpleDataPlane):
642 """
643 Config port with No_Flood and test Flood action
644
645 Generate a packet
646 Generate a matching flow
647 Add action to forward to OFPP_ALL
648 Set port to no-flood
649 Send the packet to ingress dataplane port
650 Verify the packet is received at all other ports except
651 the ingress port and the no_flood port
652 """
653 def runTest(self):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700654 of_ports = pa_port_map.keys()
655 of_ports.sort()
656 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
657
658 pkt = simple_tcp_packet()
659 match = parse.packet_to_flow_match(pkt)
660 match.wildcards &= ~ofp.OFPFW_IN_PORT
661 self.assertTrue(match is not None,
662 "Could not generate flow match from pkt")
663 act = action.action_output()
664
665 for idx in range(len(of_ports)):
666 rv = delete_all_flows(self.controller, pa_logger)
667 self.assertEqual(rv, 0, "Failed to delete all flows")
668
669 ingress_port = of_ports[idx]
670 no_flood_idx = (idx + 1) % len(of_ports)
671 no_flood_port = of_ports[no_flood_idx]
672 rv = port_config_set(self.controller, no_flood_port,
673 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
674 pa_logger)
675 self.assertEqual(rv, 0, "Failed to set port config")
676
677 match.in_port = ingress_port
678
679 request = message.flow_mod()
680 request.match = match
681 request.buffer_id = 0xffffffff
682 act.port = ofp.OFPP_FLOOD
683 self.assertTrue(request.actions.add(act),
684 "Could not add flood port action")
685 pa_logger.info(request.show())
686
687 pa_logger.info("Inserting flow")
688 rv = self.controller.message_send(request)
689 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700690 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700691
692 pa_logger.info("Sending packet to dp port " + str(ingress_port))
693 pa_logger.info("No flood port is " + str(no_flood_port))
694 self.dataplane.send(ingress_port, str(pkt))
695 no_ports = set([ingress_port, no_flood_port])
696 yes_ports = set(of_ports).difference(no_ports)
697 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700698 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700699
700 # Turn no flood off again
701 rv = port_config_set(self.controller, no_flood_port,
702 0, ofp.OFPPC_NO_FLOOD, pa_logger)
703 self.assertEqual(rv, 0, "Failed to reset port config")
704
705 #@todo Should check no other packets received
706
Dan Talayco21381562010-07-17 00:34:47 -0700707
708
Dan Talayco551befa2010-07-15 17:05:32 -0700709################################################################
710
711class BaseMatchCase(basic.SimpleDataPlane):
712 def setUp(self):
713 basic.SimpleDataPlane.setUp(self)
714 self.logger = pa_logger
715 def runTest(self):
716 self.logger.info("BaseMatchCase")
717
718class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700719 """
Dan Talayco551befa2010-07-15 17:05:32 -0700720 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700721
722 Generate a packet
723 Generate and install a matching flow without wildcard mask
724 Add action to forward to a port
725 Send the packet to the port
726 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700727 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700728
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700729 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700730 flow_match_test(self, pa_port_map)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700731
Dan Talayco551befa2010-07-15 17:05:32 -0700732class ExactMatchTagged(BaseMatchCase):
733 """
734 Exact match for all port pairs with tagged pkts
735 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700736
Dan Talayco551befa2010-07-15 17:05:32 -0700737 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700738 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700739 flow_match_test(self, pa_port_map, dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700740
Dan Talayco551befa2010-07-15 17:05:32 -0700741class ExactMatchTaggedMany(BaseMatchCase):
742 """
743 ExactMatchTagged with many VLANS
744 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700745
Dan Talayco551befa2010-07-15 17:05:32 -0700746 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700747 for vid in range(2,100,10):
Dan Talayco551befa2010-07-15 17:05:32 -0700748 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
749 for vid in range(100,4000,389):
750 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
751 flow_match_test(self, pa_port_map, dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700752
Dan Talayco551befa2010-07-15 17:05:32 -0700753# Don't run by default
754test_prio["ExactMatchTaggedMany"] = -1
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700755
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700756
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700757class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700758 """
759 SingleWildcardMatchPriority
760 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700761
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700762 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700763 self.pkt = simple_tcp_packet()
764 self.flowMsgs = {}
765
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700766 def _ClearTable(self):
767 rc = delete_all_flows(self.controller, self.logger)
768 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700769 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700770
771 def runTest(self):
772
773 self._Init()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700774 of_ports = pa_port_map.keys()
775 of_ports.sort()
776
777 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700778 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700779
780 # Run several combinations, each at lower priority settings.
781 # At the end of each call to runPrioFlows(), the table should
782 # be empty. If its not, we'll catch it as the priorities decreases
783 portA = of_ports[0]
784 portB = of_ports[1]
785 portC = of_ports[2]
786
787 # TODO -- these priority numbers should be validated somehow?
788 self.runPrioFlows(portA, portB, portC, 1000, 999)
789 self.runPrioFlows(portB, portC, portA, 998, 997)
790 self.runPrioFlows(portC, portA, portB, 996, 995)
791 self.runPrioFlows(portA, portC, portB, 994, 993)
792
793
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700794
795 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
796 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700797
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700798 if clearTable:
799 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700800
801 # Sanity check flow at lower priority from pA to pB
802 self.logger.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
803 % (portA, portB, portC, prioHigher, prioLower))
804
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700805 self.installFlow(prioHigher, portA, portC)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700806 self.installFlow(prioLower, portA, portB)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700807
808 return
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700809 self.verifyFlow(portA, portB)
810 self.removeFlow(prioLower)
811 # Sanity check flow at lower priority from pA to pC
812 self.installFlow(prioLower, portA, portC)
813 self.verifyFlow(portA, portC)
814 self.removeFlow(prioLower)
815
816 # Install and verify pA->pB @ prioLower
817 self.installFlow(prioLower, portA, portB)
818 self.verifyFlow(portA, portB)
819
820 # Install and verify pA->pC @ prioHigher, should override pA->pB
821 self.installFlow(prioHigher, portA, portC)
822 self.verifyFlow(portA, portC)
823 # remove pA->pC
824 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700825 # Old flow pA -> pB @ prioLower should still be active
826 self.verifyFlow(portA, portB)
827 self.removeFlow(prioLower)
828
829 # Table should be empty at this point, leave it alone as
830 # an assumption for future test runs
831
832
833
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700834 def installFlow(self, prio, inp, egp):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700835 request = flow_msg_create(self, self.pkt, ing_port=inp,
836 wildcards=ofp.OFPFW_DL_SRC,
837 egr_ports=egp)
838 request.priority = prio
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700839 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700840 self.flowMsgs[prio] = request
841
842 def removeFlow(self, prio):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700843 return
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700844 if self.flowMsgs.has_key(prio):
845 msg = self.flowMsgs[prio]
846 msg.command = ofp.OFPFC_DELETE_STRICT
847 # This *must* be set for DELETE
848 msg.out_port = ofp.OFPP_NONE
849 self.controller.message_send(msg)
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700850 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700851 else:
852 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700853
854
855 def verifyFlow(self, inp, egp):
856 self.logger.info("Pkt match test: " + str(inp) +
857 " to " + str(egp))
858 self.logger.debug("Send packet: " + str(inp) + " to "
859 + str(egp))
860 self.dataplane.send(inp, str(self.pkt))
861 receive_pkt_verify(self, egp, self.pkt, inp)
862
863
864
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700865class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
866
867 def runTest(self):
868
869 self._Init()
870
871 of_ports = pa_port_map.keys()
872 of_ports.sort()
873
874 # Install an entry from 0 -> 1 @ prio 1000
875 self._ClearTable()
876 self.installFlow(1000, of_ports[0], of_ports[1])
877 self.verifyFlow(of_ports[0], of_ports[1])
878 self.installFlow(1000, of_ports[1], of_ports[0])
879 self.verifyFlow(of_ports[1], of_ports[0])
880 self.installFlow(1001, of_ports[0], of_ports[1])
881 self.verifyFlow(of_ports[0], of_ports[1])
882 self.installFlow(1001, of_ports[1], of_ports[0])
883 self.verifyFlow(of_ports[1], of_ports[0])
884 self.removeFlow(1001)
885 self.verifyFlow(of_ports[0], of_ports[1])
886 self.removeFlow(1000)
887
888
889
890
Dan Talayco551befa2010-07-15 17:05:32 -0700891class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700892 """
893 Exercise wildcard matching for all ports
894
895 Generate a packet
896 Generate and install a matching flow with wildcard mask
897 Add action to forward to a port
898 Send the packet to the port
899 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700900 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700901 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700902 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -0700903 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700904 for wc in WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -0700905 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -0700906 # Set nonzero VLAN id to avoid sending priority-tagged packet
907 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -0700908 else:
909 dl_vlan = -1
910 flow_match_test(self, pa_port_map, wildcards=wc,
911 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700912
Dan Talayco551befa2010-07-15 17:05:32 -0700913class SingleWildcardMatchTagged(BaseMatchCase):
914 """
915 SingleWildcardMatch with tagged packets
916 """
917 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700918 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700919 for wc in WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700920 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -0700921 max_test=10)
922
923class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700924 """
Dan Talayco80b54ed2010-07-13 09:48:35 -0700925 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700926
927 Generate a packet
928 Generate and install a matching flow with wildcard all except one filed
929 Add action to forward to a port
930 Send the packet to the port
931 Verify the packet is received at all other ports (one port at a time)
932 Verify flow_expiration message is correct when command option is set
933 """
934 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -0700935 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -0700936 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -0700937 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -0700938 # Set nonzero VLAN id to avoid sending priority-tagged packet
939 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -0700940 else:
941 dl_vlan = -1
942 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
943 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700944
Dan Talayco551befa2010-07-15 17:05:32 -0700945class AllExceptOneWildcardMatchTagged(BaseMatchCase):
946 """
947 Match one field with tagged packets
948 """
949 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700950 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -0700951 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700952 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
953 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -0700954
955class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700956 """
957 Create Wildcard-all flow and exercise for all ports
958
959 Generate a packet
960 Generate and install a matching flow with wildcard-all
961 Add action to forward to a port
962 Send the packet to the port
963 Verify the packet is received at all other ports (one port at a time)
964 Verify flow_expiration message is correct when command option is set
965 """
966 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700967 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700968
Dan Talayco551befa2010-07-15 17:05:32 -0700969class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700970 """
Dan Talayco551befa2010-07-15 17:05:32 -0700971 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700972 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700973 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700974 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700975 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
976 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700977
Dan Talaycoba3745c2010-07-21 21:51:08 -0700978
Dan Talayco551befa2010-07-15 17:05:32 -0700979class AddVLANTag(BaseMatchCase):
980 """
981 Add a VLAN tag to an untagged packet
982 """
983 def runTest(self):
984 new_vid = 2
985 sup_acts = supported_actions_get(self)
986 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700987 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -0700988 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700989
Dan Talayco551befa2010-07-15 17:05:32 -0700990 len = 100
991 len_w_vid = 104
992 pkt = simple_tcp_packet(pktlen=len)
993 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
994 dl_vlan=new_vid)
995 vid_act = action.action_set_vlan_vid()
996 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700997
Dan Talayco551befa2010-07-15 17:05:32 -0700998 flow_match_test(self, pa_port_map, pkt=pkt,
999 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001000
Dan Talayco551befa2010-07-15 17:05:32 -07001001class PacketOnly(basic.DataPlaneOnly):
1002 """
1003 Just send a packet thru the switch
1004 """
1005 def runTest(self):
1006 pkt = simple_tcp_packet()
1007 of_ports = pa_port_map.keys()
1008 of_ports.sort()
1009 ing_port = of_ports[0]
1010 pa_logger.info("Sending packet to " + str(ing_port))
1011 pa_logger.debug("Data: " + str(pkt).encode('hex'))
1012 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001013
Dan Talayco551befa2010-07-15 17:05:32 -07001014class PacketOnlyTagged(basic.DataPlaneOnly):
1015 """
1016 Just send a packet thru the switch
1017 """
1018 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001019 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001020 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
1021 of_ports = pa_port_map.keys()
1022 of_ports.sort()
1023 ing_port = of_ports[0]
1024 pa_logger.info("Sending packet to " + str(ing_port))
1025 pa_logger.debug("Data: " + str(pkt).encode('hex'))
1026 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001027
Dan Talayco551befa2010-07-15 17:05:32 -07001028test_prio["PacketOnly"] = -1
1029test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001030
Dan Talayco551befa2010-07-15 17:05:32 -07001031class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001032 """
1033 Modify the VLAN ID in the VLAN tag of a tagged packet
1034 """
Dan Talayco551befa2010-07-15 17:05:32 -07001035 def runTest(self):
1036 old_vid = 2
1037 new_vid = 3
1038 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001039 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001040 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001041 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001042
Dan Talayco551befa2010-07-15 17:05:32 -07001043 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1044 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
1045 vid_act = action.action_set_vlan_vid()
1046 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001047
Dan Talayco551befa2010-07-15 17:05:32 -07001048 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1049 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001050
Howard Pershc1199d52012-04-11 14:21:32 -07001051class ModifyVlanPcp(BaseMatchCase):
1052 """
1053 Modify the priority field of the VLAN tag of a tagged packet
1054 """
1055 def runTest(self):
1056 vid = 123
1057 old_vlan_pcp = 2
1058 new_vlan_pcp = 3
1059 sup_acts = supported_actions_get(self)
1060 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1061 skip_message_emit(self, "Modify VLAN tag test")
1062 return
1063
1064 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1065 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1066 vid_act = action.action_set_vlan_pcp()
1067 vid_act.vlan_pcp = new_vlan_pcp
1068
1069 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1070 action_list=[vid_act])
1071
Dan Talayco551befa2010-07-15 17:05:32 -07001072class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001073 """
1074 Strip the VLAN tag from a tagged packet
1075 """
Dan Talayco551befa2010-07-15 17:05:32 -07001076 def runTest(self):
1077 old_vid = 2
1078 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001079 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001080 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001081 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001082
Dan Talayco551befa2010-07-15 17:05:32 -07001083 len_w_vid = 104
1084 len = 100
1085 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1086 dl_vlan=old_vid)
1087 exp_pkt = simple_tcp_packet(pktlen=len)
1088 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001089
Dan Talayco551befa2010-07-15 17:05:32 -07001090 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1091 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001092
Dan Talayco4b2bee62010-07-20 14:10:05 -07001093def init_pkt_args():
1094 """
1095 Pass back a dictionary with default packet arguments
1096 """
1097 args = {}
1098 args["dl_src"] = '00:23:45:67:89:AB'
1099
1100 dl_vlan_enable=False
1101 dl_vlan=-1
1102 if pa_config["test-params"]["vid"]:
1103 dl_vlan_enable=True
1104 dl_vlan = pa_config["test-params"]["vid"]
1105
1106# Unpack operator is ** on a dictionary
1107
1108 return args
1109
Dan Talayco551befa2010-07-15 17:05:32 -07001110class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001111 """
1112 Modify the source MAC address (TP1)
1113 """
Dan Talayco551befa2010-07-15 17:05:32 -07001114 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001115 sup_acts = supported_actions_get(self)
1116 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001117 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001118 return
1119
1120 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1121 check_test_params=True)
1122 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1123 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001124
Dan Talayco551befa2010-07-15 17:05:32 -07001125class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001126 """
1127 Modify the dest MAC address (TP1)
1128 """
Dan Talayco551befa2010-07-15 17:05:32 -07001129 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001130 sup_acts = supported_actions_get(self)
1131 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001132 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001133 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)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001139
Dan Talayco551befa2010-07-15 17:05:32 -07001140class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001141 """
1142 Modify the source IP address of an IP packet (TP1)
1143 """
Dan Talayco551befa2010-07-15 17:05:32 -07001144 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001145 sup_acts = supported_actions_get(self)
1146 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001147 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001148 return
1149
1150 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1151 check_test_params=True)
1152 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1153 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001154
Dan Talayco551befa2010-07-15 17:05:32 -07001155class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001156 """
1157 Modify the dest IP address of an IP packet (TP1)
1158 """
Dan Talayco551befa2010-07-15 17:05:32 -07001159 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001160 sup_acts = supported_actions_get(self)
1161 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001162 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001163 return
1164
1165 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1166 check_test_params=True)
1167 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1168 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001169
1170class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001171 """
1172 Modify the source TCP port of a TCP packet (TP1)
1173 """
Dan Talayco551befa2010-07-15 17:05:32 -07001174 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001175 sup_acts = supported_actions_get(self)
1176 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001177 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001178 return
1179
1180 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1181 check_test_params=True)
1182 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1183 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001184
1185class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001186 """
1187 Modify the dest TCP port of a TCP packet (TP1)
1188 """
Dan Talayco551befa2010-07-15 17:05:32 -07001189 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001190 sup_acts = supported_actions_get(self)
1191 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001192 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001193 return
1194
1195 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1196 check_test_params=True)
1197 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1198 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001199
1200class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001201 """
1202 Modify the IP type of service of an IP packet (TP1)
1203 """
Dan Talayco551befa2010-07-15 17:05:32 -07001204 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001205 sup_acts = supported_actions_get(self)
1206 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001207 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001208 return
Dan Talayco551befa2010-07-15 17:05:32 -07001209
Dan Talayco4b2bee62010-07-20 14:10:05 -07001210 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1211 check_test_params=True)
1212 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001213 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001214
Dan Talaycof6e76c02012-03-23 10:56:12 -07001215class ModifyL2DstMC(BaseMatchCase):
1216 """
1217 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001218 """
1219 def runTest(self):
1220 sup_acts = supported_actions_get(self)
1221 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001222 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001223 return
1224
Dan Talaycof6e76c02012-03-23 10:56:12 -07001225 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1226 check_test_params=True)
1227 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001228 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001229
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001230class ModifyL2DstIngress(BaseMatchCase):
1231 """
1232 Modify the L2 dest and send to the ingress port
1233 """
1234 def runTest(self):
1235 sup_acts = supported_actions_get(self)
1236 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001237 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001238 return
1239
1240 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1241 check_test_params=True)
1242 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1243 action_list=acts, max_test=2, egr_count=0,
1244 ing_port=True)
1245
Dan Talaycod8ae7582012-03-23 12:24:56 -07001246class ModifyL2DstIngressMC(BaseMatchCase):
1247 """
1248 Modify the L2 dest and send to the ingress port
1249 """
1250 def runTest(self):
1251 sup_acts = supported_actions_get(self)
1252 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1253 skip_message_emit(self, "ModifyL2dstMC test")
1254 return
1255
1256 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1257 check_test_params=True)
1258 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1259 action_list=acts, max_test=2, egr_count=-1,
1260 ing_port=True)
1261
Dan Talaycof6e76c02012-03-23 10:56:12 -07001262class ModifyL2SrcMC(BaseMatchCase):
1263 """
1264 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001265 """
1266 def runTest(self):
1267 sup_acts = supported_actions_get(self)
1268 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001269 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001270 return
1271
Dan Talaycof6e76c02012-03-23 10:56:12 -07001272 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1273 check_test_params=True)
1274 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001275 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001276
1277class ModifyL2SrcDstMC(BaseMatchCase):
1278 """
1279 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001280 """
1281 def runTest(self):
1282 sup_acts = supported_actions_get(self)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001283 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1284 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1285 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001286 return
1287
Dan Talaycof6e76c02012-03-23 10:56:12 -07001288 mod_fields = ['dl_dst', 'dl_src']
1289 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1290 check_test_params=True)
1291 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001292 action_list=acts, max_test=2, egr_count=-1)
1293
1294class ModifyL2DstVIDMC(BaseMatchCase):
1295 """
1296 Modify the L2 dest and send to 2 ports
1297 """
1298 def runTest(self):
1299 sup_acts = supported_actions_get(self)
1300 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1301 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1302 skip_message_emit(self, "ModifyL2DstVIDMC test")
1303 return
1304
1305 mod_fields = ['dl_dst', 'dl_vlan']
1306 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1307 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1308 check_test_params=True)
1309 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1310 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001311
Dan Talaycofa6454f2012-04-05 10:04:13 -07001312class FlowToggle(BaseMatchCase):
1313 """
1314 Add flows to the table and modify them repeatedly
1315 """
1316 def runTest(self):
Dan Talayco50be7672012-04-05 11:38:08 -07001317 flow_count = test_param_get(self.config, 'ft_flow_count', default=20)
1318 iter_count = test_param_get(self.config, 'ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001319
1320 pa_logger.info("Running flow toggle with %d flows, %d iterations" %
1321 (flow_count, iter_count))
1322 acts = []
1323 acts.append(action.action_output())
1324 acts.append(action.action_output())
1325
1326 of_ports = pa_port_map.keys()
1327 if len(of_ports) < 3:
1328 self.assertTrue(False, "Too few ports for test")
1329
1330 for idx in range(2):
1331 acts[idx].port = of_ports[idx]
1332
1333 flows = []
1334 flows.append([])
1335 flows.append([])
1336
Dan Talayco50be7672012-04-05 11:38:08 -07001337 wildcards = ofp.OFPFW_DL_SRC | ofp.OFPFW_DL_DST
Dan Talaycofa6454f2012-04-05 10:04:13 -07001338 # Create up the flows in an array
1339 for toggle in range(2):
1340 for f_idx in range(flow_count):
1341 pkt = simple_tcp_packet(tcp_sport=f_idx)
1342 msg = message.flow_mod()
1343 match = parse.packet_to_flow_match(pkt)
1344 match.in_port = of_ports[3]
Dan Talayco50be7672012-04-05 11:38:08 -07001345 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001346 msg.match = match
1347 msg.buffer_id = 0xffffffff
1348 msg.actions.add(acts[toggle])
1349 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001350
1351 # Show two sample flows
1352 pa_logger.debug(flows[0][0].show())
1353 pa_logger.debug(flows[1][0].show())
1354
Dan Talaycofa6454f2012-04-05 10:04:13 -07001355 # Install the first set of flows
1356 for f_idx in range(flow_count):
1357 rv = self.controller.message_send(flows[0][f_idx])
1358 self.assertTrue(rv != -1, "Error installing flow %d" % f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001359 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycofa6454f2012-04-05 10:04:13 -07001360
1361 pa_logger.info("Installed %d flows" % flow_count)
1362
1363 # Repeatedly modify all the flows back and forth
1364 updates = 0
1365 # Report status about 5 times
1366 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001367 start = time.time()
1368 for iter_idx in range(iter_count):
1369 if not iter_idx % mod_val:
1370 pa_logger.info("Flow Toggle: iter %d of %d. " %
1371 (iter_idx, iter_count) +
1372 "%d updates in %d secs" %
1373 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001374 for toggle in range(2):
1375 t_idx = 1 - toggle
1376 for f_idx in range(flow_count):
1377 rv = self.controller.message_send(flows[t_idx][f_idx])
1378 updates += 1
1379 self.assertTrue(rv != -1, "Error modifying flow %d" %
1380 f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001381 self.assertEqual(do_barrier(self.controller), 0,
1382 "Barrier failed")
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001383
1384 end = time.time()
1385 divisor = end - start or (end - start + 1)
1386 pa_logger.info("Flow toggle: %d iterations" % iter_count)
1387 pa_logger.info(" %d flow mods in %d secs, %d mods/sec" %
1388 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001389
1390
Dan Talayco8a64e332012-03-28 14:53:20 -07001391# You can pick and choose these by commenting tests in or out
1392iter_classes = [
1393 basic.PacketIn,
1394 basic.PacketOut,
1395 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001396 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001397 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001398 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001399 AllWildcardMatch,
1400 AllWildcardMatchTagged,
1401 SingleWildcardMatch,
1402 SingleWildcardMatchTagged,
1403 ExactMatch,
1404 ExactMatchTagged,
1405 SingleWildcardMatch,
1406 ModifyL2Src,
1407 ModifyL2Dst,
1408 ModifyL2SrcMC,
1409 ModifyL2DstMC,
1410 ModifyL2SrcDstMC
1411 ]
1412
1413class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001414 """
1415 Iterate over a bunch of test cases
1416
1417 The cases come from the list above
1418 """
1419
Dan Talayco8a64e332012-03-28 14:53:20 -07001420 def runTest(self):
1421 count = test_param_get(self.config, 'iter_count', default=10)
1422 tests_done = 0
1423 pa_logger.info("Running iteration test " + str(count) + " times")
1424 start = time.time()
1425 last = start
1426 for idx in range(count):
1427 pa_logger.info("Iteration " + str(idx + 1))
1428 for cls in iter_classes:
1429 test = cls()
1430 test.inheritSetup(self)
1431 test.runTest()
1432 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001433 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001434 if time.time() - last > 60:
1435 last = time.time()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001436 pa_logger.info(
1437 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1438 (idx, count, tests_done, last - start) +
1439 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001440 stats = all_stats_get(self)
1441 last = time.time()
1442 pa_logger.info("\nIterCases ran %d tests in %d seconds." %
1443 (tests_done, last - start))
1444 pa_logger.info(" flows: %d. packets: %d. bytes: %d" %
1445 (stats["flows"], stats["packets"], stats["bytes"]))
1446 pa_logger.info(" active: %d. lookups: %d. matched %d." %
1447 (stats["active"], stats["lookups"], stats["matched"]))
1448
1449# Don't run by default
1450test_prio["IterCases"] = -1
Dan Talaycof6e76c02012-03-23 10:56:12 -07001451
Dan Talayco4b2bee62010-07-20 14:10:05 -07001452#@todo Need to implement tagged versions of the above tests
1453#
1454#@todo Implement a test case that strips tag 2, adds tag 3
1455# and modifies tag 4 to tag 5. Then verify (in addition) that
1456# tag 6 does not get modified.
1457
1458class MixedVLAN(BaseMatchCase):
1459 """
1460 Test mixture of VLAN tag actions
1461
1462 Strip tag 2 on port 1, send to port 2
1463 Add tag 3 on port 1, send to port 2
1464 Modify tag 4 to 5 on port 1, send to port 2
1465 All other traffic from port 1, send to port 3
1466 All traffic from port 2 sent to port 4
1467 Use exact matches with different packets for all mods
1468 Verify the following: (port, vid)
1469 (port 1, vid 2) => VLAN tag stripped, out port 2
1470 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1471 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1472 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1473 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1474 (port 2, no tag) => untagged packet out port 4
1475 (port 2, vid 2-6) => unmodified packet out port 4
1476
1477 Variation: Might try sending VID 5 to port 3 and check.
1478 If only VID 5 distinguishes pkt, this will fail on some platforms
1479 """
1480
1481test_prio["MixedVLAN"] = -1
1482
Dan Talayco551befa2010-07-15 17:05:32 -07001483def supported_actions_get(parent, use_cache=True):
1484 """
1485 Get the bitmap of supported actions from the switch
1486 If use_cache is false, the cached value will be updated
1487 """
1488 global cached_supported_actions
1489 if cached_supported_actions is None or not use_cache:
1490 request = message.features_request()
1491 (reply, pkt) = parent.controller.transact(request, timeout=2)
1492 parent.assertTrue(reply is not None, "Did not get response to ftr req")
1493 cached_supported_actions = reply.actions
1494 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
1495
1496 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -07001497
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001498if __name__ == "__main__":
1499 print "Please run through oft script: ./oft --test_spec=basic"