blob: 4598262331e9bfc837242a24cf445db7f5717ca2 [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
Howard Persh670b5672012-04-13 09:08:29 -0700199 def portQueuesGet(self, queue_stats, port_num):
200 result = []
201 for qs in queue_stats.stats:
202 if qs.port_no != port_num:
203 continue
204 result.append(qs.queue_id)
205 return result
206
Howard Pershf97840f2012-04-10 16:30:42 -0700207 def handleFlow(self, pkttype='TCP'):
208 of_ports = pa_port_map.keys()
209 of_ports.sort()
210 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
211
212 if (pkttype == 'ICMP'):
213 pkt = simple_icmp_packet()
214 else:
215 pkt = simple_tcp_packet()
216 match = parse.packet_to_flow_match(pkt)
217 match.wildcards &= ~ofp.OFPFW_IN_PORT
218 self.assertTrue(match is not None,
219 "Could not generate flow match from pkt")
220
Howard Persh670b5672012-04-13 09:08:29 -0700221 # Get queue stats from switch
222
223 request = message.queue_stats_request()
224 request.port_no = ofp.OFPP_ALL
225 request.queue_id = ofp.OFPQ_ALL
226 (queue_stats, pkt) = self.controller.transact(request, timeout=2)
227 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
228
229 act = action.action_enqueue()
Howard Pershf97840f2012-04-10 16:30:42 -0700230
231 for idx in range(len(of_ports)):
Howard Pershf97840f2012-04-10 16:30:42 -0700232 ingress_port = of_ports[idx]
233 egress_port = of_ports[(idx + 1) % len(of_ports)]
Howard Pershf97840f2012-04-10 16:30:42 -0700234
Howard Persh670b5672012-04-13 09:08:29 -0700235 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
236 pa_logger.info("Ingress " + str(ingress_port)
237 + " to egress " + str(egress_port)
238 + " queue " + str(egress_queue_id)
239 )
Howard Pershf97840f2012-04-10 16:30:42 -0700240
Howard Persh670b5672012-04-13 09:08:29 -0700241 rv = delete_all_flows(self.controller, pa_logger)
242 self.assertEqual(rv, 0, "Failed to delete all flows")
Howard Pershf97840f2012-04-10 16:30:42 -0700243
Howard Persh670b5672012-04-13 09:08:29 -0700244 match.in_port = ingress_port
245
246 request = message.flow_mod()
247 request.match = match
Howard Pershf97840f2012-04-10 16:30:42 -0700248
Howard Persh670b5672012-04-13 09:08:29 -0700249 request.buffer_id = 0xffffffff
250 act.port = egress_port
251 act.queue_id = egress_queue_id
252 self.assertTrue(request.actions.add(act), "Could not add action")
Howard Pershf97840f2012-04-10 16:30:42 -0700253
Howard Persh670b5672012-04-13 09:08:29 -0700254 pa_logger.info("Inserting flow")
255 rv = self.controller.message_send(request)
256 self.assertTrue(rv != -1, "Error installing flow mod")
257 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Howard Pershf97840f2012-04-10 16:30:42 -0700258
Howard Persh670b5672012-04-13 09:08:29 -0700259 # Get current stats for selected egress queue
Howard Pershf97840f2012-04-10 16:30:42 -0700260
Howard Persh670b5672012-04-13 09:08:29 -0700261 request = message.queue_stats_request()
262 request.port_no = egress_port
263 request.queue_id = egress_queue_id
264 (qs_before, pkt) = self.controller.transact(request, timeout=2)
265 self.assertNotEqual(qs_before, None, "Queue stats request failed")
266
267 pa_logger.info("Sending packet to dp port " +
268 str(ingress_port))
269 self.dataplane.send(ingress_port, str(pkt))
270
271 exp_pkt_arg = None
272 exp_port = None
273 if pa_config["relax"]:
274 exp_pkt_arg = pkt
275 exp_port = egress_port
276
277 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(timeout=1,
278 port_number=exp_port,
279 exp_pkt=exp_pkt_arg)
280 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
281 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
282 str(rcv_port))
283 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
284 self.assertEqual(str(pkt), str(rcv_pkt),
285 'Response packet does not match send packet')
286
287 # Get current stats for selected egress queue again
288
289 request = message.queue_stats_request()
290 request.port_no = egress_port
291 request.queue_id = egress_queue_id
292 (qs_after, pkt) = self.controller.transact(request, timeout=2)
293 self.assertNotEqual(qs_after, None, "Queue stats request failed")
294
295 # Make sure that tx packet counter for selected egress queue was
296 # incremented
297
298 self.assertEqual(qs_after.stats.stats[0].tx_packets, \
299 qs_before.stats.stats[0].tx_packets + 1, \
300 "Verification of egress queue tx packet count failed"
301 )
302
303
Howard Pershf97840f2012-04-10 16:30:42 -0700304
305
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700306class DirectPacketICMP(DirectPacket):
307 """
308 Send ICMP packet to single egress port
309
310 Generate a ICMP packet
311 Generate and install a matching flow
312 Add action to direct the packet to an egress port
313 Send the packet to ingress dataplane port
314 Verify the packet is received at the egress port only
315 Difference from DirectPacket test is that sent packet is ICMP
316 """
317 def runTest(self):
318 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700319
320class DirectTwoPorts(basic.SimpleDataPlane):
321 """
322 Send packet to two egress ports
323
324 Generate a packet
325 Generate and install a matching flow
326 Add action to direct the packet to two egress ports
327 Send the packet to ingress dataplane port
328 Verify the packet is received at the two egress ports
329 """
330 def runTest(self):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700331 of_ports = pa_port_map.keys()
332 of_ports.sort()
333 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
334
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700335 pkt = simple_tcp_packet()
336 match = parse.packet_to_flow_match(pkt)
337 match.wildcards &= ~ofp.OFPFW_IN_PORT
338 self.assertTrue(match is not None,
339 "Could not generate flow match from pkt")
340 act = action.action_output()
341
342 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700343 rv = delete_all_flows(self.controller, pa_logger)
344 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700345
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700346 ingress_port = of_ports[idx]
347 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
348 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
349 pa_logger.info("Ingress " + str(ingress_port) +
350 " to egress " + str(egress_port1) + " and " +
351 str(egress_port2))
352
353 match.in_port = ingress_port
354
355 request = message.flow_mod()
356 request.match = match
357 request.buffer_id = 0xffffffff
358 act.port = egress_port1
359 self.assertTrue(request.actions.add(act), "Could not add action1")
360 act.port = egress_port2
361 self.assertTrue(request.actions.add(act), "Could not add action2")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700362 # pa_logger.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700363
364 pa_logger.info("Inserting flow")
365 rv = self.controller.message_send(request)
366 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700367 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700368
369 pa_logger.info("Sending packet to dp port " +
370 str(ingress_port))
371 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700372 yes_ports = set([egress_port1, egress_port2])
373 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700374
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700375 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700376 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700377
378class DirectMCNonIngress(basic.SimpleDataPlane):
379 """
380 Multicast to all non-ingress ports
381
382 Generate a packet
383 Generate and install a matching flow
384 Add action to direct the packet to all non-ingress ports
385 Send the packet to ingress dataplane port
386 Verify the packet is received at all non-ingress ports
387
388 Does not use the flood action
389 """
390 def runTest(self):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700391 of_ports = pa_port_map.keys()
392 of_ports.sort()
393 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
394
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700395 pkt = simple_tcp_packet()
396 match = parse.packet_to_flow_match(pkt)
397 match.wildcards &= ~ofp.OFPFW_IN_PORT
398 self.assertTrue(match is not None,
399 "Could not generate flow match from pkt")
400 act = action.action_output()
401
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700402 for ingress_port in of_ports:
403 rv = delete_all_flows(self.controller, pa_logger)
404 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700405
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700406 pa_logger.info("Ingress " + str(ingress_port) +
407 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700408 match.in_port = ingress_port
409
410 request = message.flow_mod()
411 request.match = match
412 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700413 for egress_port in of_ports:
414 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700415 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700416 act.port = egress_port
417 self.assertTrue(request.actions.add(act),
418 "Could not add output to " + str(egress_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700419 pa_logger.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700420
421 pa_logger.info("Inserting flow")
422 rv = self.controller.message_send(request)
423 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700424 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700425
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700426 pa_logger.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700427 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700428 yes_ports = set(of_ports).difference([ingress_port])
429 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700430 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700431
Dan Talayco32fa6542010-05-11 15:54:08 -0700432
433class DirectMC(basic.SimpleDataPlane):
434 """
435 Multicast to all ports including ingress
436
437 Generate a packet
438 Generate and install a matching flow
439 Add action to direct the packet to all non-ingress ports
440 Send the packet to ingress dataplane port
441 Verify the packet is received at all ports
442
443 Does not use the flood action
444 """
445 def runTest(self):
Dan Talayco32fa6542010-05-11 15:54:08 -0700446 of_ports = pa_port_map.keys()
447 of_ports.sort()
448 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
449
Dan Talayco32fa6542010-05-11 15:54:08 -0700450 pkt = simple_tcp_packet()
451 match = parse.packet_to_flow_match(pkt)
452 match.wildcards &= ~ofp.OFPFW_IN_PORT
453 self.assertTrue(match is not None,
454 "Could not generate flow match from pkt")
455 act = action.action_output()
456
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700457 for ingress_port in of_ports:
458 rv = delete_all_flows(self.controller, pa_logger)
459 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700460
Dan Talayco32fa6542010-05-11 15:54:08 -0700461 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700462 match.in_port = ingress_port
463
464 request = message.flow_mod()
465 request.match = match
466 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700467 for egress_port in of_ports:
468 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700469 act.port = ofp.OFPP_IN_PORT
470 else:
471 act.port = egress_port
472 self.assertTrue(request.actions.add(act),
473 "Could not add output to " + str(egress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700474 # pa_logger.info(request.show())
475
476 pa_logger.info("Inserting flow")
477 rv = self.controller.message_send(request)
478 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700479 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2e77a842010-05-12 15:39:46 -0700480
481 pa_logger.info("Sending packet to dp port " + str(ingress_port))
482 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700483 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700484 pa_logger, pa_config)
Dan Talayco2e77a842010-05-12 15:39:46 -0700485
486class Flood(basic.SimpleDataPlane):
487 """
488 Flood to all ports except ingress
489
490 Generate a packet
491 Generate and install a matching flow
492 Add action to flood the packet
493 Send the packet to ingress dataplane port
494 Verify the packet is received at all other ports
495 """
496 def runTest(self):
Dan Talayco2e77a842010-05-12 15:39:46 -0700497 of_ports = pa_port_map.keys()
498 of_ports.sort()
499 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
500
501 pkt = simple_tcp_packet()
502 match = parse.packet_to_flow_match(pkt)
503 match.wildcards &= ~ofp.OFPFW_IN_PORT
504 self.assertTrue(match is not None,
505 "Could not generate flow match from pkt")
506 act = action.action_output()
507
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700508 for ingress_port in of_ports:
509 rv = delete_all_flows(self.controller, pa_logger)
510 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700511
Dan Talayco2e77a842010-05-12 15:39:46 -0700512 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700513 match.in_port = ingress_port
514
515 request = message.flow_mod()
516 request.match = match
517 request.buffer_id = 0xffffffff
518 act.port = ofp.OFPP_FLOOD
519 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700520 "Could not add flood port action")
Dan Talayco32fa6542010-05-11 15:54:08 -0700521 pa_logger.info(request.show())
522
523 pa_logger.info("Inserting flow")
524 rv = self.controller.message_send(request)
525 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700526 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco32fa6542010-05-11 15:54:08 -0700527
528 pa_logger.info("Sending packet to dp port " + str(ingress_port))
529 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700530 yes_ports = set(of_ports).difference([ingress_port])
531 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700532 self, pa_logger, pa_config)
Dan Talayco3be5b062010-05-12 15:46:21 -0700533
Dan Talayco3be5b062010-05-12 15:46:21 -0700534class FloodPlusIngress(basic.SimpleDataPlane):
535 """
536 Flood to all ports plus send to ingress port
537
538 Generate a packet
539 Generate and install a matching flow
540 Add action to flood the packet
541 Add action to send to ingress port
542 Send the packet to ingress dataplane port
543 Verify the packet is received at all other ports
544 """
545 def runTest(self):
Dan Talayco3be5b062010-05-12 15:46:21 -0700546 of_ports = pa_port_map.keys()
547 of_ports.sort()
548 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
549
550 pkt = simple_tcp_packet()
551 match = parse.packet_to_flow_match(pkt)
552 match.wildcards &= ~ofp.OFPFW_IN_PORT
553 self.assertTrue(match is not None,
554 "Could not generate flow match from pkt")
555 act = action.action_output()
556
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700557 for ingress_port in of_ports:
558 rv = delete_all_flows(self.controller, pa_logger)
559 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700560
Dan Talayco3be5b062010-05-12 15:46:21 -0700561 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700562 match.in_port = ingress_port
563
564 request = message.flow_mod()
565 request.match = match
566 request.buffer_id = 0xffffffff
567 act.port = ofp.OFPP_FLOOD
568 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700569 "Could not add flood port action")
570 act.port = ofp.OFPP_IN_PORT
571 self.assertTrue(request.actions.add(act),
572 "Could not add ingress port for output")
573 pa_logger.info(request.show())
574
575 pa_logger.info("Inserting flow")
576 rv = self.controller.message_send(request)
577 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700578 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700579
580 pa_logger.info("Sending packet to dp port " + str(ingress_port))
581 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700582 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700583 pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700584
585class All(basic.SimpleDataPlane):
586 """
587 Send to OFPP_ALL port
588
589 Generate a packet
590 Generate and install a matching flow
591 Add action to forward to OFPP_ALL
592 Send the packet to ingress dataplane port
593 Verify the packet is received at all other ports
594 """
595 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700596 of_ports = pa_port_map.keys()
597 of_ports.sort()
598 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
599
600 pkt = simple_tcp_packet()
601 match = parse.packet_to_flow_match(pkt)
602 match.wildcards &= ~ofp.OFPFW_IN_PORT
603 self.assertTrue(match is not None,
604 "Could not generate flow match from pkt")
605 act = action.action_output()
606
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700607 for ingress_port in of_ports:
608 rv = delete_all_flows(self.controller, pa_logger)
609 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700610
Dan Talayco4aa13122010-05-12 15:54:44 -0700611 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700612 match.in_port = ingress_port
613
614 request = message.flow_mod()
615 request.match = match
616 request.buffer_id = 0xffffffff
617 act.port = ofp.OFPP_ALL
618 self.assertTrue(request.actions.add(act),
619 "Could not add ALL port action")
620 pa_logger.info(request.show())
621
622 pa_logger.info("Inserting flow")
623 rv = self.controller.message_send(request)
624 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700625 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700626
627 pa_logger.info("Sending packet to dp port " + str(ingress_port))
628 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700629 yes_ports = set(of_ports).difference([ingress_port])
630 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700631 self, pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700632
633class AllPlusIngress(basic.SimpleDataPlane):
634 """
635 Send to OFPP_ALL port and ingress port
636
637 Generate a packet
638 Generate and install a matching flow
639 Add action to forward to OFPP_ALL
640 Add action to forward to ingress port
641 Send the packet to ingress dataplane port
642 Verify the packet is received at all other ports
643 """
644 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700645 of_ports = pa_port_map.keys()
646 of_ports.sort()
647 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
648
649 pkt = simple_tcp_packet()
650 match = parse.packet_to_flow_match(pkt)
651 match.wildcards &= ~ofp.OFPFW_IN_PORT
652 self.assertTrue(match is not None,
653 "Could not generate flow match from pkt")
654 act = action.action_output()
655
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700656 for ingress_port in of_ports:
657 rv = delete_all_flows(self.controller, pa_logger)
658 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700659
Dan Talayco4aa13122010-05-12 15:54:44 -0700660 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700661 match.in_port = ingress_port
662
663 request = message.flow_mod()
664 request.match = match
665 request.buffer_id = 0xffffffff
666 act.port = ofp.OFPP_ALL
667 self.assertTrue(request.actions.add(act),
668 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700669 act.port = ofp.OFPP_IN_PORT
670 self.assertTrue(request.actions.add(act),
671 "Could not add ingress port for output")
672 pa_logger.info(request.show())
673
674 pa_logger.info("Inserting flow")
675 rv = self.controller.message_send(request)
676 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700677 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco3be5b062010-05-12 15:46:21 -0700678
679 pa_logger.info("Sending packet to dp port " + str(ingress_port))
680 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700681 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700682 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700683
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700684class FloodMinusPort(basic.SimpleDataPlane):
685 """
686 Config port with No_Flood and test Flood action
687
688 Generate a packet
689 Generate a matching flow
690 Add action to forward to OFPP_ALL
691 Set port to no-flood
692 Send the packet to ingress dataplane port
693 Verify the packet is received at all other ports except
694 the ingress port and the no_flood port
695 """
696 def runTest(self):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700697 of_ports = pa_port_map.keys()
698 of_ports.sort()
699 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
700
701 pkt = simple_tcp_packet()
702 match = parse.packet_to_flow_match(pkt)
703 match.wildcards &= ~ofp.OFPFW_IN_PORT
704 self.assertTrue(match is not None,
705 "Could not generate flow match from pkt")
706 act = action.action_output()
707
708 for idx in range(len(of_ports)):
709 rv = delete_all_flows(self.controller, pa_logger)
710 self.assertEqual(rv, 0, "Failed to delete all flows")
711
712 ingress_port = of_ports[idx]
713 no_flood_idx = (idx + 1) % len(of_ports)
714 no_flood_port = of_ports[no_flood_idx]
715 rv = port_config_set(self.controller, no_flood_port,
716 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
717 pa_logger)
718 self.assertEqual(rv, 0, "Failed to set port config")
719
720 match.in_port = ingress_port
721
722 request = message.flow_mod()
723 request.match = match
724 request.buffer_id = 0xffffffff
725 act.port = ofp.OFPP_FLOOD
726 self.assertTrue(request.actions.add(act),
727 "Could not add flood port action")
728 pa_logger.info(request.show())
729
730 pa_logger.info("Inserting flow")
731 rv = self.controller.message_send(request)
732 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700733 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700734
735 pa_logger.info("Sending packet to dp port " + str(ingress_port))
736 pa_logger.info("No flood port is " + str(no_flood_port))
737 self.dataplane.send(ingress_port, str(pkt))
738 no_ports = set([ingress_port, no_flood_port])
739 yes_ports = set(of_ports).difference(no_ports)
740 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700741 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700742
743 # Turn no flood off again
744 rv = port_config_set(self.controller, no_flood_port,
745 0, ofp.OFPPC_NO_FLOOD, pa_logger)
746 self.assertEqual(rv, 0, "Failed to reset port config")
747
748 #@todo Should check no other packets received
749
Dan Talayco21381562010-07-17 00:34:47 -0700750
751
Dan Talayco551befa2010-07-15 17:05:32 -0700752################################################################
753
754class BaseMatchCase(basic.SimpleDataPlane):
755 def setUp(self):
756 basic.SimpleDataPlane.setUp(self)
757 self.logger = pa_logger
758 def runTest(self):
759 self.logger.info("BaseMatchCase")
760
761class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700762 """
Dan Talayco551befa2010-07-15 17:05:32 -0700763 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700764
765 Generate a packet
766 Generate and install a matching flow without wildcard mask
767 Add action to forward to a port
768 Send the packet to the port
769 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700770 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700771
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700772 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700773 flow_match_test(self, pa_port_map)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700774
Dan Talayco551befa2010-07-15 17:05:32 -0700775class ExactMatchTagged(BaseMatchCase):
776 """
777 Exact match for all port pairs with tagged pkts
778 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700779
Dan Talayco551befa2010-07-15 17:05:32 -0700780 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700781 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700782 flow_match_test(self, pa_port_map, dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700783
Dan Talayco551befa2010-07-15 17:05:32 -0700784class ExactMatchTaggedMany(BaseMatchCase):
785 """
786 ExactMatchTagged with many VLANS
787 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700788
Dan Talayco551befa2010-07-15 17:05:32 -0700789 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700790 for vid in range(2,100,10):
Dan Talayco551befa2010-07-15 17:05:32 -0700791 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
792 for vid in range(100,4000,389):
793 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
794 flow_match_test(self, pa_port_map, dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700795
Dan Talayco551befa2010-07-15 17:05:32 -0700796# Don't run by default
797test_prio["ExactMatchTaggedMany"] = -1
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700798
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700799
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700800class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700801 """
802 SingleWildcardMatchPriority
803 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700804
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700805 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700806 self.pkt = simple_tcp_packet()
807 self.flowMsgs = {}
808
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700809 def _ClearTable(self):
810 rc = delete_all_flows(self.controller, self.logger)
811 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700812 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700813
814 def runTest(self):
815
816 self._Init()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700817 of_ports = pa_port_map.keys()
818 of_ports.sort()
819
820 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700821 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700822
823 # Run several combinations, each at lower priority settings.
824 # At the end of each call to runPrioFlows(), the table should
825 # be empty. If its not, we'll catch it as the priorities decreases
826 portA = of_ports[0]
827 portB = of_ports[1]
828 portC = of_ports[2]
829
830 # TODO -- these priority numbers should be validated somehow?
831 self.runPrioFlows(portA, portB, portC, 1000, 999)
832 self.runPrioFlows(portB, portC, portA, 998, 997)
833 self.runPrioFlows(portC, portA, portB, 996, 995)
834 self.runPrioFlows(portA, portC, portB, 994, 993)
835
836
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700837
838 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
839 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700840
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700841 if clearTable:
842 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700843
844 # Sanity check flow at lower priority from pA to pB
845 self.logger.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
846 % (portA, portB, portC, prioHigher, prioLower))
847
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700848 self.installFlow(prioHigher, portA, portC)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700849 self.installFlow(prioLower, portA, portB)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700850
851 return
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700852 self.verifyFlow(portA, portB)
853 self.removeFlow(prioLower)
854 # Sanity check flow at lower priority from pA to pC
855 self.installFlow(prioLower, portA, portC)
856 self.verifyFlow(portA, portC)
857 self.removeFlow(prioLower)
858
859 # Install and verify pA->pB @ prioLower
860 self.installFlow(prioLower, portA, portB)
861 self.verifyFlow(portA, portB)
862
863 # Install and verify pA->pC @ prioHigher, should override pA->pB
864 self.installFlow(prioHigher, portA, portC)
865 self.verifyFlow(portA, portC)
866 # remove pA->pC
867 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700868 # Old flow pA -> pB @ prioLower should still be active
869 self.verifyFlow(portA, portB)
870 self.removeFlow(prioLower)
871
872 # Table should be empty at this point, leave it alone as
873 # an assumption for future test runs
874
875
876
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700877 def installFlow(self, prio, inp, egp):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700878 request = flow_msg_create(self, self.pkt, ing_port=inp,
879 wildcards=ofp.OFPFW_DL_SRC,
880 egr_ports=egp)
881 request.priority = prio
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700882 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700883 self.flowMsgs[prio] = request
884
885 def removeFlow(self, prio):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700886 return
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700887 if self.flowMsgs.has_key(prio):
888 msg = self.flowMsgs[prio]
889 msg.command = ofp.OFPFC_DELETE_STRICT
890 # This *must* be set for DELETE
891 msg.out_port = ofp.OFPP_NONE
892 self.controller.message_send(msg)
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700893 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700894 else:
895 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700896
897
898 def verifyFlow(self, inp, egp):
899 self.logger.info("Pkt match test: " + str(inp) +
900 " to " + str(egp))
901 self.logger.debug("Send packet: " + str(inp) + " to "
902 + str(egp))
903 self.dataplane.send(inp, str(self.pkt))
904 receive_pkt_verify(self, egp, self.pkt, inp)
905
906
907
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700908class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
909
910 def runTest(self):
911
912 self._Init()
913
914 of_ports = pa_port_map.keys()
915 of_ports.sort()
916
917 # Install an entry from 0 -> 1 @ prio 1000
918 self._ClearTable()
919 self.installFlow(1000, of_ports[0], of_ports[1])
920 self.verifyFlow(of_ports[0], of_ports[1])
921 self.installFlow(1000, of_ports[1], of_ports[0])
922 self.verifyFlow(of_ports[1], of_ports[0])
923 self.installFlow(1001, of_ports[0], of_ports[1])
924 self.verifyFlow(of_ports[0], of_ports[1])
925 self.installFlow(1001, of_ports[1], of_ports[0])
926 self.verifyFlow(of_ports[1], of_ports[0])
927 self.removeFlow(1001)
928 self.verifyFlow(of_ports[0], of_ports[1])
929 self.removeFlow(1000)
930
931
932
933
Dan Talayco551befa2010-07-15 17:05:32 -0700934class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700935 """
936 Exercise wildcard matching for all ports
937
938 Generate a packet
939 Generate and install a matching flow with wildcard mask
940 Add action to forward to a port
941 Send the packet to the port
942 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700943 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700944 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700945 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -0700946 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700947 for wc in WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -0700948 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -0700949 # Set nonzero VLAN id to avoid sending priority-tagged packet
950 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -0700951 else:
952 dl_vlan = -1
953 flow_match_test(self, pa_port_map, wildcards=wc,
954 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700955
Dan Talayco551befa2010-07-15 17:05:32 -0700956class SingleWildcardMatchTagged(BaseMatchCase):
957 """
958 SingleWildcardMatch with tagged packets
959 """
960 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700961 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700962 for wc in WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700963 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -0700964 max_test=10)
965
966class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700967 """
Dan Talayco80b54ed2010-07-13 09:48:35 -0700968 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700969
970 Generate a packet
971 Generate and install a matching flow with wildcard all except one filed
972 Add action to forward to a port
973 Send the packet to the port
974 Verify the packet is received at all other ports (one port at a time)
975 Verify flow_expiration message is correct when command option is set
976 """
977 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -0700978 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -0700979 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -0700980 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -0700981 # Set nonzero VLAN id to avoid sending priority-tagged packet
982 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -0700983 else:
984 dl_vlan = -1
985 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
986 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700987
Dan Talayco551befa2010-07-15 17:05:32 -0700988class AllExceptOneWildcardMatchTagged(BaseMatchCase):
989 """
990 Match one field with tagged packets
991 """
992 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700993 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -0700994 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700995 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
996 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -0700997
998class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700999 """
1000 Create Wildcard-all flow and exercise for all ports
1001
1002 Generate a packet
1003 Generate and install a matching flow with wildcard-all
1004 Add action to forward to a port
1005 Send the packet to the port
1006 Verify the packet is received at all other ports (one port at a time)
1007 Verify flow_expiration message is correct when command option is set
1008 """
1009 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -07001010 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001011
Dan Talayco551befa2010-07-15 17:05:32 -07001012class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001013 """
Dan Talayco551befa2010-07-15 17:05:32 -07001014 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001015 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001016 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001017 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -07001018 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
1019 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001020
Dan Talaycoba3745c2010-07-21 21:51:08 -07001021
Dan Talayco551befa2010-07-15 17:05:32 -07001022class AddVLANTag(BaseMatchCase):
1023 """
1024 Add a VLAN tag to an untagged packet
1025 """
1026 def runTest(self):
1027 new_vid = 2
1028 sup_acts = supported_actions_get(self)
1029 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001030 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001031 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001032
Dan Talayco551befa2010-07-15 17:05:32 -07001033 len = 100
1034 len_w_vid = 104
1035 pkt = simple_tcp_packet(pktlen=len)
1036 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1037 dl_vlan=new_vid)
1038 vid_act = action.action_set_vlan_vid()
1039 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001040
Dan Talayco551befa2010-07-15 17:05:32 -07001041 flow_match_test(self, pa_port_map, pkt=pkt,
1042 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001043
Dan Talayco551befa2010-07-15 17:05:32 -07001044class PacketOnly(basic.DataPlaneOnly):
1045 """
1046 Just send a packet thru the switch
1047 """
1048 def runTest(self):
1049 pkt = simple_tcp_packet()
1050 of_ports = pa_port_map.keys()
1051 of_ports.sort()
1052 ing_port = of_ports[0]
1053 pa_logger.info("Sending packet to " + str(ing_port))
1054 pa_logger.debug("Data: " + str(pkt).encode('hex'))
1055 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001056
Dan Talayco551befa2010-07-15 17:05:32 -07001057class PacketOnlyTagged(basic.DataPlaneOnly):
1058 """
1059 Just send a packet thru the switch
1060 """
1061 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001062 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001063 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
1064 of_ports = pa_port_map.keys()
1065 of_ports.sort()
1066 ing_port = of_ports[0]
1067 pa_logger.info("Sending packet to " + str(ing_port))
1068 pa_logger.debug("Data: " + str(pkt).encode('hex'))
1069 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001070
Dan Talayco551befa2010-07-15 17:05:32 -07001071test_prio["PacketOnly"] = -1
1072test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001073
Dan Talayco551befa2010-07-15 17:05:32 -07001074class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001075 """
1076 Modify the VLAN ID in the VLAN tag of a tagged packet
1077 """
Dan Talayco551befa2010-07-15 17:05:32 -07001078 def runTest(self):
1079 old_vid = 2
1080 new_vid = 3
1081 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001082 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001083 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001084 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001085
Dan Talayco551befa2010-07-15 17:05:32 -07001086 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1087 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
1088 vid_act = action.action_set_vlan_vid()
1089 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001090
Dan Talayco551befa2010-07-15 17:05:32 -07001091 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1092 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001093
Howard Pershc1199d52012-04-11 14:21:32 -07001094class ModifyVlanPcp(BaseMatchCase):
1095 """
1096 Modify the priority field of the VLAN tag of a tagged packet
1097 """
1098 def runTest(self):
1099 vid = 123
1100 old_vlan_pcp = 2
1101 new_vlan_pcp = 3
1102 sup_acts = supported_actions_get(self)
1103 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1104 skip_message_emit(self, "Modify VLAN tag test")
1105 return
1106
1107 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1108 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1109 vid_act = action.action_set_vlan_pcp()
1110 vid_act.vlan_pcp = new_vlan_pcp
1111
1112 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1113 action_list=[vid_act])
1114
Dan Talayco551befa2010-07-15 17:05:32 -07001115class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001116 """
1117 Strip the VLAN tag from a tagged packet
1118 """
Dan Talayco551befa2010-07-15 17:05:32 -07001119 def runTest(self):
1120 old_vid = 2
1121 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001122 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001123 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001124 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001125
Dan Talayco551befa2010-07-15 17:05:32 -07001126 len_w_vid = 104
1127 len = 100
1128 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1129 dl_vlan=old_vid)
1130 exp_pkt = simple_tcp_packet(pktlen=len)
1131 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001132
Dan Talayco551befa2010-07-15 17:05:32 -07001133 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1134 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001135
Dan Talayco4b2bee62010-07-20 14:10:05 -07001136def init_pkt_args():
1137 """
1138 Pass back a dictionary with default packet arguments
1139 """
1140 args = {}
1141 args["dl_src"] = '00:23:45:67:89:AB'
1142
1143 dl_vlan_enable=False
1144 dl_vlan=-1
1145 if pa_config["test-params"]["vid"]:
1146 dl_vlan_enable=True
1147 dl_vlan = pa_config["test-params"]["vid"]
1148
1149# Unpack operator is ** on a dictionary
1150
1151 return args
1152
Dan Talayco551befa2010-07-15 17:05:32 -07001153class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001154 """
1155 Modify the source MAC address (TP1)
1156 """
Dan Talayco551befa2010-07-15 17:05:32 -07001157 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001158 sup_acts = supported_actions_get(self)
1159 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001160 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001161 return
1162
1163 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1164 check_test_params=True)
1165 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1166 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001167
Dan Talayco551befa2010-07-15 17:05:32 -07001168class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001169 """
1170 Modify the dest MAC address (TP1)
1171 """
Dan Talayco551befa2010-07-15 17:05:32 -07001172 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001173 sup_acts = supported_actions_get(self)
1174 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001175 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001176 return
1177
1178 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1179 check_test_params=True)
1180 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1181 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001182
Dan Talayco551befa2010-07-15 17:05:32 -07001183class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001184 """
1185 Modify the source IP address of an IP packet (TP1)
1186 """
Dan Talayco551befa2010-07-15 17:05:32 -07001187 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001188 sup_acts = supported_actions_get(self)
1189 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001190 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001191 return
1192
1193 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1194 check_test_params=True)
1195 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1196 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001197
Dan Talayco551befa2010-07-15 17:05:32 -07001198class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001199 """
1200 Modify the dest IP address of an IP packet (TP1)
1201 """
Dan Talayco551befa2010-07-15 17:05:32 -07001202 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001203 sup_acts = supported_actions_get(self)
1204 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001205 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001206 return
1207
1208 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1209 check_test_params=True)
1210 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1211 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001212
1213class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001214 """
1215 Modify the source TCP port of a TCP packet (TP1)
1216 """
Dan Talayco551befa2010-07-15 17:05:32 -07001217 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001218 sup_acts = supported_actions_get(self)
1219 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001220 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001221 return
1222
1223 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1224 check_test_params=True)
1225 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1226 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001227
1228class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001229 """
1230 Modify the dest TCP port of a TCP packet (TP1)
1231 """
Dan Talayco551befa2010-07-15 17:05:32 -07001232 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001233 sup_acts = supported_actions_get(self)
1234 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001235 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001236 return
1237
1238 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1239 check_test_params=True)
1240 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1241 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001242
1243class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001244 """
1245 Modify the IP type of service of an IP packet (TP1)
1246 """
Dan Talayco551befa2010-07-15 17:05:32 -07001247 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001248 sup_acts = supported_actions_get(self)
1249 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001250 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001251 return
Dan Talayco551befa2010-07-15 17:05:32 -07001252
Dan Talayco4b2bee62010-07-20 14:10:05 -07001253 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1254 check_test_params=True)
1255 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001256 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001257
Dan Talaycof6e76c02012-03-23 10:56:12 -07001258class ModifyL2DstMC(BaseMatchCase):
1259 """
1260 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001261 """
1262 def runTest(self):
1263 sup_acts = supported_actions_get(self)
1264 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001265 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001266 return
1267
Dan Talaycof6e76c02012-03-23 10:56:12 -07001268 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1269 check_test_params=True)
1270 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001271 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001272
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001273class ModifyL2DstIngress(BaseMatchCase):
1274 """
1275 Modify the L2 dest and send to the ingress port
1276 """
1277 def runTest(self):
1278 sup_acts = supported_actions_get(self)
1279 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001280 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001281 return
1282
1283 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1284 check_test_params=True)
1285 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1286 action_list=acts, max_test=2, egr_count=0,
1287 ing_port=True)
1288
Dan Talaycod8ae7582012-03-23 12:24:56 -07001289class ModifyL2DstIngressMC(BaseMatchCase):
1290 """
1291 Modify the L2 dest and send to the ingress port
1292 """
1293 def runTest(self):
1294 sup_acts = supported_actions_get(self)
1295 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1296 skip_message_emit(self, "ModifyL2dstMC test")
1297 return
1298
1299 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1300 check_test_params=True)
1301 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1302 action_list=acts, max_test=2, egr_count=-1,
1303 ing_port=True)
1304
Dan Talaycof6e76c02012-03-23 10:56:12 -07001305class ModifyL2SrcMC(BaseMatchCase):
1306 """
1307 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001308 """
1309 def runTest(self):
1310 sup_acts = supported_actions_get(self)
1311 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001312 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001313 return
1314
Dan Talaycof6e76c02012-03-23 10:56:12 -07001315 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1316 check_test_params=True)
1317 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001318 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001319
1320class ModifyL2SrcDstMC(BaseMatchCase):
1321 """
1322 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001323 """
1324 def runTest(self):
1325 sup_acts = supported_actions_get(self)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001326 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1327 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1328 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001329 return
1330
Dan Talaycof6e76c02012-03-23 10:56:12 -07001331 mod_fields = ['dl_dst', 'dl_src']
1332 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1333 check_test_params=True)
1334 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001335 action_list=acts, max_test=2, egr_count=-1)
1336
1337class ModifyL2DstVIDMC(BaseMatchCase):
1338 """
1339 Modify the L2 dest and send to 2 ports
1340 """
1341 def runTest(self):
1342 sup_acts = supported_actions_get(self)
1343 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1344 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1345 skip_message_emit(self, "ModifyL2DstVIDMC test")
1346 return
1347
1348 mod_fields = ['dl_dst', 'dl_vlan']
1349 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1350 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1351 check_test_params=True)
1352 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1353 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001354
Dan Talaycofa6454f2012-04-05 10:04:13 -07001355class FlowToggle(BaseMatchCase):
1356 """
1357 Add flows to the table and modify them repeatedly
1358 """
1359 def runTest(self):
Dan Talayco50be7672012-04-05 11:38:08 -07001360 flow_count = test_param_get(self.config, 'ft_flow_count', default=20)
1361 iter_count = test_param_get(self.config, 'ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001362
1363 pa_logger.info("Running flow toggle with %d flows, %d iterations" %
1364 (flow_count, iter_count))
1365 acts = []
1366 acts.append(action.action_output())
1367 acts.append(action.action_output())
1368
1369 of_ports = pa_port_map.keys()
1370 if len(of_ports) < 3:
1371 self.assertTrue(False, "Too few ports for test")
1372
1373 for idx in range(2):
1374 acts[idx].port = of_ports[idx]
1375
1376 flows = []
1377 flows.append([])
1378 flows.append([])
1379
Dan Talayco50be7672012-04-05 11:38:08 -07001380 wildcards = ofp.OFPFW_DL_SRC | ofp.OFPFW_DL_DST
Dan Talaycofa6454f2012-04-05 10:04:13 -07001381 # Create up the flows in an array
1382 for toggle in range(2):
1383 for f_idx in range(flow_count):
1384 pkt = simple_tcp_packet(tcp_sport=f_idx)
1385 msg = message.flow_mod()
1386 match = parse.packet_to_flow_match(pkt)
1387 match.in_port = of_ports[3]
Dan Talayco50be7672012-04-05 11:38:08 -07001388 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001389 msg.match = match
1390 msg.buffer_id = 0xffffffff
1391 msg.actions.add(acts[toggle])
1392 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001393
1394 # Show two sample flows
1395 pa_logger.debug(flows[0][0].show())
1396 pa_logger.debug(flows[1][0].show())
1397
Dan Talaycofa6454f2012-04-05 10:04:13 -07001398 # Install the first set of flows
1399 for f_idx in range(flow_count):
1400 rv = self.controller.message_send(flows[0][f_idx])
1401 self.assertTrue(rv != -1, "Error installing flow %d" % f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001402 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycofa6454f2012-04-05 10:04:13 -07001403
1404 pa_logger.info("Installed %d flows" % flow_count)
1405
1406 # Repeatedly modify all the flows back and forth
1407 updates = 0
1408 # Report status about 5 times
1409 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001410 start = time.time()
1411 for iter_idx in range(iter_count):
1412 if not iter_idx % mod_val:
1413 pa_logger.info("Flow Toggle: iter %d of %d. " %
1414 (iter_idx, iter_count) +
1415 "%d updates in %d secs" %
1416 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001417 for toggle in range(2):
1418 t_idx = 1 - toggle
1419 for f_idx in range(flow_count):
1420 rv = self.controller.message_send(flows[t_idx][f_idx])
1421 updates += 1
1422 self.assertTrue(rv != -1, "Error modifying flow %d" %
1423 f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001424 self.assertEqual(do_barrier(self.controller), 0,
1425 "Barrier failed")
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001426
1427 end = time.time()
1428 divisor = end - start or (end - start + 1)
1429 pa_logger.info("Flow toggle: %d iterations" % iter_count)
1430 pa_logger.info(" %d flow mods in %d secs, %d mods/sec" %
1431 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001432
1433
Dan Talayco8a64e332012-03-28 14:53:20 -07001434# You can pick and choose these by commenting tests in or out
1435iter_classes = [
1436 basic.PacketIn,
1437 basic.PacketOut,
1438 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001439 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001440 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001441 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001442 AllWildcardMatch,
1443 AllWildcardMatchTagged,
1444 SingleWildcardMatch,
1445 SingleWildcardMatchTagged,
1446 ExactMatch,
1447 ExactMatchTagged,
1448 SingleWildcardMatch,
1449 ModifyL2Src,
1450 ModifyL2Dst,
1451 ModifyL2SrcMC,
1452 ModifyL2DstMC,
1453 ModifyL2SrcDstMC
1454 ]
1455
1456class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001457 """
1458 Iterate over a bunch of test cases
1459
1460 The cases come from the list above
1461 """
1462
Dan Talayco8a64e332012-03-28 14:53:20 -07001463 def runTest(self):
1464 count = test_param_get(self.config, 'iter_count', default=10)
1465 tests_done = 0
1466 pa_logger.info("Running iteration test " + str(count) + " times")
1467 start = time.time()
1468 last = start
1469 for idx in range(count):
1470 pa_logger.info("Iteration " + str(idx + 1))
1471 for cls in iter_classes:
1472 test = cls()
1473 test.inheritSetup(self)
1474 test.runTest()
1475 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001476 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001477 if time.time() - last > 60:
1478 last = time.time()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001479 pa_logger.info(
1480 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1481 (idx, count, tests_done, last - start) +
1482 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001483 stats = all_stats_get(self)
1484 last = time.time()
1485 pa_logger.info("\nIterCases ran %d tests in %d seconds." %
1486 (tests_done, last - start))
1487 pa_logger.info(" flows: %d. packets: %d. bytes: %d" %
1488 (stats["flows"], stats["packets"], stats["bytes"]))
1489 pa_logger.info(" active: %d. lookups: %d. matched %d." %
1490 (stats["active"], stats["lookups"], stats["matched"]))
1491
1492# Don't run by default
1493test_prio["IterCases"] = -1
Dan Talaycof6e76c02012-03-23 10:56:12 -07001494
Dan Talayco4b2bee62010-07-20 14:10:05 -07001495#@todo Need to implement tagged versions of the above tests
1496#
1497#@todo Implement a test case that strips tag 2, adds tag 3
1498# and modifies tag 4 to tag 5. Then verify (in addition) that
1499# tag 6 does not get modified.
1500
1501class MixedVLAN(BaseMatchCase):
1502 """
1503 Test mixture of VLAN tag actions
1504
1505 Strip tag 2 on port 1, send to port 2
1506 Add tag 3 on port 1, send to port 2
1507 Modify tag 4 to 5 on port 1, send to port 2
1508 All other traffic from port 1, send to port 3
1509 All traffic from port 2 sent to port 4
1510 Use exact matches with different packets for all mods
1511 Verify the following: (port, vid)
1512 (port 1, vid 2) => VLAN tag stripped, out port 2
1513 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1514 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1515 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1516 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1517 (port 2, no tag) => untagged packet out port 4
1518 (port 2, vid 2-6) => unmodified packet out port 4
1519
1520 Variation: Might try sending VID 5 to port 3 and check.
1521 If only VID 5 distinguishes pkt, this will fail on some platforms
1522 """
1523
1524test_prio["MixedVLAN"] = -1
1525
Dan Talayco551befa2010-07-15 17:05:32 -07001526def supported_actions_get(parent, use_cache=True):
1527 """
1528 Get the bitmap of supported actions from the switch
1529 If use_cache is false, the cached value will be updated
1530 """
1531 global cached_supported_actions
1532 if cached_supported_actions is None or not use_cache:
1533 request = message.features_request()
1534 (reply, pkt) = parent.controller.transact(request, timeout=2)
1535 parent.assertTrue(reply is not None, "Did not get response to ftr req")
1536 cached_supported_actions = reply.actions
1537 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
1538
1539 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -07001540
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001541if __name__ == "__main__":
1542 print "Please run through oft script: ./oft --test_spec=basic"