blob: dc767f0e267b13bd4191dfa33572bef52f1932eb [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
Ken Chiange9a211d2012-04-20 14:52:11 -07001122class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1123 """
1124 With vlan ID and priority wildcarded, perform SET_VLAN_VID action.
1125 The same flow should match on both untagged and tagged packets.
1126 """
1127 def runTest(self):
1128 old_vid = 2
1129 new_vid = 3
1130 sup_acts = supported_actions_get(self)
1131 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1132 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1133 return
1134
1135 of_ports = pa_port_map.keys()
1136 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1137 ing_port = of_ports[0]
1138 egr_ports = of_ports[1]
1139
1140 rv = delete_all_flows(self.controller, pa_logger)
1141 self.assertEqual(rv, 0, "Failed to delete all flows")
1142
1143 len_untagged = 100
1144 len_w_vid = 104
1145 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1146 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
1147 dl_vlan_enable=True, dl_vlan=old_vid)
1148 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1149 dl_vlan=new_vid)
1150 wildcards=ofp.OFPFW_DL_VLAN|ofp.OFPFW_DL_VLAN_PCP
1151 vid_act = action.action_set_vlan_vid()
1152 vid_act.vlan_vid = new_vid
1153 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
1154 wildcards=wildcards, egr_ports=egr_ports,
1155 action_list=[vid_act])
1156 flow_msg_install(self, request)
1157
1158 pa_logger.debug("Send untagged packet: " + str(ing_port) + " to " +
1159 str(egr_ports))
1160 self.dataplane.send(ing_port, str(untagged_pkt))
1161 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1162
1163 pa_logger.debug("Send tagged packet: " + str(ing_port) + " to " +
1164 str(egr_ports))
1165 self.dataplane.send(ing_port, str(tagged_pkt))
1166 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1167
Howard Pershc1199d52012-04-11 14:21:32 -07001168class ModifyVlanPcp(BaseMatchCase):
1169 """
1170 Modify the priority field of the VLAN tag of a tagged packet
1171 """
1172 def runTest(self):
1173 vid = 123
1174 old_vlan_pcp = 2
1175 new_vlan_pcp = 3
1176 sup_acts = supported_actions_get(self)
1177 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1178 skip_message_emit(self, "Modify VLAN tag test")
1179 return
1180
1181 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1182 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1183 vid_act = action.action_set_vlan_pcp()
1184 vid_act.vlan_pcp = new_vlan_pcp
1185
1186 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1187 action_list=[vid_act])
1188
Dan Talayco551befa2010-07-15 17:05:32 -07001189class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001190 """
1191 Strip the VLAN tag from a tagged packet
1192 """
Dan Talayco551befa2010-07-15 17:05:32 -07001193 def runTest(self):
1194 old_vid = 2
1195 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001196 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001197 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001198 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001199
Dan Talayco551befa2010-07-15 17:05:32 -07001200 len_w_vid = 104
1201 len = 100
1202 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1203 dl_vlan=old_vid)
1204 exp_pkt = simple_tcp_packet(pktlen=len)
1205 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001206
Dan Talayco551befa2010-07-15 17:05:32 -07001207 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1208 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001209
Ken Chiange9a211d2012-04-20 14:52:11 -07001210class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1211 """
1212 Strip the VLAN tag from a tagged packet.
1213 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1214 """
1215 def runTest(self):
1216 old_vid = 2
1217 sup_acts = supported_actions_get(self)
1218 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1219 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1220 return
1221
1222 len_w_vid = 104
1223 len_untagged = 100
1224 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1225 dl_vlan=old_vid)
1226 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
1227 vid_act = action.action_strip_vlan()
1228
1229 flow_match_test(self, pa_port_map,
1230 wildcards=ofp.OFPFW_DL_VLAN|ofp.OFPFW_DL_VLAN_PCP,
1231 pkt=pkt, exp_pkt=exp_pkt,
1232 action_list=[vid_act])
1233
Dan Talayco4b2bee62010-07-20 14:10:05 -07001234def init_pkt_args():
1235 """
1236 Pass back a dictionary with default packet arguments
1237 """
1238 args = {}
1239 args["dl_src"] = '00:23:45:67:89:AB'
1240
1241 dl_vlan_enable=False
1242 dl_vlan=-1
1243 if pa_config["test-params"]["vid"]:
1244 dl_vlan_enable=True
1245 dl_vlan = pa_config["test-params"]["vid"]
1246
1247# Unpack operator is ** on a dictionary
1248
1249 return args
1250
Dan Talayco551befa2010-07-15 17:05:32 -07001251class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001252 """
1253 Modify the source MAC address (TP1)
1254 """
Dan Talayco551befa2010-07-15 17:05:32 -07001255 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001256 sup_acts = supported_actions_get(self)
1257 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001258 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001259 return
1260
1261 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1262 check_test_params=True)
1263 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1264 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001265
Dan Talayco551befa2010-07-15 17:05:32 -07001266class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001267 """
1268 Modify the dest MAC address (TP1)
1269 """
Dan Talayco551befa2010-07-15 17:05:32 -07001270 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001271 sup_acts = supported_actions_get(self)
1272 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001273 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001274 return
1275
1276 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1277 check_test_params=True)
1278 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1279 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001280
Dan Talayco551befa2010-07-15 17:05:32 -07001281class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001282 """
1283 Modify the source IP address of an IP packet (TP1)
1284 """
Dan Talayco551befa2010-07-15 17:05:32 -07001285 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001286 sup_acts = supported_actions_get(self)
1287 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001288 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001289 return
1290
1291 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1292 check_test_params=True)
1293 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1294 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001295
Dan Talayco551befa2010-07-15 17:05:32 -07001296class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001297 """
1298 Modify the dest IP address of an IP packet (TP1)
1299 """
Dan Talayco551befa2010-07-15 17:05:32 -07001300 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001301 sup_acts = supported_actions_get(self)
1302 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001303 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001304 return
1305
1306 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1307 check_test_params=True)
1308 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1309 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001310
1311class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001312 """
1313 Modify the source TCP port of a TCP packet (TP1)
1314 """
Dan Talayco551befa2010-07-15 17:05:32 -07001315 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001316 sup_acts = supported_actions_get(self)
1317 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001318 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001319 return
1320
1321 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1322 check_test_params=True)
1323 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1324 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001325
1326class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001327 """
1328 Modify the dest TCP port of a TCP packet (TP1)
1329 """
Dan Talayco551befa2010-07-15 17:05:32 -07001330 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001331 sup_acts = supported_actions_get(self)
1332 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001333 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001334 return
1335
1336 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1337 check_test_params=True)
1338 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1339 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001340
1341class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001342 """
1343 Modify the IP type of service of an IP packet (TP1)
1344 """
Dan Talayco551befa2010-07-15 17:05:32 -07001345 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001346 sup_acts = supported_actions_get(self)
1347 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001348 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001349 return
Dan Talayco551befa2010-07-15 17:05:32 -07001350
Dan Talayco4b2bee62010-07-20 14:10:05 -07001351 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1352 check_test_params=True)
1353 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001354 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001355
Dan Talaycof6e76c02012-03-23 10:56:12 -07001356class ModifyL2DstMC(BaseMatchCase):
1357 """
1358 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001359 """
1360 def runTest(self):
1361 sup_acts = supported_actions_get(self)
1362 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001363 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001364 return
1365
Dan Talaycof6e76c02012-03-23 10:56:12 -07001366 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1367 check_test_params=True)
1368 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001369 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001370
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001371class ModifyL2DstIngress(BaseMatchCase):
1372 """
1373 Modify the L2 dest and send to the ingress port
1374 """
1375 def runTest(self):
1376 sup_acts = supported_actions_get(self)
1377 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001378 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001379 return
1380
1381 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1382 check_test_params=True)
1383 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1384 action_list=acts, max_test=2, egr_count=0,
1385 ing_port=True)
1386
Dan Talaycod8ae7582012-03-23 12:24:56 -07001387class ModifyL2DstIngressMC(BaseMatchCase):
1388 """
1389 Modify the L2 dest and send to the ingress port
1390 """
1391 def runTest(self):
1392 sup_acts = supported_actions_get(self)
1393 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1394 skip_message_emit(self, "ModifyL2dstMC test")
1395 return
1396
1397 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1398 check_test_params=True)
1399 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1400 action_list=acts, max_test=2, egr_count=-1,
1401 ing_port=True)
1402
Dan Talaycof6e76c02012-03-23 10:56:12 -07001403class ModifyL2SrcMC(BaseMatchCase):
1404 """
1405 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001406 """
1407 def runTest(self):
1408 sup_acts = supported_actions_get(self)
1409 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001410 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001411 return
1412
Dan Talaycof6e76c02012-03-23 10:56:12 -07001413 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1414 check_test_params=True)
1415 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001416 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001417
1418class ModifyL2SrcDstMC(BaseMatchCase):
1419 """
1420 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001421 """
1422 def runTest(self):
1423 sup_acts = supported_actions_get(self)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001424 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1425 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1426 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001427 return
1428
Dan Talaycof6e76c02012-03-23 10:56:12 -07001429 mod_fields = ['dl_dst', 'dl_src']
1430 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1431 check_test_params=True)
1432 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001433 action_list=acts, max_test=2, egr_count=-1)
1434
1435class ModifyL2DstVIDMC(BaseMatchCase):
1436 """
1437 Modify the L2 dest and send to 2 ports
1438 """
1439 def runTest(self):
1440 sup_acts = supported_actions_get(self)
1441 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1442 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1443 skip_message_emit(self, "ModifyL2DstVIDMC test")
1444 return
1445
1446 mod_fields = ['dl_dst', 'dl_vlan']
1447 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1448 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1449 check_test_params=True)
1450 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1451 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001452
Dan Talaycofa6454f2012-04-05 10:04:13 -07001453class FlowToggle(BaseMatchCase):
1454 """
1455 Add flows to the table and modify them repeatedly
1456 """
1457 def runTest(self):
Dan Talayco50be7672012-04-05 11:38:08 -07001458 flow_count = test_param_get(self.config, 'ft_flow_count', default=20)
1459 iter_count = test_param_get(self.config, 'ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001460
1461 pa_logger.info("Running flow toggle with %d flows, %d iterations" %
1462 (flow_count, iter_count))
1463 acts = []
1464 acts.append(action.action_output())
1465 acts.append(action.action_output())
1466
1467 of_ports = pa_port_map.keys()
1468 if len(of_ports) < 3:
1469 self.assertTrue(False, "Too few ports for test")
1470
1471 for idx in range(2):
1472 acts[idx].port = of_ports[idx]
1473
1474 flows = []
1475 flows.append([])
1476 flows.append([])
1477
Dan Talayco50be7672012-04-05 11:38:08 -07001478 wildcards = ofp.OFPFW_DL_SRC | ofp.OFPFW_DL_DST
Dan Talaycofa6454f2012-04-05 10:04:13 -07001479 # Create up the flows in an array
1480 for toggle in range(2):
1481 for f_idx in range(flow_count):
1482 pkt = simple_tcp_packet(tcp_sport=f_idx)
1483 msg = message.flow_mod()
1484 match = parse.packet_to_flow_match(pkt)
1485 match.in_port = of_ports[3]
Dan Talayco50be7672012-04-05 11:38:08 -07001486 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001487 msg.match = match
1488 msg.buffer_id = 0xffffffff
1489 msg.actions.add(acts[toggle])
1490 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001491
1492 # Show two sample flows
1493 pa_logger.debug(flows[0][0].show())
1494 pa_logger.debug(flows[1][0].show())
1495
Dan Talaycofa6454f2012-04-05 10:04:13 -07001496 # Install the first set of flows
1497 for f_idx in range(flow_count):
1498 rv = self.controller.message_send(flows[0][f_idx])
1499 self.assertTrue(rv != -1, "Error installing flow %d" % f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001500 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycofa6454f2012-04-05 10:04:13 -07001501
1502 pa_logger.info("Installed %d flows" % flow_count)
1503
1504 # Repeatedly modify all the flows back and forth
1505 updates = 0
1506 # Report status about 5 times
1507 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001508 start = time.time()
1509 for iter_idx in range(iter_count):
1510 if not iter_idx % mod_val:
1511 pa_logger.info("Flow Toggle: iter %d of %d. " %
1512 (iter_idx, iter_count) +
1513 "%d updates in %d secs" %
1514 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001515 for toggle in range(2):
1516 t_idx = 1 - toggle
1517 for f_idx in range(flow_count):
1518 rv = self.controller.message_send(flows[t_idx][f_idx])
1519 updates += 1
1520 self.assertTrue(rv != -1, "Error modifying flow %d" %
1521 f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001522 self.assertEqual(do_barrier(self.controller), 0,
1523 "Barrier failed")
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001524
1525 end = time.time()
1526 divisor = end - start or (end - start + 1)
1527 pa_logger.info("Flow toggle: %d iterations" % iter_count)
1528 pa_logger.info(" %d flow mods in %d secs, %d mods/sec" %
1529 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001530
1531
Dan Talayco8a64e332012-03-28 14:53:20 -07001532# You can pick and choose these by commenting tests in or out
1533iter_classes = [
1534 basic.PacketIn,
1535 basic.PacketOut,
1536 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001537 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001538 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001539 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001540 AllWildcardMatch,
1541 AllWildcardMatchTagged,
1542 SingleWildcardMatch,
1543 SingleWildcardMatchTagged,
1544 ExactMatch,
1545 ExactMatchTagged,
1546 SingleWildcardMatch,
1547 ModifyL2Src,
1548 ModifyL2Dst,
1549 ModifyL2SrcMC,
1550 ModifyL2DstMC,
1551 ModifyL2SrcDstMC
1552 ]
1553
1554class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001555 """
1556 Iterate over a bunch of test cases
1557
1558 The cases come from the list above
1559 """
1560
Dan Talayco8a64e332012-03-28 14:53:20 -07001561 def runTest(self):
1562 count = test_param_get(self.config, 'iter_count', default=10)
1563 tests_done = 0
1564 pa_logger.info("Running iteration test " + str(count) + " times")
1565 start = time.time()
1566 last = start
1567 for idx in range(count):
1568 pa_logger.info("Iteration " + str(idx + 1))
1569 for cls in iter_classes:
1570 test = cls()
1571 test.inheritSetup(self)
1572 test.runTest()
1573 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001574 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001575 if time.time() - last > 60:
1576 last = time.time()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001577 pa_logger.info(
1578 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1579 (idx, count, tests_done, last - start) +
1580 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001581 stats = all_stats_get(self)
1582 last = time.time()
1583 pa_logger.info("\nIterCases ran %d tests in %d seconds." %
1584 (tests_done, last - start))
1585 pa_logger.info(" flows: %d. packets: %d. bytes: %d" %
1586 (stats["flows"], stats["packets"], stats["bytes"]))
1587 pa_logger.info(" active: %d. lookups: %d. matched %d." %
1588 (stats["active"], stats["lookups"], stats["matched"]))
1589
1590# Don't run by default
1591test_prio["IterCases"] = -1
Dan Talaycof6e76c02012-03-23 10:56:12 -07001592
Dan Talayco4b2bee62010-07-20 14:10:05 -07001593#@todo Need to implement tagged versions of the above tests
1594#
1595#@todo Implement a test case that strips tag 2, adds tag 3
1596# and modifies tag 4 to tag 5. Then verify (in addition) that
1597# tag 6 does not get modified.
1598
1599class MixedVLAN(BaseMatchCase):
1600 """
1601 Test mixture of VLAN tag actions
1602
1603 Strip tag 2 on port 1, send to port 2
1604 Add tag 3 on port 1, send to port 2
1605 Modify tag 4 to 5 on port 1, send to port 2
1606 All other traffic from port 1, send to port 3
1607 All traffic from port 2 sent to port 4
1608 Use exact matches with different packets for all mods
1609 Verify the following: (port, vid)
1610 (port 1, vid 2) => VLAN tag stripped, out port 2
1611 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1612 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1613 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1614 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1615 (port 2, no tag) => untagged packet out port 4
1616 (port 2, vid 2-6) => unmodified packet out port 4
1617
1618 Variation: Might try sending VID 5 to port 3 and check.
1619 If only VID 5 distinguishes pkt, this will fail on some platforms
1620 """
1621
1622test_prio["MixedVLAN"] = -1
1623
Dan Talayco551befa2010-07-15 17:05:32 -07001624def supported_actions_get(parent, use_cache=True):
1625 """
1626 Get the bitmap of supported actions from the switch
1627 If use_cache is false, the cached value will be updated
1628 """
1629 global cached_supported_actions
1630 if cached_supported_actions is None or not use_cache:
1631 request = message.features_request()
1632 (reply, pkt) = parent.controller.transact(request, timeout=2)
1633 parent.assertTrue(reply is not None, "Did not get response to ftr req")
1634 cached_supported_actions = reply.actions
1635 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
1636
1637 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -07001638
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001639if __name__ == "__main__":
1640 print "Please run through oft script: ./oft --test_spec=basic"