blob: eaba6249c395c64ef5cb3e20f31868ef31dbedff [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
Ed Swierk065a2db2012-04-17 16:35:52 -0700226 (queue_stats, p) = self.controller.transact(request, timeout=2)
Howard Persh670b5672012-04-13 09:08:29 -0700227 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
Ed Swierk065a2db2012-04-17 16:35:52 -0700264 (qs_before, p) = self.controller.transact(request, timeout=2)
Howard Persh670b5672012-04-13 09:08:29 -0700265 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
Ed Swierkb8a86512012-04-18 18:45:58 -0700287 # FIXME: instead of sleeping, keep requesting queue stats until
288 # the expected queue counter increases or some large timeout is
289 # reached
290 time.sleep(2)
291
Howard Persh670b5672012-04-13 09:08:29 -0700292 # Get current stats for selected egress queue again
293
294 request = message.queue_stats_request()
295 request.port_no = egress_port
296 request.queue_id = egress_queue_id
Ed Swierk065a2db2012-04-17 16:35:52 -0700297 (qs_after, p) = self.controller.transact(request, timeout=2)
Howard Persh670b5672012-04-13 09:08:29 -0700298 self.assertNotEqual(qs_after, None, "Queue stats request failed")
299
300 # Make sure that tx packet counter for selected egress queue was
301 # incremented
302
Ed Swierk22f59152012-04-17 16:36:47 -0700303 self.assertEqual(qs_after.stats[0].tx_packets, \
304 qs_before.stats[0].tx_packets + 1, \
Howard Persh670b5672012-04-13 09:08:29 -0700305 "Verification of egress queue tx packet count failed"
306 )
307
308
Howard Pershf97840f2012-04-10 16:30:42 -0700309
310
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700311class DirectPacketICMP(DirectPacket):
312 """
313 Send ICMP packet to single egress port
314
315 Generate a ICMP packet
316 Generate and install a matching flow
317 Add action to direct the packet to an egress port
318 Send the packet to ingress dataplane port
319 Verify the packet is received at the egress port only
320 Difference from DirectPacket test is that sent packet is ICMP
321 """
322 def runTest(self):
323 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700324
325class DirectTwoPorts(basic.SimpleDataPlane):
326 """
327 Send packet to two egress ports
328
329 Generate a packet
330 Generate and install a matching flow
331 Add action to direct the packet to two egress ports
332 Send the packet to ingress dataplane port
333 Verify the packet is received at the two egress ports
334 """
335 def runTest(self):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700336 of_ports = pa_port_map.keys()
337 of_ports.sort()
338 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
339
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700340 pkt = simple_tcp_packet()
341 match = parse.packet_to_flow_match(pkt)
342 match.wildcards &= ~ofp.OFPFW_IN_PORT
343 self.assertTrue(match is not None,
344 "Could not generate flow match from pkt")
345 act = action.action_output()
346
347 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700348 rv = delete_all_flows(self.controller, pa_logger)
349 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700350
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700351 ingress_port = of_ports[idx]
352 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
353 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
354 pa_logger.info("Ingress " + str(ingress_port) +
355 " to egress " + str(egress_port1) + " and " +
356 str(egress_port2))
357
358 match.in_port = ingress_port
359
360 request = message.flow_mod()
361 request.match = match
362 request.buffer_id = 0xffffffff
363 act.port = egress_port1
364 self.assertTrue(request.actions.add(act), "Could not add action1")
365 act.port = egress_port2
366 self.assertTrue(request.actions.add(act), "Could not add action2")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700367 # pa_logger.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700368
369 pa_logger.info("Inserting flow")
370 rv = self.controller.message_send(request)
371 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700372 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700373
374 pa_logger.info("Sending packet to dp port " +
375 str(ingress_port))
376 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700377 yes_ports = set([egress_port1, egress_port2])
378 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700379
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700380 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700381 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700382
383class DirectMCNonIngress(basic.SimpleDataPlane):
384 """
385 Multicast to all non-ingress ports
386
387 Generate a packet
388 Generate and install a matching flow
389 Add action to direct the packet to all non-ingress ports
390 Send the packet to ingress dataplane port
391 Verify the packet is received at all non-ingress ports
392
393 Does not use the flood action
394 """
395 def runTest(self):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700396 of_ports = pa_port_map.keys()
397 of_ports.sort()
398 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
399
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700400 pkt = simple_tcp_packet()
401 match = parse.packet_to_flow_match(pkt)
402 match.wildcards &= ~ofp.OFPFW_IN_PORT
403 self.assertTrue(match is not None,
404 "Could not generate flow match from pkt")
405 act = action.action_output()
406
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700407 for ingress_port in of_ports:
408 rv = delete_all_flows(self.controller, pa_logger)
409 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700410
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700411 pa_logger.info("Ingress " + str(ingress_port) +
412 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700413 match.in_port = ingress_port
414
415 request = message.flow_mod()
416 request.match = match
417 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700418 for egress_port in of_ports:
419 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700420 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700421 act.port = egress_port
422 self.assertTrue(request.actions.add(act),
423 "Could not add output to " + str(egress_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700424 pa_logger.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700425
426 pa_logger.info("Inserting flow")
427 rv = self.controller.message_send(request)
428 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700429 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700430
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700431 pa_logger.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700432 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700433 yes_ports = set(of_ports).difference([ingress_port])
434 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700435 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700436
Dan Talayco32fa6542010-05-11 15:54:08 -0700437
438class DirectMC(basic.SimpleDataPlane):
439 """
440 Multicast to all ports including ingress
441
442 Generate a packet
443 Generate and install a matching flow
444 Add action to direct the packet to all non-ingress ports
445 Send the packet to ingress dataplane port
446 Verify the packet is received at all ports
447
448 Does not use the flood action
449 """
450 def runTest(self):
Dan Talayco32fa6542010-05-11 15:54:08 -0700451 of_ports = pa_port_map.keys()
452 of_ports.sort()
453 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
454
Dan Talayco32fa6542010-05-11 15:54:08 -0700455 pkt = simple_tcp_packet()
456 match = parse.packet_to_flow_match(pkt)
457 match.wildcards &= ~ofp.OFPFW_IN_PORT
458 self.assertTrue(match is not None,
459 "Could not generate flow match from pkt")
460 act = action.action_output()
461
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700462 for ingress_port in of_ports:
463 rv = delete_all_flows(self.controller, pa_logger)
464 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700465
Dan Talayco32fa6542010-05-11 15:54:08 -0700466 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700467 match.in_port = ingress_port
468
469 request = message.flow_mod()
470 request.match = match
471 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700472 for egress_port in of_ports:
473 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700474 act.port = ofp.OFPP_IN_PORT
475 else:
476 act.port = egress_port
477 self.assertTrue(request.actions.add(act),
478 "Could not add output to " + str(egress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700479 # pa_logger.info(request.show())
480
481 pa_logger.info("Inserting flow")
482 rv = self.controller.message_send(request)
483 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700484 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2e77a842010-05-12 15:39:46 -0700485
486 pa_logger.info("Sending packet to dp port " + str(ingress_port))
487 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700488 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700489 pa_logger, pa_config)
Dan Talayco2e77a842010-05-12 15:39:46 -0700490
491class Flood(basic.SimpleDataPlane):
492 """
493 Flood to all ports except ingress
494
495 Generate a packet
496 Generate and install a matching flow
497 Add action to flood the packet
498 Send the packet to ingress dataplane port
499 Verify the packet is received at all other ports
500 """
501 def runTest(self):
Dan Talayco2e77a842010-05-12 15:39:46 -0700502 of_ports = pa_port_map.keys()
503 of_ports.sort()
504 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
505
506 pkt = simple_tcp_packet()
507 match = parse.packet_to_flow_match(pkt)
508 match.wildcards &= ~ofp.OFPFW_IN_PORT
509 self.assertTrue(match is not None,
510 "Could not generate flow match from pkt")
511 act = action.action_output()
512
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700513 for ingress_port in of_ports:
514 rv = delete_all_flows(self.controller, pa_logger)
515 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700516
Dan Talayco2e77a842010-05-12 15:39:46 -0700517 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700518 match.in_port = ingress_port
519
520 request = message.flow_mod()
521 request.match = match
522 request.buffer_id = 0xffffffff
523 act.port = ofp.OFPP_FLOOD
524 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700525 "Could not add flood port action")
Dan Talayco32fa6542010-05-11 15:54:08 -0700526 pa_logger.info(request.show())
527
528 pa_logger.info("Inserting flow")
529 rv = self.controller.message_send(request)
530 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700531 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco32fa6542010-05-11 15:54:08 -0700532
533 pa_logger.info("Sending packet to dp port " + str(ingress_port))
534 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700535 yes_ports = set(of_ports).difference([ingress_port])
536 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700537 self, pa_logger, pa_config)
Dan Talayco3be5b062010-05-12 15:46:21 -0700538
Dan Talayco3be5b062010-05-12 15:46:21 -0700539class FloodPlusIngress(basic.SimpleDataPlane):
540 """
541 Flood to all ports plus send to ingress port
542
543 Generate a packet
544 Generate and install a matching flow
545 Add action to flood the packet
546 Add action to send to ingress port
547 Send the packet to ingress dataplane port
548 Verify the packet is received at all other ports
549 """
550 def runTest(self):
Dan Talayco3be5b062010-05-12 15:46:21 -0700551 of_ports = pa_port_map.keys()
552 of_ports.sort()
553 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
554
555 pkt = simple_tcp_packet()
556 match = parse.packet_to_flow_match(pkt)
557 match.wildcards &= ~ofp.OFPFW_IN_PORT
558 self.assertTrue(match is not None,
559 "Could not generate flow match from pkt")
560 act = action.action_output()
561
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700562 for ingress_port in of_ports:
563 rv = delete_all_flows(self.controller, pa_logger)
564 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700565
Dan Talayco3be5b062010-05-12 15:46:21 -0700566 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700567 match.in_port = ingress_port
568
569 request = message.flow_mod()
570 request.match = match
571 request.buffer_id = 0xffffffff
572 act.port = ofp.OFPP_FLOOD
573 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700574 "Could not add flood port action")
575 act.port = ofp.OFPP_IN_PORT
576 self.assertTrue(request.actions.add(act),
577 "Could not add ingress port for output")
578 pa_logger.info(request.show())
579
580 pa_logger.info("Inserting flow")
581 rv = self.controller.message_send(request)
582 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700583 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700584
585 pa_logger.info("Sending packet to dp port " + str(ingress_port))
586 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700587 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700588 pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700589
590class All(basic.SimpleDataPlane):
591 """
592 Send to OFPP_ALL port
593
594 Generate a packet
595 Generate and install a matching flow
596 Add action to forward to OFPP_ALL
597 Send the packet to ingress dataplane port
598 Verify the packet is received at all other ports
599 """
600 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700601 of_ports = pa_port_map.keys()
602 of_ports.sort()
603 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
604
605 pkt = simple_tcp_packet()
606 match = parse.packet_to_flow_match(pkt)
607 match.wildcards &= ~ofp.OFPFW_IN_PORT
608 self.assertTrue(match is not None,
609 "Could not generate flow match from pkt")
610 act = action.action_output()
611
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700612 for ingress_port in of_ports:
613 rv = delete_all_flows(self.controller, pa_logger)
614 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700615
Dan Talayco4aa13122010-05-12 15:54:44 -0700616 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700617 match.in_port = ingress_port
618
619 request = message.flow_mod()
620 request.match = match
621 request.buffer_id = 0xffffffff
622 act.port = ofp.OFPP_ALL
623 self.assertTrue(request.actions.add(act),
624 "Could not add ALL port action")
625 pa_logger.info(request.show())
626
627 pa_logger.info("Inserting flow")
628 rv = self.controller.message_send(request)
629 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700630 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700631
632 pa_logger.info("Sending packet to dp port " + str(ingress_port))
633 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700634 yes_ports = set(of_ports).difference([ingress_port])
635 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700636 self, pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700637
638class AllPlusIngress(basic.SimpleDataPlane):
639 """
640 Send to OFPP_ALL port and ingress port
641
642 Generate a packet
643 Generate and install a matching flow
644 Add action to forward to OFPP_ALL
645 Add action to forward to ingress port
646 Send the packet to ingress dataplane port
647 Verify the packet is received at all other ports
648 """
649 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700650 of_ports = pa_port_map.keys()
651 of_ports.sort()
652 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
653
654 pkt = simple_tcp_packet()
655 match = parse.packet_to_flow_match(pkt)
656 match.wildcards &= ~ofp.OFPFW_IN_PORT
657 self.assertTrue(match is not None,
658 "Could not generate flow match from pkt")
659 act = action.action_output()
660
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700661 for ingress_port in of_ports:
662 rv = delete_all_flows(self.controller, pa_logger)
663 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700664
Dan Talayco4aa13122010-05-12 15:54:44 -0700665 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700666 match.in_port = ingress_port
667
668 request = message.flow_mod()
669 request.match = match
670 request.buffer_id = 0xffffffff
671 act.port = ofp.OFPP_ALL
672 self.assertTrue(request.actions.add(act),
673 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700674 act.port = ofp.OFPP_IN_PORT
675 self.assertTrue(request.actions.add(act),
676 "Could not add ingress port for output")
677 pa_logger.info(request.show())
678
679 pa_logger.info("Inserting flow")
680 rv = self.controller.message_send(request)
681 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700682 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco3be5b062010-05-12 15:46:21 -0700683
684 pa_logger.info("Sending packet to dp port " + str(ingress_port))
685 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700686 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700687 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700688
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700689class FloodMinusPort(basic.SimpleDataPlane):
690 """
691 Config port with No_Flood and test Flood action
692
693 Generate a packet
694 Generate a matching flow
695 Add action to forward to OFPP_ALL
696 Set port to no-flood
697 Send the packet to ingress dataplane port
698 Verify the packet is received at all other ports except
699 the ingress port and the no_flood port
700 """
701 def runTest(self):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700702 of_ports = pa_port_map.keys()
703 of_ports.sort()
704 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
705
706 pkt = simple_tcp_packet()
707 match = parse.packet_to_flow_match(pkt)
708 match.wildcards &= ~ofp.OFPFW_IN_PORT
709 self.assertTrue(match is not None,
710 "Could not generate flow match from pkt")
711 act = action.action_output()
712
713 for idx in range(len(of_ports)):
714 rv = delete_all_flows(self.controller, pa_logger)
715 self.assertEqual(rv, 0, "Failed to delete all flows")
716
717 ingress_port = of_ports[idx]
718 no_flood_idx = (idx + 1) % len(of_ports)
719 no_flood_port = of_ports[no_flood_idx]
720 rv = port_config_set(self.controller, no_flood_port,
721 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
722 pa_logger)
723 self.assertEqual(rv, 0, "Failed to set port config")
724
725 match.in_port = ingress_port
726
727 request = message.flow_mod()
728 request.match = match
729 request.buffer_id = 0xffffffff
730 act.port = ofp.OFPP_FLOOD
731 self.assertTrue(request.actions.add(act),
732 "Could not add flood port action")
733 pa_logger.info(request.show())
734
735 pa_logger.info("Inserting flow")
736 rv = self.controller.message_send(request)
737 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700738 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700739
740 pa_logger.info("Sending packet to dp port " + str(ingress_port))
741 pa_logger.info("No flood port is " + str(no_flood_port))
742 self.dataplane.send(ingress_port, str(pkt))
743 no_ports = set([ingress_port, no_flood_port])
744 yes_ports = set(of_ports).difference(no_ports)
745 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700746 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700747
748 # Turn no flood off again
749 rv = port_config_set(self.controller, no_flood_port,
750 0, ofp.OFPPC_NO_FLOOD, pa_logger)
751 self.assertEqual(rv, 0, "Failed to reset port config")
752
753 #@todo Should check no other packets received
754
Dan Talayco21381562010-07-17 00:34:47 -0700755
756
Dan Talayco551befa2010-07-15 17:05:32 -0700757################################################################
758
759class BaseMatchCase(basic.SimpleDataPlane):
760 def setUp(self):
761 basic.SimpleDataPlane.setUp(self)
762 self.logger = pa_logger
763 def runTest(self):
764 self.logger.info("BaseMatchCase")
765
766class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700767 """
Dan Talayco551befa2010-07-15 17:05:32 -0700768 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700769
770 Generate a packet
771 Generate and install a matching flow without wildcard mask
772 Add action to forward to a port
773 Send the packet to the port
774 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700775 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700776
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700777 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700778 flow_match_test(self, pa_port_map)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700779
Dan Talayco551befa2010-07-15 17:05:32 -0700780class ExactMatchTagged(BaseMatchCase):
781 """
782 Exact match for all port pairs with tagged pkts
783 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700784
Dan Talayco551befa2010-07-15 17:05:32 -0700785 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700786 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700787 flow_match_test(self, pa_port_map, dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700788
Dan Talayco551befa2010-07-15 17:05:32 -0700789class ExactMatchTaggedMany(BaseMatchCase):
790 """
791 ExactMatchTagged with many VLANS
792 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700793
Dan Talayco551befa2010-07-15 17:05:32 -0700794 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700795 for vid in range(2,100,10):
Dan Talayco551befa2010-07-15 17:05:32 -0700796 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
797 for vid in range(100,4000,389):
798 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
799 flow_match_test(self, pa_port_map, dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700800
Dan Talayco551befa2010-07-15 17:05:32 -0700801# Don't run by default
802test_prio["ExactMatchTaggedMany"] = -1
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700803
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700804
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700805class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700806 """
807 SingleWildcardMatchPriority
808 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700809
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700810 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700811 self.pkt = simple_tcp_packet()
812 self.flowMsgs = {}
813
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700814 def _ClearTable(self):
815 rc = delete_all_flows(self.controller, self.logger)
816 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700817 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700818
819 def runTest(self):
820
821 self._Init()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700822 of_ports = pa_port_map.keys()
823 of_ports.sort()
824
825 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700826 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700827
828 # Run several combinations, each at lower priority settings.
829 # At the end of each call to runPrioFlows(), the table should
830 # be empty. If its not, we'll catch it as the priorities decreases
831 portA = of_ports[0]
832 portB = of_ports[1]
833 portC = of_ports[2]
834
835 # TODO -- these priority numbers should be validated somehow?
836 self.runPrioFlows(portA, portB, portC, 1000, 999)
837 self.runPrioFlows(portB, portC, portA, 998, 997)
838 self.runPrioFlows(portC, portA, portB, 996, 995)
839 self.runPrioFlows(portA, portC, portB, 994, 993)
840
841
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700842
843 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
844 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700845
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700846 if clearTable:
847 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700848
849 # Sanity check flow at lower priority from pA to pB
850 self.logger.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
851 % (portA, portB, portC, prioHigher, prioLower))
852
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700853 self.installFlow(prioHigher, portA, portC)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700854 self.installFlow(prioLower, portA, portB)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700855
856 return
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700857 self.verifyFlow(portA, portB)
858 self.removeFlow(prioLower)
859 # Sanity check flow at lower priority from pA to pC
860 self.installFlow(prioLower, portA, portC)
861 self.verifyFlow(portA, portC)
862 self.removeFlow(prioLower)
863
864 # Install and verify pA->pB @ prioLower
865 self.installFlow(prioLower, portA, portB)
866 self.verifyFlow(portA, portB)
867
868 # Install and verify pA->pC @ prioHigher, should override pA->pB
869 self.installFlow(prioHigher, portA, portC)
870 self.verifyFlow(portA, portC)
871 # remove pA->pC
872 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700873 # Old flow pA -> pB @ prioLower should still be active
874 self.verifyFlow(portA, portB)
875 self.removeFlow(prioLower)
876
877 # Table should be empty at this point, leave it alone as
878 # an assumption for future test runs
879
880
881
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700882 def installFlow(self, prio, inp, egp,
883 wildcards=ofp.OFPFW_DL_SRC):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700884 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700885 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700886 egr_ports=egp)
887 request.priority = prio
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700888 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700889 self.flowMsgs[prio] = request
890
891 def removeFlow(self, prio):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700892 return
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700893 if self.flowMsgs.has_key(prio):
894 msg = self.flowMsgs[prio]
895 msg.command = ofp.OFPFC_DELETE_STRICT
896 # This *must* be set for DELETE
897 msg.out_port = ofp.OFPP_NONE
898 self.controller.message_send(msg)
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700899 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700900 else:
901 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700902
903
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700904 def verifyFlow(self, inp, egp, pkt=None):
905 if pkt == None:
906 pkt = self.pkt
907
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700908 self.logger.info("Pkt match test: " + str(inp) +
909 " to " + str(egp))
910 self.logger.debug("Send packet: " + str(inp) + " to "
911 + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700912 self.dataplane.send(inp, str(pkt))
913 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700914
915
916
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700917class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
918
919 def runTest(self):
920
921 self._Init()
922
923 of_ports = pa_port_map.keys()
924 of_ports.sort()
925
926 # Install an entry from 0 -> 1 @ prio 1000
927 self._ClearTable()
928 self.installFlow(1000, of_ports[0], of_ports[1])
929 self.verifyFlow(of_ports[0], of_ports[1])
930 self.installFlow(1000, of_ports[1], of_ports[0])
931 self.verifyFlow(of_ports[1], of_ports[0])
932 self.installFlow(1001, of_ports[0], of_ports[1])
933 self.verifyFlow(of_ports[0], of_ports[1])
934 self.installFlow(1001, of_ports[1], of_ports[0])
935 self.verifyFlow(of_ports[1], of_ports[0])
936 self.removeFlow(1001)
937 self.verifyFlow(of_ports[0], of_ports[1])
938 self.removeFlow(1000)
939
940
941
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700942class WildcardPriority(SingleWildcardMatchPriority):
943
944 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700945
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700946 self._Init()
947
948 of_ports = pa_port_map.keys()
949 of_ports.sort()
950
951 self._ClearTable()
952 # Install a flow with no wildcards for our packet:
953 self.installFlow(1000, of_ports[0], of_ports[1], wildcards=0)
954 self.verifyFlow(of_ports[0], of_ports[1])
955 # Install a flow with wildcards for our packet with higher
956 # priority.
957 self.installFlow(1001, of_ports[0], of_ports[2])
958 self.verifyFlow(of_ports[0], of_ports[2])
959
960
961
Dan Talayco551befa2010-07-15 17:05:32 -0700962class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700963 """
964 Exercise wildcard matching for all ports
965
966 Generate a packet
967 Generate and install a matching flow with wildcard mask
968 Add action to forward to a port
969 Send the packet to the port
970 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700971 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700972 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700973 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -0700974 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700975 for wc in WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -0700976 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -0700977 # Set nonzero VLAN id to avoid sending priority-tagged packet
978 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -0700979 else:
980 dl_vlan = -1
981 flow_match_test(self, pa_port_map, wildcards=wc,
982 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700983
Dan Talayco551befa2010-07-15 17:05:32 -0700984class SingleWildcardMatchTagged(BaseMatchCase):
985 """
986 SingleWildcardMatch with tagged packets
987 """
988 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700989 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700990 for wc in WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700991 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -0700992 max_test=10)
993
994class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700995 """
Dan Talayco80b54ed2010-07-13 09:48:35 -0700996 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700997
998 Generate a packet
999 Generate and install a matching flow with wildcard all except one filed
1000 Add action to forward to a port
1001 Send the packet to the port
1002 Verify the packet is received at all other ports (one port at a time)
1003 Verify flow_expiration message is correct when command option is set
1004 """
1005 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -07001006 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001007 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -07001008 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001009 # Set nonzero VLAN id to avoid sending priority-tagged packet
1010 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001011 else:
1012 dl_vlan = -1
1013 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
1014 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001015
Dan Talayco551befa2010-07-15 17:05:32 -07001016class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1017 """
1018 Match one field with tagged packets
1019 """
1020 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001021 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001022 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -07001023 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
1024 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001025
1026class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001027 """
1028 Create Wildcard-all flow and exercise for all ports
1029
1030 Generate a packet
1031 Generate and install a matching flow with wildcard-all
1032 Add action to forward to a port
1033 Send the packet to the port
1034 Verify the packet is received at all other ports (one port at a time)
1035 Verify flow_expiration message is correct when command option is set
1036 """
1037 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -07001038 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001039
Dan Talayco551befa2010-07-15 17:05:32 -07001040class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001041 """
Dan Talayco551befa2010-07-15 17:05:32 -07001042 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001043 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001044 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001045 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -07001046 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
1047 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001048
Dan Talaycoba3745c2010-07-21 21:51:08 -07001049
Dan Talayco551befa2010-07-15 17:05:32 -07001050class AddVLANTag(BaseMatchCase):
1051 """
1052 Add a VLAN tag to an untagged packet
1053 """
1054 def runTest(self):
1055 new_vid = 2
1056 sup_acts = supported_actions_get(self)
1057 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001058 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001059 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001060
Dan Talayco551befa2010-07-15 17:05:32 -07001061 len = 100
1062 len_w_vid = 104
1063 pkt = simple_tcp_packet(pktlen=len)
1064 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1065 dl_vlan=new_vid)
1066 vid_act = action.action_set_vlan_vid()
1067 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001068
Dan Talayco551befa2010-07-15 17:05:32 -07001069 flow_match_test(self, pa_port_map, pkt=pkt,
1070 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001071
Dan Talayco551befa2010-07-15 17:05:32 -07001072class PacketOnly(basic.DataPlaneOnly):
1073 """
1074 Just send a packet thru the switch
1075 """
1076 def runTest(self):
1077 pkt = simple_tcp_packet()
1078 of_ports = pa_port_map.keys()
1079 of_ports.sort()
1080 ing_port = of_ports[0]
1081 pa_logger.info("Sending packet to " + str(ing_port))
1082 pa_logger.debug("Data: " + str(pkt).encode('hex'))
1083 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001084
Dan Talayco551befa2010-07-15 17:05:32 -07001085class PacketOnlyTagged(basic.DataPlaneOnly):
1086 """
1087 Just send a packet thru the switch
1088 """
1089 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001090 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001091 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
1092 of_ports = pa_port_map.keys()
1093 of_ports.sort()
1094 ing_port = of_ports[0]
1095 pa_logger.info("Sending packet to " + str(ing_port))
1096 pa_logger.debug("Data: " + str(pkt).encode('hex'))
1097 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001098
Dan Talayco551befa2010-07-15 17:05:32 -07001099test_prio["PacketOnly"] = -1
1100test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001101
Dan Talayco551befa2010-07-15 17:05:32 -07001102class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001103 """
1104 Modify the VLAN ID in the VLAN tag of a tagged packet
1105 """
Dan Talayco551befa2010-07-15 17:05:32 -07001106 def runTest(self):
1107 old_vid = 2
1108 new_vid = 3
1109 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001110 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001111 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001112 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001113
Dan Talayco551befa2010-07-15 17:05:32 -07001114 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1115 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
1116 vid_act = action.action_set_vlan_vid()
1117 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001118
Dan Talayco551befa2010-07-15 17:05:32 -07001119 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1120 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001121
Howard Pershc1199d52012-04-11 14:21:32 -07001122class ModifyVlanPcp(BaseMatchCase):
1123 """
1124 Modify the priority field of the VLAN tag of a tagged packet
1125 """
1126 def runTest(self):
1127 vid = 123
1128 old_vlan_pcp = 2
1129 new_vlan_pcp = 3
1130 sup_acts = supported_actions_get(self)
1131 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1132 skip_message_emit(self, "Modify VLAN tag test")
1133 return
1134
1135 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1136 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1137 vid_act = action.action_set_vlan_pcp()
1138 vid_act.vlan_pcp = new_vlan_pcp
1139
1140 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1141 action_list=[vid_act])
1142
Dan Talayco551befa2010-07-15 17:05:32 -07001143class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001144 """
1145 Strip the VLAN tag from a tagged packet
1146 """
Dan Talayco551befa2010-07-15 17:05:32 -07001147 def runTest(self):
1148 old_vid = 2
1149 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001150 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001151 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001152 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001153
Dan Talayco551befa2010-07-15 17:05:32 -07001154 len_w_vid = 104
1155 len = 100
1156 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1157 dl_vlan=old_vid)
1158 exp_pkt = simple_tcp_packet(pktlen=len)
1159 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001160
Dan Talayco551befa2010-07-15 17:05:32 -07001161 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1162 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001163
Dan Talayco4b2bee62010-07-20 14:10:05 -07001164def init_pkt_args():
1165 """
1166 Pass back a dictionary with default packet arguments
1167 """
1168 args = {}
1169 args["dl_src"] = '00:23:45:67:89:AB'
1170
1171 dl_vlan_enable=False
1172 dl_vlan=-1
1173 if pa_config["test-params"]["vid"]:
1174 dl_vlan_enable=True
1175 dl_vlan = pa_config["test-params"]["vid"]
1176
1177# Unpack operator is ** on a dictionary
1178
1179 return args
1180
Dan Talayco551befa2010-07-15 17:05:32 -07001181class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001182 """
1183 Modify the source MAC address (TP1)
1184 """
Dan Talayco551befa2010-07-15 17:05:32 -07001185 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001186 sup_acts = supported_actions_get(self)
1187 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001188 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001189 return
1190
1191 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1192 check_test_params=True)
1193 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1194 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001195
Dan Talayco551befa2010-07-15 17:05:32 -07001196class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001197 """
1198 Modify the dest MAC address (TP1)
1199 """
Dan Talayco551befa2010-07-15 17:05:32 -07001200 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001201 sup_acts = supported_actions_get(self)
1202 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001203 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001204 return
1205
1206 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1207 check_test_params=True)
1208 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1209 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001210
Dan Talayco551befa2010-07-15 17:05:32 -07001211class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001212 """
1213 Modify the source IP address of an IP packet (TP1)
1214 """
Dan Talayco551befa2010-07-15 17:05:32 -07001215 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001216 sup_acts = supported_actions_get(self)
1217 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001218 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001219 return
1220
1221 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1222 check_test_params=True)
1223 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1224 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001225
Dan Talayco551befa2010-07-15 17:05:32 -07001226class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001227 """
1228 Modify the dest IP address of an IP packet (TP1)
1229 """
Dan Talayco551befa2010-07-15 17:05:32 -07001230 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001231 sup_acts = supported_actions_get(self)
1232 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001233 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001234 return
1235
1236 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1237 check_test_params=True)
1238 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1239 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001240
1241class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001242 """
1243 Modify the source TCP port of a TCP packet (TP1)
1244 """
Dan Talayco551befa2010-07-15 17:05:32 -07001245 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001246 sup_acts = supported_actions_get(self)
1247 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001248 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001249 return
1250
1251 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1252 check_test_params=True)
1253 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1254 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001255
1256class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001257 """
1258 Modify the dest TCP port of a TCP packet (TP1)
1259 """
Dan Talayco551befa2010-07-15 17:05:32 -07001260 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001261 sup_acts = supported_actions_get(self)
1262 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001263 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001264 return
1265
1266 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1267 check_test_params=True)
1268 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1269 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001270
1271class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001272 """
1273 Modify the IP type of service of an IP packet (TP1)
1274 """
Dan Talayco551befa2010-07-15 17:05:32 -07001275 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001276 sup_acts = supported_actions_get(self)
1277 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001278 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001279 return
Dan Talayco551befa2010-07-15 17:05:32 -07001280
Dan Talayco4b2bee62010-07-20 14:10:05 -07001281 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1282 check_test_params=True)
1283 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001284 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001285
Dan Talaycof6e76c02012-03-23 10:56:12 -07001286class ModifyL2DstMC(BaseMatchCase):
1287 """
1288 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001289 """
1290 def runTest(self):
1291 sup_acts = supported_actions_get(self)
1292 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001293 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001294 return
1295
Dan Talaycof6e76c02012-03-23 10:56:12 -07001296 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1297 check_test_params=True)
1298 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001299 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001300
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001301class ModifyL2DstIngress(BaseMatchCase):
1302 """
1303 Modify the L2 dest and send to the ingress port
1304 """
1305 def runTest(self):
1306 sup_acts = supported_actions_get(self)
1307 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001308 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001309 return
1310
1311 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1312 check_test_params=True)
1313 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1314 action_list=acts, max_test=2, egr_count=0,
1315 ing_port=True)
1316
Dan Talaycod8ae7582012-03-23 12:24:56 -07001317class ModifyL2DstIngressMC(BaseMatchCase):
1318 """
1319 Modify the L2 dest and send to the ingress port
1320 """
1321 def runTest(self):
1322 sup_acts = supported_actions_get(self)
1323 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1324 skip_message_emit(self, "ModifyL2dstMC test")
1325 return
1326
1327 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1328 check_test_params=True)
1329 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1330 action_list=acts, max_test=2, egr_count=-1,
1331 ing_port=True)
1332
Dan Talaycof6e76c02012-03-23 10:56:12 -07001333class ModifyL2SrcMC(BaseMatchCase):
1334 """
1335 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001336 """
1337 def runTest(self):
1338 sup_acts = supported_actions_get(self)
1339 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001340 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001341 return
1342
Dan Talaycof6e76c02012-03-23 10:56:12 -07001343 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1344 check_test_params=True)
1345 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001346 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001347
1348class ModifyL2SrcDstMC(BaseMatchCase):
1349 """
1350 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001351 """
1352 def runTest(self):
1353 sup_acts = supported_actions_get(self)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001354 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1355 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1356 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001357 return
1358
Dan Talaycof6e76c02012-03-23 10:56:12 -07001359 mod_fields = ['dl_dst', 'dl_src']
1360 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1361 check_test_params=True)
1362 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001363 action_list=acts, max_test=2, egr_count=-1)
1364
1365class ModifyL2DstVIDMC(BaseMatchCase):
1366 """
1367 Modify the L2 dest and send to 2 ports
1368 """
1369 def runTest(self):
1370 sup_acts = supported_actions_get(self)
1371 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1372 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1373 skip_message_emit(self, "ModifyL2DstVIDMC test")
1374 return
1375
1376 mod_fields = ['dl_dst', 'dl_vlan']
1377 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1378 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1379 check_test_params=True)
1380 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1381 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001382
Dan Talaycofa6454f2012-04-05 10:04:13 -07001383class FlowToggle(BaseMatchCase):
1384 """
1385 Add flows to the table and modify them repeatedly
1386 """
1387 def runTest(self):
Dan Talayco50be7672012-04-05 11:38:08 -07001388 flow_count = test_param_get(self.config, 'ft_flow_count', default=20)
1389 iter_count = test_param_get(self.config, 'ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001390
1391 pa_logger.info("Running flow toggle with %d flows, %d iterations" %
1392 (flow_count, iter_count))
1393 acts = []
1394 acts.append(action.action_output())
1395 acts.append(action.action_output())
1396
1397 of_ports = pa_port_map.keys()
1398 if len(of_ports) < 3:
1399 self.assertTrue(False, "Too few ports for test")
1400
1401 for idx in range(2):
1402 acts[idx].port = of_ports[idx]
1403
1404 flows = []
1405 flows.append([])
1406 flows.append([])
1407
Dan Talayco50be7672012-04-05 11:38:08 -07001408 wildcards = ofp.OFPFW_DL_SRC | ofp.OFPFW_DL_DST
Dan Talaycofa6454f2012-04-05 10:04:13 -07001409 # Create up the flows in an array
1410 for toggle in range(2):
1411 for f_idx in range(flow_count):
1412 pkt = simple_tcp_packet(tcp_sport=f_idx)
1413 msg = message.flow_mod()
1414 match = parse.packet_to_flow_match(pkt)
1415 match.in_port = of_ports[3]
Dan Talayco50be7672012-04-05 11:38:08 -07001416 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001417 msg.match = match
1418 msg.buffer_id = 0xffffffff
1419 msg.actions.add(acts[toggle])
1420 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001421
1422 # Show two sample flows
1423 pa_logger.debug(flows[0][0].show())
1424 pa_logger.debug(flows[1][0].show())
1425
Dan Talaycofa6454f2012-04-05 10:04:13 -07001426 # Install the first set of flows
1427 for f_idx in range(flow_count):
1428 rv = self.controller.message_send(flows[0][f_idx])
1429 self.assertTrue(rv != -1, "Error installing flow %d" % f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001430 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycofa6454f2012-04-05 10:04:13 -07001431
1432 pa_logger.info("Installed %d flows" % flow_count)
1433
1434 # Repeatedly modify all the flows back and forth
1435 updates = 0
1436 # Report status about 5 times
1437 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001438 start = time.time()
1439 for iter_idx in range(iter_count):
1440 if not iter_idx % mod_val:
1441 pa_logger.info("Flow Toggle: iter %d of %d. " %
1442 (iter_idx, iter_count) +
1443 "%d updates in %d secs" %
1444 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001445 for toggle in range(2):
1446 t_idx = 1 - toggle
1447 for f_idx in range(flow_count):
1448 rv = self.controller.message_send(flows[t_idx][f_idx])
1449 updates += 1
1450 self.assertTrue(rv != -1, "Error modifying flow %d" %
1451 f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001452 self.assertEqual(do_barrier(self.controller), 0,
1453 "Barrier failed")
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001454
1455 end = time.time()
1456 divisor = end - start or (end - start + 1)
1457 pa_logger.info("Flow toggle: %d iterations" % iter_count)
1458 pa_logger.info(" %d flow mods in %d secs, %d mods/sec" %
1459 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001460
1461
Dan Talayco8a64e332012-03-28 14:53:20 -07001462# You can pick and choose these by commenting tests in or out
1463iter_classes = [
1464 basic.PacketIn,
1465 basic.PacketOut,
1466 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001467 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001468 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001469 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001470 AllWildcardMatch,
1471 AllWildcardMatchTagged,
1472 SingleWildcardMatch,
1473 SingleWildcardMatchTagged,
1474 ExactMatch,
1475 ExactMatchTagged,
1476 SingleWildcardMatch,
1477 ModifyL2Src,
1478 ModifyL2Dst,
1479 ModifyL2SrcMC,
1480 ModifyL2DstMC,
1481 ModifyL2SrcDstMC
1482 ]
1483
1484class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001485 """
1486 Iterate over a bunch of test cases
1487
1488 The cases come from the list above
1489 """
1490
Dan Talayco8a64e332012-03-28 14:53:20 -07001491 def runTest(self):
1492 count = test_param_get(self.config, 'iter_count', default=10)
1493 tests_done = 0
1494 pa_logger.info("Running iteration test " + str(count) + " times")
1495 start = time.time()
1496 last = start
1497 for idx in range(count):
1498 pa_logger.info("Iteration " + str(idx + 1))
1499 for cls in iter_classes:
1500 test = cls()
1501 test.inheritSetup(self)
1502 test.runTest()
1503 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001504 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001505 if time.time() - last > 60:
1506 last = time.time()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001507 pa_logger.info(
1508 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1509 (idx, count, tests_done, last - start) +
1510 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001511 stats = all_stats_get(self)
1512 last = time.time()
1513 pa_logger.info("\nIterCases ran %d tests in %d seconds." %
1514 (tests_done, last - start))
1515 pa_logger.info(" flows: %d. packets: %d. bytes: %d" %
1516 (stats["flows"], stats["packets"], stats["bytes"]))
1517 pa_logger.info(" active: %d. lookups: %d. matched %d." %
1518 (stats["active"], stats["lookups"], stats["matched"]))
1519
1520# Don't run by default
1521test_prio["IterCases"] = -1
Dan Talaycof6e76c02012-03-23 10:56:12 -07001522
Dan Talayco4b2bee62010-07-20 14:10:05 -07001523#@todo Need to implement tagged versions of the above tests
1524#
1525#@todo Implement a test case that strips tag 2, adds tag 3
1526# and modifies tag 4 to tag 5. Then verify (in addition) that
1527# tag 6 does not get modified.
1528
1529class MixedVLAN(BaseMatchCase):
1530 """
1531 Test mixture of VLAN tag actions
1532
1533 Strip tag 2 on port 1, send to port 2
1534 Add tag 3 on port 1, send to port 2
1535 Modify tag 4 to 5 on port 1, send to port 2
1536 All other traffic from port 1, send to port 3
1537 All traffic from port 2 sent to port 4
1538 Use exact matches with different packets for all mods
1539 Verify the following: (port, vid)
1540 (port 1, vid 2) => VLAN tag stripped, out port 2
1541 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1542 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1543 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1544 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1545 (port 2, no tag) => untagged packet out port 4
1546 (port 2, vid 2-6) => unmodified packet out port 4
1547
1548 Variation: Might try sending VID 5 to port 3 and check.
1549 If only VID 5 distinguishes pkt, this will fail on some platforms
1550 """
1551
1552test_prio["MixedVLAN"] = -1
1553
Dan Talayco551befa2010-07-15 17:05:32 -07001554def supported_actions_get(parent, use_cache=True):
1555 """
1556 Get the bitmap of supported actions from the switch
1557 If use_cache is false, the cached value will be updated
1558 """
1559 global cached_supported_actions
1560 if cached_supported_actions is None or not use_cache:
1561 request = message.features_request()
1562 (reply, pkt) = parent.controller.transact(request, timeout=2)
1563 parent.assertTrue(reply is not None, "Did not get response to ftr req")
1564 cached_supported_actions = reply.actions
1565 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
1566
1567 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -07001568
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001569if __name__ == "__main__":
1570 print "Please run through oft script: ./oft --test_spec=basic"