blob: 5048510a5fd94976bc556df49a03a6164806db9f [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
Ken Chiang38d7a152012-05-24 15:33:50 -0700888 self.logger.debug("Install flow with priority " + str(prio))
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700889 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700890 self.flowMsgs[prio] = request
891
892 def removeFlow(self, prio):
893 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
Ken Chiang38d7a152012-05-24 15:33:50 -0700898 self.logger.debug("Remove flow with priority " + str(prio))
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700899 self.controller.message_send(msg)
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700900 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700901 else:
902 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700903
904
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700905 def verifyFlow(self, inp, egp, pkt=None):
906 if pkt == None:
907 pkt = self.pkt
908
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700909 self.logger.info("Pkt match test: " + str(inp) +
910 " to " + str(egp))
911 self.logger.debug("Send packet: " + str(inp) + " to "
912 + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700913 self.dataplane.send(inp, str(pkt))
914 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700915
916
917
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700918class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
919
920 def runTest(self):
921
922 self._Init()
923
924 of_ports = pa_port_map.keys()
925 of_ports.sort()
926
927 # Install an entry from 0 -> 1 @ prio 1000
928 self._ClearTable()
929 self.installFlow(1000, of_ports[0], of_ports[1])
930 self.verifyFlow(of_ports[0], of_ports[1])
931 self.installFlow(1000, of_ports[1], of_ports[0])
932 self.verifyFlow(of_ports[1], of_ports[0])
933 self.installFlow(1001, of_ports[0], of_ports[1])
934 self.verifyFlow(of_ports[0], of_ports[1])
935 self.installFlow(1001, of_ports[1], of_ports[0])
936 self.verifyFlow(of_ports[1], of_ports[0])
937 self.removeFlow(1001)
938 self.verifyFlow(of_ports[0], of_ports[1])
939 self.removeFlow(1000)
940
941
942
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700943class WildcardPriority(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -0700944 """
945 1. Add wildcard flow, verify packet received.
946 2. Add exact match flow with higher priority, verify packet received
947 on port specified by this flow.
948 3. Add wildcard flow with even higher priority, verify packet received
949 on port specified by this flow.
950 """
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700951
952 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700953
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700954 self._Init()
955
956 of_ports = pa_port_map.keys()
957 of_ports.sort()
958
959 self._ClearTable()
Ken Chiang38d7a152012-05-24 15:33:50 -0700960
961 # Install a flow with wildcards
962 self.installFlow(999, of_ports[0], of_ports[1],
963 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700964 self.verifyFlow(of_ports[0], of_ports[1])
Ken Chiang38d7a152012-05-24 15:33:50 -0700965 # Install a flow with no wildcards for our packet
966 self.installFlow(1000, of_ports[0], of_ports[2], wildcards=0)
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700967 self.verifyFlow(of_ports[0], of_ports[2])
Ken Chiang38d7a152012-05-24 15:33:50 -0700968 # Install a flow with wildcards for our packet with higher
969 # priority
970 self.installFlow(1001, of_ports[0], of_ports[3])
971 self.verifyFlow(of_ports[0], of_ports[3])
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700972
973
Ken Chiang38d7a152012-05-24 15:33:50 -0700974class WildcardPriority2(SingleWildcardMatchPriority):
975 """
976 1. Add exact match flow, verify packet received.
977 2. Add wildcard flow with higher priority, verify packet received on port
978 specified by this flow.
979 3. Add exact match flow with even higher priority, verify packet received
980 on port specified by this flow.
981 4. Delete lowest priority flow, verify packet received on port specified
982 by highest priority flow.
983 5. Delete highest priority flow, verify packet received on port specified
984 by remaining flow.
985 """
986
987 def runTest(self):
988
989 self._Init()
990
991 of_ports = pa_port_map.keys()
992 of_ports.sort()
993
994 self._ClearTable()
995
996 # Install an exact match flow
997 self.installFlow(250, of_ports[0], of_ports[1], wildcards=0)
998 self.verifyFlow(of_ports[0], of_ports[1])
999 # Install a flow with wildcards of higher priority
1000 self.installFlow(1250, of_ports[0], of_ports[2],
1001 wildcards=ofp.OFPFW_DL_DST)
1002 self.verifyFlow(of_ports[0], of_ports[2])
1003 # Install an exact match flow with even higher priority
1004 self.installFlow(2001, of_ports[0], of_ports[3], wildcards=0)
1005 self.verifyFlow(of_ports[0], of_ports[3])
1006 # Delete lowest priority flow
1007 self.removeFlow(250)
1008 self.verifyFlow(of_ports[0], of_ports[3])
1009 # Delete highest priority flow
1010 self.removeFlow(2001)
1011 self.verifyFlow(of_ports[0], of_ports[2])
1012
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001013
Dan Talayco551befa2010-07-15 17:05:32 -07001014class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001015 """
1016 Exercise wildcard matching for all ports
1017
1018 Generate a packet
1019 Generate and install a matching flow with wildcard mask
1020 Add action to forward to a port
1021 Send the packet to the port
1022 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001023 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001024 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001025 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -07001026 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001027 for wc in WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -07001028 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001029 # Set nonzero VLAN id to avoid sending priority-tagged packet
1030 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001031 else:
1032 dl_vlan = -1
1033 flow_match_test(self, pa_port_map, wildcards=wc,
1034 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001035
Dan Talayco551befa2010-07-15 17:05:32 -07001036class SingleWildcardMatchTagged(BaseMatchCase):
1037 """
1038 SingleWildcardMatch with tagged packets
1039 """
1040 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001041 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001042 for wc in WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -07001043 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -07001044 max_test=10)
1045
1046class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001047 """
Dan Talayco80b54ed2010-07-13 09:48:35 -07001048 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001049
1050 Generate a packet
1051 Generate and install a matching flow with wildcard all except one filed
1052 Add action to forward to a port
1053 Send the packet to the port
1054 Verify the packet is received at all other ports (one port at a time)
1055 Verify flow_expiration message is correct when command option is set
1056 """
1057 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -07001058 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001059 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -07001060 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001061 # Set nonzero VLAN id to avoid sending priority-tagged packet
1062 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001063 else:
1064 dl_vlan = -1
1065 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
1066 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001067
Dan Talayco551befa2010-07-15 17:05:32 -07001068class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1069 """
1070 Match one field with tagged packets
1071 """
1072 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001073 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001074 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -07001075 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
1076 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001077
1078class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001079 """
1080 Create Wildcard-all flow and exercise for all ports
1081
1082 Generate a packet
1083 Generate and install a matching flow with wildcard-all
1084 Add action to forward to a port
1085 Send the packet to the port
1086 Verify the packet is received at all other ports (one port at a time)
1087 Verify flow_expiration message is correct when command option is set
1088 """
1089 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -07001090 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001091
Dan Talayco551befa2010-07-15 17:05:32 -07001092class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001093 """
Dan Talayco551befa2010-07-15 17:05:32 -07001094 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001095 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001096 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001097 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -07001098 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
1099 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001100
Dan Talaycoba3745c2010-07-21 21:51:08 -07001101
Dan Talayco551befa2010-07-15 17:05:32 -07001102class AddVLANTag(BaseMatchCase):
1103 """
1104 Add a VLAN tag to an untagged packet
1105 """
1106 def runTest(self):
1107 new_vid = 2
1108 sup_acts = supported_actions_get(self)
1109 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001110 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001111 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001112
Dan Talayco551befa2010-07-15 17:05:32 -07001113 len = 100
1114 len_w_vid = 104
1115 pkt = simple_tcp_packet(pktlen=len)
1116 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1117 dl_vlan=new_vid)
1118 vid_act = action.action_set_vlan_vid()
1119 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001120
Dan Talayco551befa2010-07-15 17:05:32 -07001121 flow_match_test(self, pa_port_map, pkt=pkt,
1122 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001123
Dan Talayco551befa2010-07-15 17:05:32 -07001124class PacketOnly(basic.DataPlaneOnly):
1125 """
1126 Just send a packet thru the switch
1127 """
1128 def runTest(self):
1129 pkt = simple_tcp_packet()
1130 of_ports = pa_port_map.keys()
1131 of_ports.sort()
1132 ing_port = of_ports[0]
1133 pa_logger.info("Sending packet to " + str(ing_port))
1134 pa_logger.debug("Data: " + str(pkt).encode('hex'))
1135 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001136
Dan Talayco551befa2010-07-15 17:05:32 -07001137class PacketOnlyTagged(basic.DataPlaneOnly):
1138 """
1139 Just send a packet thru the switch
1140 """
1141 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001142 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001143 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
1144 of_ports = pa_port_map.keys()
1145 of_ports.sort()
1146 ing_port = of_ports[0]
1147 pa_logger.info("Sending packet to " + str(ing_port))
1148 pa_logger.debug("Data: " + str(pkt).encode('hex'))
1149 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001150
Dan Talayco551befa2010-07-15 17:05:32 -07001151test_prio["PacketOnly"] = -1
1152test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001153
Dan Talayco551befa2010-07-15 17:05:32 -07001154class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001155 """
1156 Modify the VLAN ID in the VLAN tag of a tagged packet
1157 """
Dan Talayco551befa2010-07-15 17:05:32 -07001158 def runTest(self):
1159 old_vid = 2
1160 new_vid = 3
1161 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001162 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001163 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001164 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001165
Dan Talayco551befa2010-07-15 17:05:32 -07001166 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1167 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
1168 vid_act = action.action_set_vlan_vid()
1169 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001170
Dan Talayco551befa2010-07-15 17:05:32 -07001171 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1172 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001173
Ken Chiange9a211d2012-04-20 14:52:11 -07001174class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1175 """
1176 With vlan ID and priority wildcarded, perform SET_VLAN_VID action.
1177 The same flow should match on both untagged and tagged packets.
1178 """
1179 def runTest(self):
1180 old_vid = 2
1181 new_vid = 3
1182 sup_acts = supported_actions_get(self)
1183 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1184 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1185 return
1186
1187 of_ports = pa_port_map.keys()
1188 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1189 ing_port = of_ports[0]
1190 egr_ports = of_ports[1]
1191
1192 rv = delete_all_flows(self.controller, pa_logger)
1193 self.assertEqual(rv, 0, "Failed to delete all flows")
1194
1195 len_untagged = 100
1196 len_w_vid = 104
1197 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1198 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
1199 dl_vlan_enable=True, dl_vlan=old_vid)
1200 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1201 dl_vlan=new_vid)
1202 wildcards=ofp.OFPFW_DL_VLAN|ofp.OFPFW_DL_VLAN_PCP
1203 vid_act = action.action_set_vlan_vid()
1204 vid_act.vlan_vid = new_vid
1205 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
1206 wildcards=wildcards, egr_ports=egr_ports,
1207 action_list=[vid_act])
1208 flow_msg_install(self, request)
1209
1210 pa_logger.debug("Send untagged packet: " + str(ing_port) + " to " +
1211 str(egr_ports))
1212 self.dataplane.send(ing_port, str(untagged_pkt))
1213 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1214
1215 pa_logger.debug("Send tagged packet: " + str(ing_port) + " to " +
1216 str(egr_ports))
1217 self.dataplane.send(ing_port, str(tagged_pkt))
1218 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1219
Howard Pershc1199d52012-04-11 14:21:32 -07001220class ModifyVlanPcp(BaseMatchCase):
1221 """
1222 Modify the priority field of the VLAN tag of a tagged packet
1223 """
1224 def runTest(self):
1225 vid = 123
1226 old_vlan_pcp = 2
1227 new_vlan_pcp = 3
1228 sup_acts = supported_actions_get(self)
1229 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1230 skip_message_emit(self, "Modify VLAN tag test")
1231 return
1232
1233 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1234 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1235 vid_act = action.action_set_vlan_pcp()
1236 vid_act.vlan_pcp = new_vlan_pcp
1237
1238 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1239 action_list=[vid_act])
1240
Dan Talayco551befa2010-07-15 17:05:32 -07001241class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001242 """
1243 Strip the VLAN tag from a tagged packet
1244 """
Dan Talayco551befa2010-07-15 17:05:32 -07001245 def runTest(self):
1246 old_vid = 2
1247 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001248 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001249 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001250 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001251
Dan Talayco551befa2010-07-15 17:05:32 -07001252 len_w_vid = 104
1253 len = 100
1254 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1255 dl_vlan=old_vid)
1256 exp_pkt = simple_tcp_packet(pktlen=len)
1257 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001258
Dan Talayco551befa2010-07-15 17:05:32 -07001259 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1260 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001261
Ken Chiange9a211d2012-04-20 14:52:11 -07001262class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1263 """
1264 Strip the VLAN tag from a tagged packet.
1265 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1266 """
1267 def runTest(self):
1268 old_vid = 2
1269 sup_acts = supported_actions_get(self)
1270 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1271 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1272 return
1273
1274 len_w_vid = 104
1275 len_untagged = 100
1276 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1277 dl_vlan=old_vid)
1278 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
1279 vid_act = action.action_strip_vlan()
1280
1281 flow_match_test(self, pa_port_map,
1282 wildcards=ofp.OFPFW_DL_VLAN|ofp.OFPFW_DL_VLAN_PCP,
1283 pkt=pkt, exp_pkt=exp_pkt,
1284 action_list=[vid_act])
1285
Dan Talayco4b2bee62010-07-20 14:10:05 -07001286def init_pkt_args():
1287 """
1288 Pass back a dictionary with default packet arguments
1289 """
1290 args = {}
1291 args["dl_src"] = '00:23:45:67:89:AB'
1292
1293 dl_vlan_enable=False
1294 dl_vlan=-1
1295 if pa_config["test-params"]["vid"]:
1296 dl_vlan_enable=True
1297 dl_vlan = pa_config["test-params"]["vid"]
1298
1299# Unpack operator is ** on a dictionary
1300
1301 return args
1302
Dan Talayco551befa2010-07-15 17:05:32 -07001303class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001304 """
1305 Modify the source MAC address (TP1)
1306 """
Dan Talayco551befa2010-07-15 17:05:32 -07001307 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001308 sup_acts = supported_actions_get(self)
1309 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001310 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001311 return
1312
1313 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1314 check_test_params=True)
1315 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1316 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001317
Dan Talayco551befa2010-07-15 17:05:32 -07001318class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001319 """
1320 Modify the dest MAC address (TP1)
1321 """
Dan Talayco551befa2010-07-15 17:05:32 -07001322 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001323 sup_acts = supported_actions_get(self)
1324 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001325 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001326 return
1327
1328 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1329 check_test_params=True)
1330 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1331 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001332
Dan Talayco551befa2010-07-15 17:05:32 -07001333class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001334 """
1335 Modify the source IP address of an IP packet (TP1)
1336 """
Dan Talayco551befa2010-07-15 17:05:32 -07001337 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001338 sup_acts = supported_actions_get(self)
1339 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001340 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001341 return
1342
1343 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1344 check_test_params=True)
1345 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1346 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001347
Dan Talayco551befa2010-07-15 17:05:32 -07001348class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001349 """
1350 Modify the dest IP address of an IP packet (TP1)
1351 """
Dan Talayco551befa2010-07-15 17:05:32 -07001352 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001353 sup_acts = supported_actions_get(self)
1354 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001355 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001356 return
1357
1358 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1359 check_test_params=True)
1360 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1361 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001362
1363class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001364 """
1365 Modify the source TCP port of a TCP packet (TP1)
1366 """
Dan Talayco551befa2010-07-15 17:05:32 -07001367 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001368 sup_acts = supported_actions_get(self)
1369 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001370 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001371 return
1372
1373 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1374 check_test_params=True)
1375 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1376 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001377
1378class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001379 """
1380 Modify the dest TCP port of a TCP packet (TP1)
1381 """
Dan Talayco551befa2010-07-15 17:05:32 -07001382 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001383 sup_acts = supported_actions_get(self)
1384 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001385 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001386 return
1387
1388 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1389 check_test_params=True)
1390 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1391 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001392
1393class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001394 """
1395 Modify the IP type of service of an IP packet (TP1)
1396 """
Dan Talayco551befa2010-07-15 17:05:32 -07001397 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001398 sup_acts = supported_actions_get(self)
1399 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001400 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001401 return
Dan Talayco551befa2010-07-15 17:05:32 -07001402
Dan Talayco4b2bee62010-07-20 14:10:05 -07001403 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1404 check_test_params=True)
1405 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001406 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001407
Dan Talaycof6e76c02012-03-23 10:56:12 -07001408class ModifyL2DstMC(BaseMatchCase):
1409 """
1410 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001411 """
1412 def runTest(self):
1413 sup_acts = supported_actions_get(self)
1414 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001415 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001416 return
1417
Dan Talaycof6e76c02012-03-23 10:56:12 -07001418 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1419 check_test_params=True)
1420 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001421 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001422
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001423class ModifyL2DstIngress(BaseMatchCase):
1424 """
1425 Modify the L2 dest and send to the ingress port
1426 """
1427 def runTest(self):
1428 sup_acts = supported_actions_get(self)
1429 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001430 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001431 return
1432
1433 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1434 check_test_params=True)
1435 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1436 action_list=acts, max_test=2, egr_count=0,
1437 ing_port=True)
1438
Dan Talaycod8ae7582012-03-23 12:24:56 -07001439class ModifyL2DstIngressMC(BaseMatchCase):
1440 """
1441 Modify the L2 dest and send to the ingress port
1442 """
1443 def runTest(self):
1444 sup_acts = supported_actions_get(self)
1445 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1446 skip_message_emit(self, "ModifyL2dstMC test")
1447 return
1448
1449 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1450 check_test_params=True)
1451 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1452 action_list=acts, max_test=2, egr_count=-1,
1453 ing_port=True)
1454
Dan Talaycof6e76c02012-03-23 10:56:12 -07001455class ModifyL2SrcMC(BaseMatchCase):
1456 """
1457 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001458 """
1459 def runTest(self):
1460 sup_acts = supported_actions_get(self)
1461 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001462 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001463 return
1464
Dan Talaycof6e76c02012-03-23 10:56:12 -07001465 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1466 check_test_params=True)
1467 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001468 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001469
1470class ModifyL2SrcDstMC(BaseMatchCase):
1471 """
1472 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001473 """
1474 def runTest(self):
1475 sup_acts = supported_actions_get(self)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001476 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1477 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1478 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001479 return
1480
Dan Talaycof6e76c02012-03-23 10:56:12 -07001481 mod_fields = ['dl_dst', 'dl_src']
1482 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1483 check_test_params=True)
1484 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001485 action_list=acts, max_test=2, egr_count=-1)
1486
1487class ModifyL2DstVIDMC(BaseMatchCase):
1488 """
1489 Modify the L2 dest and send to 2 ports
1490 """
1491 def runTest(self):
1492 sup_acts = supported_actions_get(self)
1493 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1494 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1495 skip_message_emit(self, "ModifyL2DstVIDMC test")
1496 return
1497
1498 mod_fields = ['dl_dst', 'dl_vlan']
1499 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1500 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1501 check_test_params=True)
1502 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1503 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001504
Dan Talaycofa6454f2012-04-05 10:04:13 -07001505class FlowToggle(BaseMatchCase):
1506 """
1507 Add flows to the table and modify them repeatedly
1508 """
1509 def runTest(self):
Dan Talayco50be7672012-04-05 11:38:08 -07001510 flow_count = test_param_get(self.config, 'ft_flow_count', default=20)
1511 iter_count = test_param_get(self.config, 'ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001512
1513 pa_logger.info("Running flow toggle with %d flows, %d iterations" %
1514 (flow_count, iter_count))
1515 acts = []
1516 acts.append(action.action_output())
1517 acts.append(action.action_output())
1518
1519 of_ports = pa_port_map.keys()
1520 if len(of_ports) < 3:
1521 self.assertTrue(False, "Too few ports for test")
1522
1523 for idx in range(2):
1524 acts[idx].port = of_ports[idx]
1525
1526 flows = []
1527 flows.append([])
1528 flows.append([])
1529
Dan Talayco50be7672012-04-05 11:38:08 -07001530 wildcards = ofp.OFPFW_DL_SRC | ofp.OFPFW_DL_DST
Dan Talaycofa6454f2012-04-05 10:04:13 -07001531 # Create up the flows in an array
1532 for toggle in range(2):
1533 for f_idx in range(flow_count):
1534 pkt = simple_tcp_packet(tcp_sport=f_idx)
1535 msg = message.flow_mod()
1536 match = parse.packet_to_flow_match(pkt)
1537 match.in_port = of_ports[3]
Dan Talayco50be7672012-04-05 11:38:08 -07001538 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001539 msg.match = match
1540 msg.buffer_id = 0xffffffff
1541 msg.actions.add(acts[toggle])
1542 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001543
1544 # Show two sample flows
1545 pa_logger.debug(flows[0][0].show())
1546 pa_logger.debug(flows[1][0].show())
1547
Dan Talaycofa6454f2012-04-05 10:04:13 -07001548 # Install the first set of flows
1549 for f_idx in range(flow_count):
1550 rv = self.controller.message_send(flows[0][f_idx])
1551 self.assertTrue(rv != -1, "Error installing flow %d" % f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001552 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycofa6454f2012-04-05 10:04:13 -07001553
1554 pa_logger.info("Installed %d flows" % flow_count)
1555
1556 # Repeatedly modify all the flows back and forth
1557 updates = 0
1558 # Report status about 5 times
1559 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001560 start = time.time()
1561 for iter_idx in range(iter_count):
1562 if not iter_idx % mod_val:
1563 pa_logger.info("Flow Toggle: iter %d of %d. " %
1564 (iter_idx, iter_count) +
1565 "%d updates in %d secs" %
1566 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001567 for toggle in range(2):
1568 t_idx = 1 - toggle
1569 for f_idx in range(flow_count):
1570 rv = self.controller.message_send(flows[t_idx][f_idx])
1571 updates += 1
1572 self.assertTrue(rv != -1, "Error modifying flow %d" %
1573 f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001574 self.assertEqual(do_barrier(self.controller), 0,
1575 "Barrier failed")
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001576
1577 end = time.time()
1578 divisor = end - start or (end - start + 1)
1579 pa_logger.info("Flow toggle: %d iterations" % iter_count)
1580 pa_logger.info(" %d flow mods in %d secs, %d mods/sec" %
1581 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001582
1583
Dan Talayco8a64e332012-03-28 14:53:20 -07001584# You can pick and choose these by commenting tests in or out
1585iter_classes = [
1586 basic.PacketIn,
1587 basic.PacketOut,
1588 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001589 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001590 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001591 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001592 AllWildcardMatch,
1593 AllWildcardMatchTagged,
1594 SingleWildcardMatch,
1595 SingleWildcardMatchTagged,
1596 ExactMatch,
1597 ExactMatchTagged,
1598 SingleWildcardMatch,
1599 ModifyL2Src,
1600 ModifyL2Dst,
1601 ModifyL2SrcMC,
1602 ModifyL2DstMC,
1603 ModifyL2SrcDstMC
1604 ]
1605
1606class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001607 """
1608 Iterate over a bunch of test cases
1609
1610 The cases come from the list above
1611 """
1612
Dan Talayco8a64e332012-03-28 14:53:20 -07001613 def runTest(self):
1614 count = test_param_get(self.config, 'iter_count', default=10)
1615 tests_done = 0
1616 pa_logger.info("Running iteration test " + str(count) + " times")
1617 start = time.time()
1618 last = start
1619 for idx in range(count):
1620 pa_logger.info("Iteration " + str(idx + 1))
1621 for cls in iter_classes:
1622 test = cls()
1623 test.inheritSetup(self)
1624 test.runTest()
1625 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001626 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001627 if time.time() - last > 60:
1628 last = time.time()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001629 pa_logger.info(
1630 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1631 (idx, count, tests_done, last - start) +
1632 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001633 stats = all_stats_get(self)
1634 last = time.time()
1635 pa_logger.info("\nIterCases ran %d tests in %d seconds." %
1636 (tests_done, last - start))
1637 pa_logger.info(" flows: %d. packets: %d. bytes: %d" %
1638 (stats["flows"], stats["packets"], stats["bytes"]))
1639 pa_logger.info(" active: %d. lookups: %d. matched %d." %
1640 (stats["active"], stats["lookups"], stats["matched"]))
1641
1642# Don't run by default
1643test_prio["IterCases"] = -1
Dan Talaycof6e76c02012-03-23 10:56:12 -07001644
Dan Talayco4b2bee62010-07-20 14:10:05 -07001645#@todo Need to implement tagged versions of the above tests
1646#
1647#@todo Implement a test case that strips tag 2, adds tag 3
1648# and modifies tag 4 to tag 5. Then verify (in addition) that
1649# tag 6 does not get modified.
1650
1651class MixedVLAN(BaseMatchCase):
1652 """
1653 Test mixture of VLAN tag actions
1654
1655 Strip tag 2 on port 1, send to port 2
1656 Add tag 3 on port 1, send to port 2
1657 Modify tag 4 to 5 on port 1, send to port 2
1658 All other traffic from port 1, send to port 3
1659 All traffic from port 2 sent to port 4
1660 Use exact matches with different packets for all mods
1661 Verify the following: (port, vid)
1662 (port 1, vid 2) => VLAN tag stripped, out port 2
1663 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1664 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1665 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1666 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1667 (port 2, no tag) => untagged packet out port 4
1668 (port 2, vid 2-6) => unmodified packet out port 4
1669
1670 Variation: Might try sending VID 5 to port 3 and check.
1671 If only VID 5 distinguishes pkt, this will fail on some platforms
1672 """
1673
1674test_prio["MixedVLAN"] = -1
1675
Dan Talayco551befa2010-07-15 17:05:32 -07001676def supported_actions_get(parent, use_cache=True):
1677 """
1678 Get the bitmap of supported actions from the switch
1679 If use_cache is false, the cached value will be updated
1680 """
1681 global cached_supported_actions
1682 if cached_supported_actions is None or not use_cache:
1683 request = message.features_request()
1684 (reply, pkt) = parent.controller.transact(request, timeout=2)
1685 parent.assertTrue(reply is not None, "Did not get response to ftr req")
1686 cached_supported_actions = reply.actions
1687 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
1688
1689 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -07001690
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001691if __name__ == "__main__":
1692 print "Please run through oft script: ./oft --test_spec=basic"