blob: c85e8be4c108f92fb184bcedf63e09ac9d00b233 [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 Townsend8364b162012-04-12 13:45:40 -0700834 def installFlow(self, prio, inp, egp,
835 wildcards=ofp.OFPFW_DL_SRC):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700836 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700837 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700838 egr_ports=egp)
839 request.priority = prio
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700840 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700841 self.flowMsgs[prio] = request
842
843 def removeFlow(self, prio):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700844 return
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700845 if self.flowMsgs.has_key(prio):
846 msg = self.flowMsgs[prio]
847 msg.command = ofp.OFPFC_DELETE_STRICT
848 # This *must* be set for DELETE
849 msg.out_port = ofp.OFPP_NONE
850 self.controller.message_send(msg)
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700851 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700852 else:
853 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700854
855
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700856 def verifyFlow(self, inp, egp, pkt=None):
857 if pkt == None:
858 pkt = self.pkt
859
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700860 self.logger.info("Pkt match test: " + str(inp) +
861 " to " + str(egp))
862 self.logger.debug("Send packet: " + str(inp) + " to "
863 + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700864 self.dataplane.send(inp, str(pkt))
865 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700866
867
868
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700869class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
870
871 def runTest(self):
872
873 self._Init()
874
875 of_ports = pa_port_map.keys()
876 of_ports.sort()
877
878 # Install an entry from 0 -> 1 @ prio 1000
879 self._ClearTable()
880 self.installFlow(1000, of_ports[0], of_ports[1])
881 self.verifyFlow(of_ports[0], of_ports[1])
882 self.installFlow(1000, of_ports[1], of_ports[0])
883 self.verifyFlow(of_ports[1], of_ports[0])
884 self.installFlow(1001, of_ports[0], of_ports[1])
885 self.verifyFlow(of_ports[0], of_ports[1])
886 self.installFlow(1001, of_ports[1], of_ports[0])
887 self.verifyFlow(of_ports[1], of_ports[0])
888 self.removeFlow(1001)
889 self.verifyFlow(of_ports[0], of_ports[1])
890 self.removeFlow(1000)
891
892
893
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700894class WildcardPriority(SingleWildcardMatchPriority):
895
896 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700897
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700898 self._Init()
899
900 of_ports = pa_port_map.keys()
901 of_ports.sort()
902
903 self._ClearTable()
904 # Install a flow with no wildcards for our packet:
905 self.installFlow(1000, of_ports[0], of_ports[1], wildcards=0)
906 self.verifyFlow(of_ports[0], of_ports[1])
907 # Install a flow with wildcards for our packet with higher
908 # priority.
909 self.installFlow(1001, of_ports[0], of_ports[2])
910 self.verifyFlow(of_ports[0], of_ports[2])
911
912
913
Dan Talayco551befa2010-07-15 17:05:32 -0700914class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700915 """
916 Exercise wildcard matching for all ports
917
918 Generate a packet
919 Generate and install a matching flow with wildcard mask
920 Add action to forward to a port
921 Send the packet to the port
922 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700923 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700924 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700925 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -0700926 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700927 for wc in WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -0700928 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -0700929 # Set nonzero VLAN id to avoid sending priority-tagged packet
930 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -0700931 else:
932 dl_vlan = -1
933 flow_match_test(self, pa_port_map, wildcards=wc,
934 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700935
Dan Talayco551befa2010-07-15 17:05:32 -0700936class SingleWildcardMatchTagged(BaseMatchCase):
937 """
938 SingleWildcardMatch with tagged packets
939 """
940 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700941 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700942 for wc in WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700943 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -0700944 max_test=10)
945
946class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700947 """
Dan Talayco80b54ed2010-07-13 09:48:35 -0700948 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700949
950 Generate a packet
951 Generate and install a matching flow with wildcard all except one filed
952 Add action to forward to a port
953 Send the packet to the port
954 Verify the packet is received at all other ports (one port at a time)
955 Verify flow_expiration message is correct when command option is set
956 """
957 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -0700958 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -0700959 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -0700960 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -0700961 # Set nonzero VLAN id to avoid sending priority-tagged packet
962 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -0700963 else:
964 dl_vlan = -1
965 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
966 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700967
Dan Talayco551befa2010-07-15 17:05:32 -0700968class AllExceptOneWildcardMatchTagged(BaseMatchCase):
969 """
970 Match one field with tagged packets
971 """
972 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700973 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -0700974 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700975 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
976 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -0700977
978class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700979 """
980 Create Wildcard-all flow and exercise for all ports
981
982 Generate a packet
983 Generate and install a matching flow with wildcard-all
984 Add action to forward to a port
985 Send the packet to the port
986 Verify the packet is received at all other ports (one port at a time)
987 Verify flow_expiration message is correct when command option is set
988 """
989 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700990 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700991
Dan Talayco551befa2010-07-15 17:05:32 -0700992class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700993 """
Dan Talayco551befa2010-07-15 17:05:32 -0700994 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700995 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700996 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700997 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700998 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
999 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001000
Dan Talaycoba3745c2010-07-21 21:51:08 -07001001
Dan Talayco551befa2010-07-15 17:05:32 -07001002class AddVLANTag(BaseMatchCase):
1003 """
1004 Add a VLAN tag to an untagged packet
1005 """
1006 def runTest(self):
1007 new_vid = 2
1008 sup_acts = supported_actions_get(self)
1009 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001010 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001011 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001012
Dan Talayco551befa2010-07-15 17:05:32 -07001013 len = 100
1014 len_w_vid = 104
1015 pkt = simple_tcp_packet(pktlen=len)
1016 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1017 dl_vlan=new_vid)
1018 vid_act = action.action_set_vlan_vid()
1019 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001020
Dan Talayco551befa2010-07-15 17:05:32 -07001021 flow_match_test(self, pa_port_map, pkt=pkt,
1022 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001023
Dan Talayco551befa2010-07-15 17:05:32 -07001024class PacketOnly(basic.DataPlaneOnly):
1025 """
1026 Just send a packet thru the switch
1027 """
1028 def runTest(self):
1029 pkt = simple_tcp_packet()
1030 of_ports = pa_port_map.keys()
1031 of_ports.sort()
1032 ing_port = of_ports[0]
1033 pa_logger.info("Sending packet to " + str(ing_port))
1034 pa_logger.debug("Data: " + str(pkt).encode('hex'))
1035 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001036
Dan Talayco551befa2010-07-15 17:05:32 -07001037class PacketOnlyTagged(basic.DataPlaneOnly):
1038 """
1039 Just send a packet thru the switch
1040 """
1041 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001042 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001043 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
1044 of_ports = pa_port_map.keys()
1045 of_ports.sort()
1046 ing_port = of_ports[0]
1047 pa_logger.info("Sending packet to " + str(ing_port))
1048 pa_logger.debug("Data: " + str(pkt).encode('hex'))
1049 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001050
Dan Talayco551befa2010-07-15 17:05:32 -07001051test_prio["PacketOnly"] = -1
1052test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001053
Dan Talayco551befa2010-07-15 17:05:32 -07001054class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001055 """
1056 Modify the VLAN ID in the VLAN tag of a tagged packet
1057 """
Dan Talayco551befa2010-07-15 17:05:32 -07001058 def runTest(self):
1059 old_vid = 2
1060 new_vid = 3
1061 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001062 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001063 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001064 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001065
Dan Talayco551befa2010-07-15 17:05:32 -07001066 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1067 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
1068 vid_act = action.action_set_vlan_vid()
1069 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001070
Dan Talayco551befa2010-07-15 17:05:32 -07001071 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1072 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001073
Howard Pershc1199d52012-04-11 14:21:32 -07001074class ModifyVlanPcp(BaseMatchCase):
1075 """
1076 Modify the priority field of the VLAN tag of a tagged packet
1077 """
1078 def runTest(self):
1079 vid = 123
1080 old_vlan_pcp = 2
1081 new_vlan_pcp = 3
1082 sup_acts = supported_actions_get(self)
1083 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1084 skip_message_emit(self, "Modify VLAN tag test")
1085 return
1086
1087 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1088 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1089 vid_act = action.action_set_vlan_pcp()
1090 vid_act.vlan_pcp = new_vlan_pcp
1091
1092 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1093 action_list=[vid_act])
1094
Dan Talayco551befa2010-07-15 17:05:32 -07001095class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001096 """
1097 Strip the VLAN tag from a tagged packet
1098 """
Dan Talayco551befa2010-07-15 17:05:32 -07001099 def runTest(self):
1100 old_vid = 2
1101 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001102 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001103 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001104 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001105
Dan Talayco551befa2010-07-15 17:05:32 -07001106 len_w_vid = 104
1107 len = 100
1108 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1109 dl_vlan=old_vid)
1110 exp_pkt = simple_tcp_packet(pktlen=len)
1111 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001112
Dan Talayco551befa2010-07-15 17:05:32 -07001113 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1114 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001115
Dan Talayco4b2bee62010-07-20 14:10:05 -07001116def init_pkt_args():
1117 """
1118 Pass back a dictionary with default packet arguments
1119 """
1120 args = {}
1121 args["dl_src"] = '00:23:45:67:89:AB'
1122
1123 dl_vlan_enable=False
1124 dl_vlan=-1
1125 if pa_config["test-params"]["vid"]:
1126 dl_vlan_enable=True
1127 dl_vlan = pa_config["test-params"]["vid"]
1128
1129# Unpack operator is ** on a dictionary
1130
1131 return args
1132
Dan Talayco551befa2010-07-15 17:05:32 -07001133class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001134 """
1135 Modify the source MAC address (TP1)
1136 """
Dan Talayco551befa2010-07-15 17:05:32 -07001137 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001138 sup_acts = supported_actions_get(self)
1139 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001140 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001141 return
1142
1143 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1144 check_test_params=True)
1145 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1146 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001147
Dan Talayco551befa2010-07-15 17:05:32 -07001148class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001149 """
1150 Modify the dest MAC address (TP1)
1151 """
Dan Talayco551befa2010-07-15 17:05:32 -07001152 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001153 sup_acts = supported_actions_get(self)
1154 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001155 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001156 return
1157
1158 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1159 check_test_params=True)
1160 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1161 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001162
Dan Talayco551befa2010-07-15 17:05:32 -07001163class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001164 """
1165 Modify the source IP address of an IP packet (TP1)
1166 """
Dan Talayco551befa2010-07-15 17:05:32 -07001167 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001168 sup_acts = supported_actions_get(self)
1169 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001170 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001171 return
1172
1173 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1174 check_test_params=True)
1175 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1176 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001177
Dan Talayco551befa2010-07-15 17:05:32 -07001178class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001179 """
1180 Modify the dest IP address of an IP packet (TP1)
1181 """
Dan Talayco551befa2010-07-15 17:05:32 -07001182 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001183 sup_acts = supported_actions_get(self)
1184 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001185 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001186 return
1187
1188 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1189 check_test_params=True)
1190 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1191 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001192
1193class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001194 """
1195 Modify the source TCP port of a TCP packet (TP1)
1196 """
Dan Talayco551befa2010-07-15 17:05:32 -07001197 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001198 sup_acts = supported_actions_get(self)
1199 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001200 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001201 return
1202
1203 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1204 check_test_params=True)
1205 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1206 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001207
1208class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001209 """
1210 Modify the dest TCP port of a TCP packet (TP1)
1211 """
Dan Talayco551befa2010-07-15 17:05:32 -07001212 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001213 sup_acts = supported_actions_get(self)
1214 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001215 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001216 return
1217
1218 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1219 check_test_params=True)
1220 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1221 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001222
1223class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001224 """
1225 Modify the IP type of service of an IP packet (TP1)
1226 """
Dan Talayco551befa2010-07-15 17:05:32 -07001227 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001228 sup_acts = supported_actions_get(self)
1229 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001230 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001231 return
Dan Talayco551befa2010-07-15 17:05:32 -07001232
Dan Talayco4b2bee62010-07-20 14:10:05 -07001233 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1234 check_test_params=True)
1235 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001236 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001237
Dan Talaycof6e76c02012-03-23 10:56:12 -07001238class ModifyL2DstMC(BaseMatchCase):
1239 """
1240 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001241 """
1242 def runTest(self):
1243 sup_acts = supported_actions_get(self)
1244 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001245 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001246 return
1247
Dan Talaycof6e76c02012-03-23 10:56:12 -07001248 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1249 check_test_params=True)
1250 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001251 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001252
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001253class ModifyL2DstIngress(BaseMatchCase):
1254 """
1255 Modify the L2 dest and send to the ingress port
1256 """
1257 def runTest(self):
1258 sup_acts = supported_actions_get(self)
1259 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001260 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001261 return
1262
1263 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1264 check_test_params=True)
1265 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1266 action_list=acts, max_test=2, egr_count=0,
1267 ing_port=True)
1268
Dan Talaycod8ae7582012-03-23 12:24:56 -07001269class ModifyL2DstIngressMC(BaseMatchCase):
1270 """
1271 Modify the L2 dest and send to the ingress port
1272 """
1273 def runTest(self):
1274 sup_acts = supported_actions_get(self)
1275 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1276 skip_message_emit(self, "ModifyL2dstMC test")
1277 return
1278
1279 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1280 check_test_params=True)
1281 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1282 action_list=acts, max_test=2, egr_count=-1,
1283 ing_port=True)
1284
Dan Talaycof6e76c02012-03-23 10:56:12 -07001285class ModifyL2SrcMC(BaseMatchCase):
1286 """
1287 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001288 """
1289 def runTest(self):
1290 sup_acts = supported_actions_get(self)
1291 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001292 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001293 return
1294
Dan Talaycof6e76c02012-03-23 10:56:12 -07001295 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1296 check_test_params=True)
1297 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001298 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001299
1300class ModifyL2SrcDstMC(BaseMatchCase):
1301 """
1302 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001303 """
1304 def runTest(self):
1305 sup_acts = supported_actions_get(self)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001306 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1307 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1308 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001309 return
1310
Dan Talaycof6e76c02012-03-23 10:56:12 -07001311 mod_fields = ['dl_dst', 'dl_src']
1312 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1313 check_test_params=True)
1314 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001315 action_list=acts, max_test=2, egr_count=-1)
1316
1317class ModifyL2DstVIDMC(BaseMatchCase):
1318 """
1319 Modify the L2 dest and send to 2 ports
1320 """
1321 def runTest(self):
1322 sup_acts = supported_actions_get(self)
1323 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1324 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1325 skip_message_emit(self, "ModifyL2DstVIDMC test")
1326 return
1327
1328 mod_fields = ['dl_dst', 'dl_vlan']
1329 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1330 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1331 check_test_params=True)
1332 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1333 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001334
Dan Talaycofa6454f2012-04-05 10:04:13 -07001335class FlowToggle(BaseMatchCase):
1336 """
1337 Add flows to the table and modify them repeatedly
1338 """
1339 def runTest(self):
Dan Talayco50be7672012-04-05 11:38:08 -07001340 flow_count = test_param_get(self.config, 'ft_flow_count', default=20)
1341 iter_count = test_param_get(self.config, 'ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001342
1343 pa_logger.info("Running flow toggle with %d flows, %d iterations" %
1344 (flow_count, iter_count))
1345 acts = []
1346 acts.append(action.action_output())
1347 acts.append(action.action_output())
1348
1349 of_ports = pa_port_map.keys()
1350 if len(of_ports) < 3:
1351 self.assertTrue(False, "Too few ports for test")
1352
1353 for idx in range(2):
1354 acts[idx].port = of_ports[idx]
1355
1356 flows = []
1357 flows.append([])
1358 flows.append([])
1359
Dan Talayco50be7672012-04-05 11:38:08 -07001360 wildcards = ofp.OFPFW_DL_SRC | ofp.OFPFW_DL_DST
Dan Talaycofa6454f2012-04-05 10:04:13 -07001361 # Create up the flows in an array
1362 for toggle in range(2):
1363 for f_idx in range(flow_count):
1364 pkt = simple_tcp_packet(tcp_sport=f_idx)
1365 msg = message.flow_mod()
1366 match = parse.packet_to_flow_match(pkt)
1367 match.in_port = of_ports[3]
Dan Talayco50be7672012-04-05 11:38:08 -07001368 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001369 msg.match = match
1370 msg.buffer_id = 0xffffffff
1371 msg.actions.add(acts[toggle])
1372 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001373
1374 # Show two sample flows
1375 pa_logger.debug(flows[0][0].show())
1376 pa_logger.debug(flows[1][0].show())
1377
Dan Talaycofa6454f2012-04-05 10:04:13 -07001378 # Install the first set of flows
1379 for f_idx in range(flow_count):
1380 rv = self.controller.message_send(flows[0][f_idx])
1381 self.assertTrue(rv != -1, "Error installing flow %d" % f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001382 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycofa6454f2012-04-05 10:04:13 -07001383
1384 pa_logger.info("Installed %d flows" % flow_count)
1385
1386 # Repeatedly modify all the flows back and forth
1387 updates = 0
1388 # Report status about 5 times
1389 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001390 start = time.time()
1391 for iter_idx in range(iter_count):
1392 if not iter_idx % mod_val:
1393 pa_logger.info("Flow Toggle: iter %d of %d. " %
1394 (iter_idx, iter_count) +
1395 "%d updates in %d secs" %
1396 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001397 for toggle in range(2):
1398 t_idx = 1 - toggle
1399 for f_idx in range(flow_count):
1400 rv = self.controller.message_send(flows[t_idx][f_idx])
1401 updates += 1
1402 self.assertTrue(rv != -1, "Error modifying flow %d" %
1403 f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001404 self.assertEqual(do_barrier(self.controller), 0,
1405 "Barrier failed")
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001406
1407 end = time.time()
1408 divisor = end - start or (end - start + 1)
1409 pa_logger.info("Flow toggle: %d iterations" % iter_count)
1410 pa_logger.info(" %d flow mods in %d secs, %d mods/sec" %
1411 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001412
1413
Dan Talayco8a64e332012-03-28 14:53:20 -07001414# You can pick and choose these by commenting tests in or out
1415iter_classes = [
1416 basic.PacketIn,
1417 basic.PacketOut,
1418 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001419 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001420 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001421 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001422 AllWildcardMatch,
1423 AllWildcardMatchTagged,
1424 SingleWildcardMatch,
1425 SingleWildcardMatchTagged,
1426 ExactMatch,
1427 ExactMatchTagged,
1428 SingleWildcardMatch,
1429 ModifyL2Src,
1430 ModifyL2Dst,
1431 ModifyL2SrcMC,
1432 ModifyL2DstMC,
1433 ModifyL2SrcDstMC
1434 ]
1435
1436class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001437 """
1438 Iterate over a bunch of test cases
1439
1440 The cases come from the list above
1441 """
1442
Dan Talayco8a64e332012-03-28 14:53:20 -07001443 def runTest(self):
1444 count = test_param_get(self.config, 'iter_count', default=10)
1445 tests_done = 0
1446 pa_logger.info("Running iteration test " + str(count) + " times")
1447 start = time.time()
1448 last = start
1449 for idx in range(count):
1450 pa_logger.info("Iteration " + str(idx + 1))
1451 for cls in iter_classes:
1452 test = cls()
1453 test.inheritSetup(self)
1454 test.runTest()
1455 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001456 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001457 if time.time() - last > 60:
1458 last = time.time()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001459 pa_logger.info(
1460 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1461 (idx, count, tests_done, last - start) +
1462 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001463 stats = all_stats_get(self)
1464 last = time.time()
1465 pa_logger.info("\nIterCases ran %d tests in %d seconds." %
1466 (tests_done, last - start))
1467 pa_logger.info(" flows: %d. packets: %d. bytes: %d" %
1468 (stats["flows"], stats["packets"], stats["bytes"]))
1469 pa_logger.info(" active: %d. lookups: %d. matched %d." %
1470 (stats["active"], stats["lookups"], stats["matched"]))
1471
1472# Don't run by default
1473test_prio["IterCases"] = -1
Dan Talaycof6e76c02012-03-23 10:56:12 -07001474
Dan Talayco4b2bee62010-07-20 14:10:05 -07001475#@todo Need to implement tagged versions of the above tests
1476#
1477#@todo Implement a test case that strips tag 2, adds tag 3
1478# and modifies tag 4 to tag 5. Then verify (in addition) that
1479# tag 6 does not get modified.
1480
1481class MixedVLAN(BaseMatchCase):
1482 """
1483 Test mixture of VLAN tag actions
1484
1485 Strip tag 2 on port 1, send to port 2
1486 Add tag 3 on port 1, send to port 2
1487 Modify tag 4 to 5 on port 1, send to port 2
1488 All other traffic from port 1, send to port 3
1489 All traffic from port 2 sent to port 4
1490 Use exact matches with different packets for all mods
1491 Verify the following: (port, vid)
1492 (port 1, vid 2) => VLAN tag stripped, out port 2
1493 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1494 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1495 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1496 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1497 (port 2, no tag) => untagged packet out port 4
1498 (port 2, vid 2-6) => unmodified packet out port 4
1499
1500 Variation: Might try sending VID 5 to port 3 and check.
1501 If only VID 5 distinguishes pkt, this will fail on some platforms
1502 """
1503
1504test_prio["MixedVLAN"] = -1
1505
Dan Talayco551befa2010-07-15 17:05:32 -07001506def supported_actions_get(parent, use_cache=True):
1507 """
1508 Get the bitmap of supported actions from the switch
1509 If use_cache is false, the cached value will be updated
1510 """
1511 global cached_supported_actions
1512 if cached_supported_actions is None or not use_cache:
1513 request = message.features_request()
1514 (reply, pkt) = parent.controller.transact(request, timeout=2)
1515 parent.assertTrue(reply is not None, "Did not get response to ftr req")
1516 cached_supported_actions = reply.actions
1517 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
1518
1519 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -07001520
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001521if __name__ == "__main__":
1522 print "Please run through oft script: ./oft --test_spec=basic"