blob: b138d3c6eb8cf263275ab5e6625e095dc4e33999 [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 Townsend8364b162012-04-12 13:45:40 -0700877 def installFlow(self, prio, inp, egp,
878 wildcards=ofp.OFPFW_DL_SRC):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700879 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700880 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700881 egr_ports=egp)
882 request.priority = prio
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700883 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700884 self.flowMsgs[prio] = request
885
886 def removeFlow(self, prio):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700887 return
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700888 if self.flowMsgs.has_key(prio):
889 msg = self.flowMsgs[prio]
890 msg.command = ofp.OFPFC_DELETE_STRICT
891 # This *must* be set for DELETE
892 msg.out_port = ofp.OFPP_NONE
893 self.controller.message_send(msg)
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700894 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700895 else:
896 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700897
898
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700899 def verifyFlow(self, inp, egp, pkt=None):
900 if pkt == None:
901 pkt = self.pkt
902
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700903 self.logger.info("Pkt match test: " + str(inp) +
904 " to " + str(egp))
905 self.logger.debug("Send packet: " + str(inp) + " to "
906 + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700907 self.dataplane.send(inp, str(pkt))
908 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700909
910
911
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700912class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
913
914 def runTest(self):
915
916 self._Init()
917
918 of_ports = pa_port_map.keys()
919 of_ports.sort()
920
921 # Install an entry from 0 -> 1 @ prio 1000
922 self._ClearTable()
923 self.installFlow(1000, of_ports[0], of_ports[1])
924 self.verifyFlow(of_ports[0], of_ports[1])
925 self.installFlow(1000, of_ports[1], of_ports[0])
926 self.verifyFlow(of_ports[1], of_ports[0])
927 self.installFlow(1001, of_ports[0], of_ports[1])
928 self.verifyFlow(of_ports[0], of_ports[1])
929 self.installFlow(1001, of_ports[1], of_ports[0])
930 self.verifyFlow(of_ports[1], of_ports[0])
931 self.removeFlow(1001)
932 self.verifyFlow(of_ports[0], of_ports[1])
933 self.removeFlow(1000)
934
935
936
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700937class WildcardPriority(SingleWildcardMatchPriority):
938
939 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700940
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700941 self._Init()
942
943 of_ports = pa_port_map.keys()
944 of_ports.sort()
945
946 self._ClearTable()
947 # Install a flow with no wildcards for our packet:
948 self.installFlow(1000, of_ports[0], of_ports[1], wildcards=0)
949 self.verifyFlow(of_ports[0], of_ports[1])
950 # Install a flow with wildcards for our packet with higher
951 # priority.
952 self.installFlow(1001, of_ports[0], of_ports[2])
953 self.verifyFlow(of_ports[0], of_ports[2])
954
955
956
Dan Talayco551befa2010-07-15 17:05:32 -0700957class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700958 """
959 Exercise wildcard matching for all ports
960
961 Generate a packet
962 Generate and install a matching flow with wildcard mask
963 Add action to forward to a port
964 Send the packet to the port
965 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700966 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700967 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700968 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -0700969 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700970 for wc in WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -0700971 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -0700972 # Set nonzero VLAN id to avoid sending priority-tagged packet
973 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -0700974 else:
975 dl_vlan = -1
976 flow_match_test(self, pa_port_map, wildcards=wc,
977 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700978
Dan Talayco551befa2010-07-15 17:05:32 -0700979class SingleWildcardMatchTagged(BaseMatchCase):
980 """
981 SingleWildcardMatch with tagged packets
982 """
983 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700984 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700985 for wc in WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700986 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -0700987 max_test=10)
988
989class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700990 """
Dan Talayco80b54ed2010-07-13 09:48:35 -0700991 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700992
993 Generate a packet
994 Generate and install a matching flow with wildcard all except one filed
995 Add action to forward to a port
996 Send the packet to the port
997 Verify the packet is received at all other ports (one port at a time)
998 Verify flow_expiration message is correct when command option is set
999 """
1000 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -07001001 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001002 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -07001003 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001004 # Set nonzero VLAN id to avoid sending priority-tagged packet
1005 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001006 else:
1007 dl_vlan = -1
1008 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
1009 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001010
Dan Talayco551befa2010-07-15 17:05:32 -07001011class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1012 """
1013 Match one field with tagged packets
1014 """
1015 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001016 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001017 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -07001018 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
1019 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001020
1021class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001022 """
1023 Create Wildcard-all flow and exercise for all ports
1024
1025 Generate a packet
1026 Generate and install a matching flow with wildcard-all
1027 Add action to forward to a port
1028 Send the packet to the port
1029 Verify the packet is received at all other ports (one port at a time)
1030 Verify flow_expiration message is correct when command option is set
1031 """
1032 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -07001033 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001034
Dan Talayco551befa2010-07-15 17:05:32 -07001035class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001036 """
Dan Talayco551befa2010-07-15 17:05:32 -07001037 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001038 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001039 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001040 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -07001041 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
1042 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001043
Dan Talaycoba3745c2010-07-21 21:51:08 -07001044
Dan Talayco551befa2010-07-15 17:05:32 -07001045class AddVLANTag(BaseMatchCase):
1046 """
1047 Add a VLAN tag to an untagged packet
1048 """
1049 def runTest(self):
1050 new_vid = 2
1051 sup_acts = supported_actions_get(self)
1052 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001053 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001054 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001055
Dan Talayco551befa2010-07-15 17:05:32 -07001056 len = 100
1057 len_w_vid = 104
1058 pkt = simple_tcp_packet(pktlen=len)
1059 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1060 dl_vlan=new_vid)
1061 vid_act = action.action_set_vlan_vid()
1062 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001063
Dan Talayco551befa2010-07-15 17:05:32 -07001064 flow_match_test(self, pa_port_map, pkt=pkt,
1065 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001066
Dan Talayco551befa2010-07-15 17:05:32 -07001067class PacketOnly(basic.DataPlaneOnly):
1068 """
1069 Just send a packet thru the switch
1070 """
1071 def runTest(self):
1072 pkt = simple_tcp_packet()
1073 of_ports = pa_port_map.keys()
1074 of_ports.sort()
1075 ing_port = of_ports[0]
1076 pa_logger.info("Sending packet to " + str(ing_port))
1077 pa_logger.debug("Data: " + str(pkt).encode('hex'))
1078 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001079
Dan Talayco551befa2010-07-15 17:05:32 -07001080class PacketOnlyTagged(basic.DataPlaneOnly):
1081 """
1082 Just send a packet thru the switch
1083 """
1084 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001085 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001086 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
1087 of_ports = pa_port_map.keys()
1088 of_ports.sort()
1089 ing_port = of_ports[0]
1090 pa_logger.info("Sending packet to " + str(ing_port))
1091 pa_logger.debug("Data: " + str(pkt).encode('hex'))
1092 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001093
Dan Talayco551befa2010-07-15 17:05:32 -07001094test_prio["PacketOnly"] = -1
1095test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001096
Dan Talayco551befa2010-07-15 17:05:32 -07001097class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001098 """
1099 Modify the VLAN ID in the VLAN tag of a tagged packet
1100 """
Dan Talayco551befa2010-07-15 17:05:32 -07001101 def runTest(self):
1102 old_vid = 2
1103 new_vid = 3
1104 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001105 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001106 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001107 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001108
Dan Talayco551befa2010-07-15 17:05:32 -07001109 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1110 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
1111 vid_act = action.action_set_vlan_vid()
1112 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001113
Dan Talayco551befa2010-07-15 17:05:32 -07001114 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1115 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001116
Ken Chiange9a211d2012-04-20 14:52:11 -07001117class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1118 """
1119 With vlan ID and priority wildcarded, perform SET_VLAN_VID action.
1120 The same flow should match on both untagged and tagged packets.
1121 """
1122 def runTest(self):
1123 old_vid = 2
1124 new_vid = 3
1125 sup_acts = supported_actions_get(self)
1126 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1127 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1128 return
1129
1130 of_ports = pa_port_map.keys()
1131 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1132 ing_port = of_ports[0]
1133 egr_ports = of_ports[1]
1134
1135 rv = delete_all_flows(self.controller, pa_logger)
1136 self.assertEqual(rv, 0, "Failed to delete all flows")
1137
1138 len_untagged = 100
1139 len_w_vid = 104
1140 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1141 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
1142 dl_vlan_enable=True, dl_vlan=old_vid)
1143 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1144 dl_vlan=new_vid)
1145 wildcards=ofp.OFPFW_DL_VLAN|ofp.OFPFW_DL_VLAN_PCP
1146 vid_act = action.action_set_vlan_vid()
1147 vid_act.vlan_vid = new_vid
1148 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
1149 wildcards=wildcards, egr_ports=egr_ports,
1150 action_list=[vid_act])
1151 flow_msg_install(self, request)
1152
1153 pa_logger.debug("Send untagged packet: " + str(ing_port) + " to " +
1154 str(egr_ports))
1155 self.dataplane.send(ing_port, str(untagged_pkt))
1156 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1157
1158 pa_logger.debug("Send tagged packet: " + str(ing_port) + " to " +
1159 str(egr_ports))
1160 self.dataplane.send(ing_port, str(tagged_pkt))
1161 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1162
Howard Pershc1199d52012-04-11 14:21:32 -07001163class ModifyVlanPcp(BaseMatchCase):
1164 """
1165 Modify the priority field of the VLAN tag of a tagged packet
1166 """
1167 def runTest(self):
1168 vid = 123
1169 old_vlan_pcp = 2
1170 new_vlan_pcp = 3
1171 sup_acts = supported_actions_get(self)
1172 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1173 skip_message_emit(self, "Modify VLAN tag test")
1174 return
1175
1176 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1177 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1178 vid_act = action.action_set_vlan_pcp()
1179 vid_act.vlan_pcp = new_vlan_pcp
1180
1181 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1182 action_list=[vid_act])
1183
Dan Talayco551befa2010-07-15 17:05:32 -07001184class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001185 """
1186 Strip the VLAN tag from a tagged packet
1187 """
Dan Talayco551befa2010-07-15 17:05:32 -07001188 def runTest(self):
1189 old_vid = 2
1190 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001191 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001192 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001193 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001194
Dan Talayco551befa2010-07-15 17:05:32 -07001195 len_w_vid = 104
1196 len = 100
1197 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1198 dl_vlan=old_vid)
1199 exp_pkt = simple_tcp_packet(pktlen=len)
1200 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001201
Dan Talayco551befa2010-07-15 17:05:32 -07001202 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1203 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001204
Ken Chiange9a211d2012-04-20 14:52:11 -07001205class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1206 """
1207 Strip the VLAN tag from a tagged packet.
1208 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1209 """
1210 def runTest(self):
1211 old_vid = 2
1212 sup_acts = supported_actions_get(self)
1213 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1214 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1215 return
1216
1217 len_w_vid = 104
1218 len_untagged = 100
1219 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1220 dl_vlan=old_vid)
1221 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
1222 vid_act = action.action_strip_vlan()
1223
1224 flow_match_test(self, pa_port_map,
1225 wildcards=ofp.OFPFW_DL_VLAN|ofp.OFPFW_DL_VLAN_PCP,
1226 pkt=pkt, exp_pkt=exp_pkt,
1227 action_list=[vid_act])
1228
Dan Talayco4b2bee62010-07-20 14:10:05 -07001229def init_pkt_args():
1230 """
1231 Pass back a dictionary with default packet arguments
1232 """
1233 args = {}
1234 args["dl_src"] = '00:23:45:67:89:AB'
1235
1236 dl_vlan_enable=False
1237 dl_vlan=-1
1238 if pa_config["test-params"]["vid"]:
1239 dl_vlan_enable=True
1240 dl_vlan = pa_config["test-params"]["vid"]
1241
1242# Unpack operator is ** on a dictionary
1243
1244 return args
1245
Dan Talayco551befa2010-07-15 17:05:32 -07001246class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001247 """
1248 Modify the source MAC address (TP1)
1249 """
Dan Talayco551befa2010-07-15 17:05:32 -07001250 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001251 sup_acts = supported_actions_get(self)
1252 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001253 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001254 return
1255
1256 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1257 check_test_params=True)
1258 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1259 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001260
Dan Talayco551befa2010-07-15 17:05:32 -07001261class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001262 """
1263 Modify the dest MAC address (TP1)
1264 """
Dan Talayco551befa2010-07-15 17:05:32 -07001265 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001266 sup_acts = supported_actions_get(self)
1267 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001268 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001269 return
1270
1271 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1272 check_test_params=True)
1273 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1274 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001275
Dan Talayco551befa2010-07-15 17:05:32 -07001276class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001277 """
1278 Modify the source IP address of an IP packet (TP1)
1279 """
Dan Talayco551befa2010-07-15 17:05:32 -07001280 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001281 sup_acts = supported_actions_get(self)
1282 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001283 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001284 return
1285
1286 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1287 check_test_params=True)
1288 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1289 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001290
Dan Talayco551befa2010-07-15 17:05:32 -07001291class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001292 """
1293 Modify the dest IP address of an IP packet (TP1)
1294 """
Dan Talayco551befa2010-07-15 17:05:32 -07001295 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001296 sup_acts = supported_actions_get(self)
1297 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001298 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001299 return
1300
1301 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1302 check_test_params=True)
1303 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1304 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001305
1306class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001307 """
1308 Modify the source TCP port of a TCP packet (TP1)
1309 """
Dan Talayco551befa2010-07-15 17:05:32 -07001310 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001311 sup_acts = supported_actions_get(self)
1312 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001313 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001314 return
1315
1316 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1317 check_test_params=True)
1318 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1319 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001320
1321class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001322 """
1323 Modify the dest TCP port of a TCP packet (TP1)
1324 """
Dan Talayco551befa2010-07-15 17:05:32 -07001325 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001326 sup_acts = supported_actions_get(self)
1327 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001328 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001329 return
1330
1331 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1332 check_test_params=True)
1333 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1334 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001335
1336class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001337 """
1338 Modify the IP type of service of an IP packet (TP1)
1339 """
Dan Talayco551befa2010-07-15 17:05:32 -07001340 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001341 sup_acts = supported_actions_get(self)
1342 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001343 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001344 return
Dan Talayco551befa2010-07-15 17:05:32 -07001345
Dan Talayco4b2bee62010-07-20 14:10:05 -07001346 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1347 check_test_params=True)
1348 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001349 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001350
Dan Talaycof6e76c02012-03-23 10:56:12 -07001351class ModifyL2DstMC(BaseMatchCase):
1352 """
1353 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001354 """
1355 def runTest(self):
1356 sup_acts = supported_actions_get(self)
1357 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001358 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001359 return
1360
Dan Talaycof6e76c02012-03-23 10:56:12 -07001361 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1362 check_test_params=True)
1363 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001364 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001365
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001366class ModifyL2DstIngress(BaseMatchCase):
1367 """
1368 Modify the L2 dest and send to the ingress port
1369 """
1370 def runTest(self):
1371 sup_acts = supported_actions_get(self)
1372 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001373 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001374 return
1375
1376 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1377 check_test_params=True)
1378 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1379 action_list=acts, max_test=2, egr_count=0,
1380 ing_port=True)
1381
Dan Talaycod8ae7582012-03-23 12:24:56 -07001382class ModifyL2DstIngressMC(BaseMatchCase):
1383 """
1384 Modify the L2 dest and send to the ingress port
1385 """
1386 def runTest(self):
1387 sup_acts = supported_actions_get(self)
1388 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1389 skip_message_emit(self, "ModifyL2dstMC test")
1390 return
1391
1392 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1393 check_test_params=True)
1394 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1395 action_list=acts, max_test=2, egr_count=-1,
1396 ing_port=True)
1397
Dan Talaycof6e76c02012-03-23 10:56:12 -07001398class ModifyL2SrcMC(BaseMatchCase):
1399 """
1400 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001401 """
1402 def runTest(self):
1403 sup_acts = supported_actions_get(self)
1404 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001405 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001406 return
1407
Dan Talaycof6e76c02012-03-23 10:56:12 -07001408 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1409 check_test_params=True)
1410 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001411 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001412
1413class ModifyL2SrcDstMC(BaseMatchCase):
1414 """
1415 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001416 """
1417 def runTest(self):
1418 sup_acts = supported_actions_get(self)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001419 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1420 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1421 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001422 return
1423
Dan Talaycof6e76c02012-03-23 10:56:12 -07001424 mod_fields = ['dl_dst', 'dl_src']
1425 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1426 check_test_params=True)
1427 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001428 action_list=acts, max_test=2, egr_count=-1)
1429
1430class ModifyL2DstVIDMC(BaseMatchCase):
1431 """
1432 Modify the L2 dest and send to 2 ports
1433 """
1434 def runTest(self):
1435 sup_acts = supported_actions_get(self)
1436 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1437 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1438 skip_message_emit(self, "ModifyL2DstVIDMC test")
1439 return
1440
1441 mod_fields = ['dl_dst', 'dl_vlan']
1442 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1443 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1444 check_test_params=True)
1445 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1446 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001447
Dan Talaycofa6454f2012-04-05 10:04:13 -07001448class FlowToggle(BaseMatchCase):
1449 """
1450 Add flows to the table and modify them repeatedly
1451 """
1452 def runTest(self):
Dan Talayco50be7672012-04-05 11:38:08 -07001453 flow_count = test_param_get(self.config, 'ft_flow_count', default=20)
1454 iter_count = test_param_get(self.config, 'ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001455
1456 pa_logger.info("Running flow toggle with %d flows, %d iterations" %
1457 (flow_count, iter_count))
1458 acts = []
1459 acts.append(action.action_output())
1460 acts.append(action.action_output())
1461
1462 of_ports = pa_port_map.keys()
1463 if len(of_ports) < 3:
1464 self.assertTrue(False, "Too few ports for test")
1465
1466 for idx in range(2):
1467 acts[idx].port = of_ports[idx]
1468
1469 flows = []
1470 flows.append([])
1471 flows.append([])
1472
Dan Talayco50be7672012-04-05 11:38:08 -07001473 wildcards = ofp.OFPFW_DL_SRC | ofp.OFPFW_DL_DST
Dan Talaycofa6454f2012-04-05 10:04:13 -07001474 # Create up the flows in an array
1475 for toggle in range(2):
1476 for f_idx in range(flow_count):
1477 pkt = simple_tcp_packet(tcp_sport=f_idx)
1478 msg = message.flow_mod()
1479 match = parse.packet_to_flow_match(pkt)
1480 match.in_port = of_ports[3]
Dan Talayco50be7672012-04-05 11:38:08 -07001481 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001482 msg.match = match
1483 msg.buffer_id = 0xffffffff
1484 msg.actions.add(acts[toggle])
1485 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001486
1487 # Show two sample flows
1488 pa_logger.debug(flows[0][0].show())
1489 pa_logger.debug(flows[1][0].show())
1490
Dan Talaycofa6454f2012-04-05 10:04:13 -07001491 # Install the first set of flows
1492 for f_idx in range(flow_count):
1493 rv = self.controller.message_send(flows[0][f_idx])
1494 self.assertTrue(rv != -1, "Error installing flow %d" % f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001495 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycofa6454f2012-04-05 10:04:13 -07001496
1497 pa_logger.info("Installed %d flows" % flow_count)
1498
1499 # Repeatedly modify all the flows back and forth
1500 updates = 0
1501 # Report status about 5 times
1502 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001503 start = time.time()
1504 for iter_idx in range(iter_count):
1505 if not iter_idx % mod_val:
1506 pa_logger.info("Flow Toggle: iter %d of %d. " %
1507 (iter_idx, iter_count) +
1508 "%d updates in %d secs" %
1509 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001510 for toggle in range(2):
1511 t_idx = 1 - toggle
1512 for f_idx in range(flow_count):
1513 rv = self.controller.message_send(flows[t_idx][f_idx])
1514 updates += 1
1515 self.assertTrue(rv != -1, "Error modifying flow %d" %
1516 f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001517 self.assertEqual(do_barrier(self.controller), 0,
1518 "Barrier failed")
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001519
1520 end = time.time()
1521 divisor = end - start or (end - start + 1)
1522 pa_logger.info("Flow toggle: %d iterations" % iter_count)
1523 pa_logger.info(" %d flow mods in %d secs, %d mods/sec" %
1524 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001525
1526
Dan Talayco8a64e332012-03-28 14:53:20 -07001527# You can pick and choose these by commenting tests in or out
1528iter_classes = [
1529 basic.PacketIn,
1530 basic.PacketOut,
1531 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001532 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001533 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001534 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001535 AllWildcardMatch,
1536 AllWildcardMatchTagged,
1537 SingleWildcardMatch,
1538 SingleWildcardMatchTagged,
1539 ExactMatch,
1540 ExactMatchTagged,
1541 SingleWildcardMatch,
1542 ModifyL2Src,
1543 ModifyL2Dst,
1544 ModifyL2SrcMC,
1545 ModifyL2DstMC,
1546 ModifyL2SrcDstMC
1547 ]
1548
1549class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001550 """
1551 Iterate over a bunch of test cases
1552
1553 The cases come from the list above
1554 """
1555
Dan Talayco8a64e332012-03-28 14:53:20 -07001556 def runTest(self):
1557 count = test_param_get(self.config, 'iter_count', default=10)
1558 tests_done = 0
1559 pa_logger.info("Running iteration test " + str(count) + " times")
1560 start = time.time()
1561 last = start
1562 for idx in range(count):
1563 pa_logger.info("Iteration " + str(idx + 1))
1564 for cls in iter_classes:
1565 test = cls()
1566 test.inheritSetup(self)
1567 test.runTest()
1568 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001569 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001570 if time.time() - last > 60:
1571 last = time.time()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001572 pa_logger.info(
1573 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1574 (idx, count, tests_done, last - start) +
1575 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001576 stats = all_stats_get(self)
1577 last = time.time()
1578 pa_logger.info("\nIterCases ran %d tests in %d seconds." %
1579 (tests_done, last - start))
1580 pa_logger.info(" flows: %d. packets: %d. bytes: %d" %
1581 (stats["flows"], stats["packets"], stats["bytes"]))
1582 pa_logger.info(" active: %d. lookups: %d. matched %d." %
1583 (stats["active"], stats["lookups"], stats["matched"]))
1584
1585# Don't run by default
1586test_prio["IterCases"] = -1
Dan Talaycof6e76c02012-03-23 10:56:12 -07001587
Dan Talayco4b2bee62010-07-20 14:10:05 -07001588#@todo Need to implement tagged versions of the above tests
1589#
1590#@todo Implement a test case that strips tag 2, adds tag 3
1591# and modifies tag 4 to tag 5. Then verify (in addition) that
1592# tag 6 does not get modified.
1593
1594class MixedVLAN(BaseMatchCase):
1595 """
1596 Test mixture of VLAN tag actions
1597
1598 Strip tag 2 on port 1, send to port 2
1599 Add tag 3 on port 1, send to port 2
1600 Modify tag 4 to 5 on port 1, send to port 2
1601 All other traffic from port 1, send to port 3
1602 All traffic from port 2 sent to port 4
1603 Use exact matches with different packets for all mods
1604 Verify the following: (port, vid)
1605 (port 1, vid 2) => VLAN tag stripped, out port 2
1606 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1607 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1608 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1609 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1610 (port 2, no tag) => untagged packet out port 4
1611 (port 2, vid 2-6) => unmodified packet out port 4
1612
1613 Variation: Might try sending VID 5 to port 3 and check.
1614 If only VID 5 distinguishes pkt, this will fail on some platforms
1615 """
1616
1617test_prio["MixedVLAN"] = -1
1618
Dan Talayco551befa2010-07-15 17:05:32 -07001619def supported_actions_get(parent, use_cache=True):
1620 """
1621 Get the bitmap of supported actions from the switch
1622 If use_cache is false, the cached value will be updated
1623 """
1624 global cached_supported_actions
1625 if cached_supported_actions is None or not use_cache:
1626 request = message.features_request()
1627 (reply, pkt) = parent.controller.transact(request, timeout=2)
1628 parent.assertTrue(reply is not None, "Did not get response to ftr req")
1629 cached_supported_actions = reply.actions
1630 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
1631
1632 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -07001633
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001634if __name__ == "__main__":
1635 print "Please run through oft script: ./oft --test_spec=basic"