blob: 1b9f9d33f406fbe3658fb98a5c3fad82b5899d63 [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
287 # Get current stats for selected egress queue again
288
289 request = message.queue_stats_request()
290 request.port_no = egress_port
291 request.queue_id = egress_queue_id
Ed Swierk065a2db2012-04-17 16:35:52 -0700292 (qs_after, p) = self.controller.transact(request, timeout=2)
Howard Persh670b5672012-04-13 09:08:29 -0700293 self.assertNotEqual(qs_after, None, "Queue stats request failed")
294
295 # Make sure that tx packet counter for selected egress queue was
296 # incremented
297
298 self.assertEqual(qs_after.stats.stats[0].tx_packets, \
299 qs_before.stats.stats[0].tx_packets + 1, \
300 "Verification of egress queue tx packet count failed"
301 )
302
303
Howard Pershf97840f2012-04-10 16:30:42 -0700304
305
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700306class DirectPacketICMP(DirectPacket):
307 """
308 Send ICMP packet to single egress port
309
310 Generate a ICMP packet
311 Generate and install a matching flow
312 Add action to direct the packet to an egress port
313 Send the packet to ingress dataplane port
314 Verify the packet is received at the egress port only
315 Difference from DirectPacket test is that sent packet is ICMP
316 """
317 def runTest(self):
318 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700319
320class DirectTwoPorts(basic.SimpleDataPlane):
321 """
322 Send packet to two egress ports
323
324 Generate a packet
325 Generate and install a matching flow
326 Add action to direct the packet to two egress ports
327 Send the packet to ingress dataplane port
328 Verify the packet is received at the two egress ports
329 """
330 def runTest(self):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700331 of_ports = pa_port_map.keys()
332 of_ports.sort()
333 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
334
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700335 pkt = simple_tcp_packet()
336 match = parse.packet_to_flow_match(pkt)
337 match.wildcards &= ~ofp.OFPFW_IN_PORT
338 self.assertTrue(match is not None,
339 "Could not generate flow match from pkt")
340 act = action.action_output()
341
342 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700343 rv = delete_all_flows(self.controller, pa_logger)
344 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700345
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700346 ingress_port = of_ports[idx]
347 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
348 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
349 pa_logger.info("Ingress " + str(ingress_port) +
350 " to egress " + str(egress_port1) + " and " +
351 str(egress_port2))
352
353 match.in_port = ingress_port
354
355 request = message.flow_mod()
356 request.match = match
357 request.buffer_id = 0xffffffff
358 act.port = egress_port1
359 self.assertTrue(request.actions.add(act), "Could not add action1")
360 act.port = egress_port2
361 self.assertTrue(request.actions.add(act), "Could not add action2")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700362 # pa_logger.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700363
364 pa_logger.info("Inserting flow")
365 rv = self.controller.message_send(request)
366 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700367 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700368
369 pa_logger.info("Sending packet to dp port " +
370 str(ingress_port))
371 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700372 yes_ports = set([egress_port1, egress_port2])
373 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700374
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700375 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700376 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700377
378class DirectMCNonIngress(basic.SimpleDataPlane):
379 """
380 Multicast to all non-ingress ports
381
382 Generate a packet
383 Generate and install a matching flow
384 Add action to direct the packet to all non-ingress ports
385 Send the packet to ingress dataplane port
386 Verify the packet is received at all non-ingress ports
387
388 Does not use the flood action
389 """
390 def runTest(self):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700391 of_ports = pa_port_map.keys()
392 of_ports.sort()
393 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
394
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700395 pkt = simple_tcp_packet()
396 match = parse.packet_to_flow_match(pkt)
397 match.wildcards &= ~ofp.OFPFW_IN_PORT
398 self.assertTrue(match is not None,
399 "Could not generate flow match from pkt")
400 act = action.action_output()
401
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700402 for ingress_port in of_ports:
403 rv = delete_all_flows(self.controller, pa_logger)
404 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700405
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700406 pa_logger.info("Ingress " + str(ingress_port) +
407 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700408 match.in_port = ingress_port
409
410 request = message.flow_mod()
411 request.match = match
412 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700413 for egress_port in of_ports:
414 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700415 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700416 act.port = egress_port
417 self.assertTrue(request.actions.add(act),
418 "Could not add output to " + str(egress_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700419 pa_logger.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700420
421 pa_logger.info("Inserting flow")
422 rv = self.controller.message_send(request)
423 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700424 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700425
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700426 pa_logger.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700427 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700428 yes_ports = set(of_ports).difference([ingress_port])
429 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700430 self, pa_logger, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700431
Dan Talayco32fa6542010-05-11 15:54:08 -0700432
433class DirectMC(basic.SimpleDataPlane):
434 """
435 Multicast to all ports including ingress
436
437 Generate a packet
438 Generate and install a matching flow
439 Add action to direct the packet to all non-ingress ports
440 Send the packet to ingress dataplane port
441 Verify the packet is received at all ports
442
443 Does not use the flood action
444 """
445 def runTest(self):
Dan Talayco32fa6542010-05-11 15:54:08 -0700446 of_ports = pa_port_map.keys()
447 of_ports.sort()
448 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
449
Dan Talayco32fa6542010-05-11 15:54:08 -0700450 pkt = simple_tcp_packet()
451 match = parse.packet_to_flow_match(pkt)
452 match.wildcards &= ~ofp.OFPFW_IN_PORT
453 self.assertTrue(match is not None,
454 "Could not generate flow match from pkt")
455 act = action.action_output()
456
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700457 for ingress_port in of_ports:
458 rv = delete_all_flows(self.controller, pa_logger)
459 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700460
Dan Talayco32fa6542010-05-11 15:54:08 -0700461 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700462 match.in_port = ingress_port
463
464 request = message.flow_mod()
465 request.match = match
466 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700467 for egress_port in of_ports:
468 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700469 act.port = ofp.OFPP_IN_PORT
470 else:
471 act.port = egress_port
472 self.assertTrue(request.actions.add(act),
473 "Could not add output to " + str(egress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700474 # pa_logger.info(request.show())
475
476 pa_logger.info("Inserting flow")
477 rv = self.controller.message_send(request)
478 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700479 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2e77a842010-05-12 15:39:46 -0700480
481 pa_logger.info("Sending packet to dp port " + str(ingress_port))
482 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700483 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700484 pa_logger, pa_config)
Dan Talayco2e77a842010-05-12 15:39:46 -0700485
486class Flood(basic.SimpleDataPlane):
487 """
488 Flood to all ports except ingress
489
490 Generate a packet
491 Generate and install a matching flow
492 Add action to flood the packet
493 Send the packet to ingress dataplane port
494 Verify the packet is received at all other ports
495 """
496 def runTest(self):
Dan Talayco2e77a842010-05-12 15:39:46 -0700497 of_ports = pa_port_map.keys()
498 of_ports.sort()
499 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
500
501 pkt = simple_tcp_packet()
502 match = parse.packet_to_flow_match(pkt)
503 match.wildcards &= ~ofp.OFPFW_IN_PORT
504 self.assertTrue(match is not None,
505 "Could not generate flow match from pkt")
506 act = action.action_output()
507
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700508 for ingress_port in of_ports:
509 rv = delete_all_flows(self.controller, pa_logger)
510 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700511
Dan Talayco2e77a842010-05-12 15:39:46 -0700512 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700513 match.in_port = ingress_port
514
515 request = message.flow_mod()
516 request.match = match
517 request.buffer_id = 0xffffffff
518 act.port = ofp.OFPP_FLOOD
519 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700520 "Could not add flood port action")
Dan Talayco32fa6542010-05-11 15:54:08 -0700521 pa_logger.info(request.show())
522
523 pa_logger.info("Inserting flow")
524 rv = self.controller.message_send(request)
525 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700526 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco32fa6542010-05-11 15:54:08 -0700527
528 pa_logger.info("Sending packet to dp port " + str(ingress_port))
529 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700530 yes_ports = set(of_ports).difference([ingress_port])
531 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700532 self, pa_logger, pa_config)
Dan Talayco3be5b062010-05-12 15:46:21 -0700533
Dan Talayco3be5b062010-05-12 15:46:21 -0700534class FloodPlusIngress(basic.SimpleDataPlane):
535 """
536 Flood to all ports plus send to ingress port
537
538 Generate a packet
539 Generate and install a matching flow
540 Add action to flood the packet
541 Add action to send to ingress port
542 Send the packet to ingress dataplane port
543 Verify the packet is received at all other ports
544 """
545 def runTest(self):
Dan Talayco3be5b062010-05-12 15:46:21 -0700546 of_ports = pa_port_map.keys()
547 of_ports.sort()
548 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
549
550 pkt = simple_tcp_packet()
551 match = parse.packet_to_flow_match(pkt)
552 match.wildcards &= ~ofp.OFPFW_IN_PORT
553 self.assertTrue(match is not None,
554 "Could not generate flow match from pkt")
555 act = action.action_output()
556
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700557 for ingress_port in of_ports:
558 rv = delete_all_flows(self.controller, pa_logger)
559 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700560
Dan Talayco3be5b062010-05-12 15:46:21 -0700561 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700562 match.in_port = ingress_port
563
564 request = message.flow_mod()
565 request.match = match
566 request.buffer_id = 0xffffffff
567 act.port = ofp.OFPP_FLOOD
568 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700569 "Could not add flood port action")
570 act.port = ofp.OFPP_IN_PORT
571 self.assertTrue(request.actions.add(act),
572 "Could not add ingress port for output")
573 pa_logger.info(request.show())
574
575 pa_logger.info("Inserting flow")
576 rv = self.controller.message_send(request)
577 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700578 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700579
580 pa_logger.info("Sending packet to dp port " + str(ingress_port))
581 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700582 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700583 pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700584
585class All(basic.SimpleDataPlane):
586 """
587 Send to OFPP_ALL port
588
589 Generate a packet
590 Generate and install a matching flow
591 Add action to forward to OFPP_ALL
592 Send the packet to ingress dataplane port
593 Verify the packet is received at all other ports
594 """
595 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700596 of_ports = pa_port_map.keys()
597 of_ports.sort()
598 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
599
600 pkt = simple_tcp_packet()
601 match = parse.packet_to_flow_match(pkt)
602 match.wildcards &= ~ofp.OFPFW_IN_PORT
603 self.assertTrue(match is not None,
604 "Could not generate flow match from pkt")
605 act = action.action_output()
606
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700607 for ingress_port in of_ports:
608 rv = delete_all_flows(self.controller, pa_logger)
609 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700610
Dan Talayco4aa13122010-05-12 15:54:44 -0700611 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700612 match.in_port = ingress_port
613
614 request = message.flow_mod()
615 request.match = match
616 request.buffer_id = 0xffffffff
617 act.port = ofp.OFPP_ALL
618 self.assertTrue(request.actions.add(act),
619 "Could not add ALL port action")
620 pa_logger.info(request.show())
621
622 pa_logger.info("Inserting flow")
623 rv = self.controller.message_send(request)
624 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700625 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700626
627 pa_logger.info("Sending packet to dp port " + str(ingress_port))
628 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700629 yes_ports = set(of_ports).difference([ingress_port])
630 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700631 self, pa_logger, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700632
633class AllPlusIngress(basic.SimpleDataPlane):
634 """
635 Send to OFPP_ALL port and ingress port
636
637 Generate a packet
638 Generate and install a matching flow
639 Add action to forward to OFPP_ALL
640 Add action to forward to ingress port
641 Send the packet to ingress dataplane port
642 Verify the packet is received at all other ports
643 """
644 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700645 of_ports = pa_port_map.keys()
646 of_ports.sort()
647 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
648
649 pkt = simple_tcp_packet()
650 match = parse.packet_to_flow_match(pkt)
651 match.wildcards &= ~ofp.OFPFW_IN_PORT
652 self.assertTrue(match is not None,
653 "Could not generate flow match from pkt")
654 act = action.action_output()
655
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700656 for ingress_port in of_ports:
657 rv = delete_all_flows(self.controller, pa_logger)
658 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700659
Dan Talayco4aa13122010-05-12 15:54:44 -0700660 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700661 match.in_port = ingress_port
662
663 request = message.flow_mod()
664 request.match = match
665 request.buffer_id = 0xffffffff
666 act.port = ofp.OFPP_ALL
667 self.assertTrue(request.actions.add(act),
668 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700669 act.port = ofp.OFPP_IN_PORT
670 self.assertTrue(request.actions.add(act),
671 "Could not add ingress port for output")
672 pa_logger.info(request.show())
673
674 pa_logger.info("Inserting flow")
675 rv = self.controller.message_send(request)
676 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700677 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco3be5b062010-05-12 15:46:21 -0700678
679 pa_logger.info("Sending packet to dp port " + str(ingress_port))
680 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700681 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700682 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700683
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700684class FloodMinusPort(basic.SimpleDataPlane):
685 """
686 Config port with No_Flood and test Flood action
687
688 Generate a packet
689 Generate a matching flow
690 Add action to forward to OFPP_ALL
691 Set port to no-flood
692 Send the packet to ingress dataplane port
693 Verify the packet is received at all other ports except
694 the ingress port and the no_flood port
695 """
696 def runTest(self):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700697 of_ports = pa_port_map.keys()
698 of_ports.sort()
699 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
700
701 pkt = simple_tcp_packet()
702 match = parse.packet_to_flow_match(pkt)
703 match.wildcards &= ~ofp.OFPFW_IN_PORT
704 self.assertTrue(match is not None,
705 "Could not generate flow match from pkt")
706 act = action.action_output()
707
708 for idx in range(len(of_ports)):
709 rv = delete_all_flows(self.controller, pa_logger)
710 self.assertEqual(rv, 0, "Failed to delete all flows")
711
712 ingress_port = of_ports[idx]
713 no_flood_idx = (idx + 1) % len(of_ports)
714 no_flood_port = of_ports[no_flood_idx]
715 rv = port_config_set(self.controller, no_flood_port,
716 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
717 pa_logger)
718 self.assertEqual(rv, 0, "Failed to set port config")
719
720 match.in_port = ingress_port
721
722 request = message.flow_mod()
723 request.match = match
724 request.buffer_id = 0xffffffff
725 act.port = ofp.OFPP_FLOOD
726 self.assertTrue(request.actions.add(act),
727 "Could not add flood port action")
728 pa_logger.info(request.show())
729
730 pa_logger.info("Inserting flow")
731 rv = self.controller.message_send(request)
732 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700733 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700734
735 pa_logger.info("Sending packet to dp port " + str(ingress_port))
736 pa_logger.info("No flood port is " + str(no_flood_port))
737 self.dataplane.send(ingress_port, str(pkt))
738 no_ports = set([ingress_port, no_flood_port])
739 yes_ports = set(of_ports).difference(no_ports)
740 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700741 pa_logger, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700742
743 # Turn no flood off again
744 rv = port_config_set(self.controller, no_flood_port,
745 0, ofp.OFPPC_NO_FLOOD, pa_logger)
746 self.assertEqual(rv, 0, "Failed to reset port config")
747
748 #@todo Should check no other packets received
749
Dan Talayco21381562010-07-17 00:34:47 -0700750
751
Dan Talayco551befa2010-07-15 17:05:32 -0700752################################################################
753
754class BaseMatchCase(basic.SimpleDataPlane):
755 def setUp(self):
756 basic.SimpleDataPlane.setUp(self)
757 self.logger = pa_logger
758 def runTest(self):
759 self.logger.info("BaseMatchCase")
760
761class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700762 """
Dan Talayco551befa2010-07-15 17:05:32 -0700763 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700764
765 Generate a packet
766 Generate and install a matching flow without wildcard mask
767 Add action to forward to a port
768 Send the packet to the port
769 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700770 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700771
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700772 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700773 flow_match_test(self, pa_port_map)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700774
Dan Talayco551befa2010-07-15 17:05:32 -0700775class ExactMatchTagged(BaseMatchCase):
776 """
777 Exact match for all port pairs with tagged pkts
778 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700779
Dan Talayco551befa2010-07-15 17:05:32 -0700780 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700781 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700782 flow_match_test(self, pa_port_map, dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700783
Dan Talayco551befa2010-07-15 17:05:32 -0700784class ExactMatchTaggedMany(BaseMatchCase):
785 """
786 ExactMatchTagged with many VLANS
787 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700788
Dan Talayco551befa2010-07-15 17:05:32 -0700789 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700790 for vid in range(2,100,10):
Dan Talayco551befa2010-07-15 17:05:32 -0700791 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
792 for vid in range(100,4000,389):
793 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
794 flow_match_test(self, pa_port_map, dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700795
Dan Talayco551befa2010-07-15 17:05:32 -0700796# Don't run by default
797test_prio["ExactMatchTaggedMany"] = -1
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700798
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700799
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700800class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700801 """
802 SingleWildcardMatchPriority
803 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700804
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700805 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700806 self.pkt = simple_tcp_packet()
807 self.flowMsgs = {}
808
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700809 def _ClearTable(self):
810 rc = delete_all_flows(self.controller, self.logger)
811 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700812 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700813
814 def runTest(self):
815
816 self._Init()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700817 of_ports = pa_port_map.keys()
818 of_ports.sort()
819
820 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700821 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700822
823 # Run several combinations, each at lower priority settings.
824 # At the end of each call to runPrioFlows(), the table should
825 # be empty. If its not, we'll catch it as the priorities decreases
826 portA = of_ports[0]
827 portB = of_ports[1]
828 portC = of_ports[2]
829
830 # TODO -- these priority numbers should be validated somehow?
831 self.runPrioFlows(portA, portB, portC, 1000, 999)
832 self.runPrioFlows(portB, portC, portA, 998, 997)
833 self.runPrioFlows(portC, portA, portB, 996, 995)
834 self.runPrioFlows(portA, portC, portB, 994, 993)
835
836
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700837
838 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
839 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700840
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700841 if clearTable:
842 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700843
844 # Sanity check flow at lower priority from pA to pB
845 self.logger.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
846 % (portA, portB, portC, prioHigher, prioLower))
847
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700848 self.installFlow(prioHigher, portA, portC)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700849 self.installFlow(prioLower, portA, portB)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700850
851 return
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700852 self.verifyFlow(portA, portB)
853 self.removeFlow(prioLower)
854 # Sanity check flow at lower priority from pA to pC
855 self.installFlow(prioLower, portA, portC)
856 self.verifyFlow(portA, portC)
857 self.removeFlow(prioLower)
858
859 # Install and verify pA->pB @ prioLower
860 self.installFlow(prioLower, portA, portB)
861 self.verifyFlow(portA, portB)
862
863 # Install and verify pA->pC @ prioHigher, should override pA->pB
864 self.installFlow(prioHigher, portA, portC)
865 self.verifyFlow(portA, portC)
866 # remove pA->pC
867 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700868 # Old flow pA -> pB @ prioLower should still be active
869 self.verifyFlow(portA, portB)
870 self.removeFlow(prioLower)
871
872 # Table should be empty at this point, leave it alone as
873 # an assumption for future test runs
874
875
876
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700877 def installFlow(self, prio, inp, egp,
878 wildcards=ofp.OFPFW_DL_SRC):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700879 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700880 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700881 egr_ports=egp)
882 request.priority = prio
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700883 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700884 self.flowMsgs[prio] = request
885
886 def removeFlow(self, prio):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700887 return
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700888 if self.flowMsgs.has_key(prio):
889 msg = self.flowMsgs[prio]
890 msg.command = ofp.OFPFC_DELETE_STRICT
891 # This *must* be set for DELETE
892 msg.out_port = ofp.OFPP_NONE
893 self.controller.message_send(msg)
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700894 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700895 else:
896 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700897
898
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700899 def verifyFlow(self, inp, egp, pkt=None):
900 if pkt == None:
901 pkt = self.pkt
902
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700903 self.logger.info("Pkt match test: " + str(inp) +
904 " to " + str(egp))
905 self.logger.debug("Send packet: " + str(inp) + " to "
906 + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700907 self.dataplane.send(inp, str(pkt))
908 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700909
910
911
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700912class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
913
914 def runTest(self):
915
916 self._Init()
917
918 of_ports = pa_port_map.keys()
919 of_ports.sort()
920
921 # Install an entry from 0 -> 1 @ prio 1000
922 self._ClearTable()
923 self.installFlow(1000, of_ports[0], of_ports[1])
924 self.verifyFlow(of_ports[0], of_ports[1])
925 self.installFlow(1000, of_ports[1], of_ports[0])
926 self.verifyFlow(of_ports[1], of_ports[0])
927 self.installFlow(1001, of_ports[0], of_ports[1])
928 self.verifyFlow(of_ports[0], of_ports[1])
929 self.installFlow(1001, of_ports[1], of_ports[0])
930 self.verifyFlow(of_ports[1], of_ports[0])
931 self.removeFlow(1001)
932 self.verifyFlow(of_ports[0], of_ports[1])
933 self.removeFlow(1000)
934
935
936
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700937class WildcardPriority(SingleWildcardMatchPriority):
938
939 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700940
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700941 self._Init()
942
943 of_ports = pa_port_map.keys()
944 of_ports.sort()
945
946 self._ClearTable()
947 # Install a flow with no wildcards for our packet:
948 self.installFlow(1000, of_ports[0], of_ports[1], wildcards=0)
949 self.verifyFlow(of_ports[0], of_ports[1])
950 # Install a flow with wildcards for our packet with higher
951 # priority.
952 self.installFlow(1001, of_ports[0], of_ports[2])
953 self.verifyFlow(of_ports[0], of_ports[2])
954
955
956
Dan Talayco551befa2010-07-15 17:05:32 -0700957class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700958 """
959 Exercise wildcard matching for all ports
960
961 Generate a packet
962 Generate and install a matching flow with wildcard mask
963 Add action to forward to a port
964 Send the packet to the port
965 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700966 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700967 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700968 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -0700969 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700970 for wc in WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -0700971 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -0700972 # Set nonzero VLAN id to avoid sending priority-tagged packet
973 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -0700974 else:
975 dl_vlan = -1
976 flow_match_test(self, pa_port_map, wildcards=wc,
977 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700978
Dan Talayco551befa2010-07-15 17:05:32 -0700979class SingleWildcardMatchTagged(BaseMatchCase):
980 """
981 SingleWildcardMatch with tagged packets
982 """
983 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700984 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700985 for wc in WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700986 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -0700987 max_test=10)
988
989class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700990 """
Dan Talayco80b54ed2010-07-13 09:48:35 -0700991 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700992
993 Generate a packet
994 Generate and install a matching flow with wildcard all except one filed
995 Add action to forward to a port
996 Send the packet to the port
997 Verify the packet is received at all other ports (one port at a time)
998 Verify flow_expiration message is correct when command option is set
999 """
1000 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -07001001 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001002 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Dan Talayco4431d542012-03-21 16:42:16 -07001003 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001004 # Set nonzero VLAN id to avoid sending priority-tagged packet
1005 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001006 else:
1007 dl_vlan = -1
1008 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
1009 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001010
Dan Talayco551befa2010-07-15 17:05:32 -07001011class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1012 """
1013 Match one field with tagged packets
1014 """
1015 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001016 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001017 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -07001018 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
1019 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001020
1021class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001022 """
1023 Create Wildcard-all flow and exercise for all ports
1024
1025 Generate a packet
1026 Generate and install a matching flow with wildcard-all
1027 Add action to forward to a port
1028 Send the packet to the port
1029 Verify the packet is received at all other ports (one port at a time)
1030 Verify flow_expiration message is correct when command option is set
1031 """
1032 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -07001033 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001034
Dan Talayco551befa2010-07-15 17:05:32 -07001035class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001036 """
Dan Talayco551befa2010-07-15 17:05:32 -07001037 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001038 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001039 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001040 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -07001041 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
1042 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001043
Dan Talaycoba3745c2010-07-21 21:51:08 -07001044
Dan Talayco551befa2010-07-15 17:05:32 -07001045class AddVLANTag(BaseMatchCase):
1046 """
1047 Add a VLAN tag to an untagged packet
1048 """
1049 def runTest(self):
1050 new_vid = 2
1051 sup_acts = supported_actions_get(self)
1052 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001053 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001054 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001055
Dan Talayco551befa2010-07-15 17:05:32 -07001056 len = 100
1057 len_w_vid = 104
1058 pkt = simple_tcp_packet(pktlen=len)
1059 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1060 dl_vlan=new_vid)
1061 vid_act = action.action_set_vlan_vid()
1062 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001063
Dan Talayco551befa2010-07-15 17:05:32 -07001064 flow_match_test(self, pa_port_map, pkt=pkt,
1065 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001066
Dan Talayco551befa2010-07-15 17:05:32 -07001067class PacketOnly(basic.DataPlaneOnly):
1068 """
1069 Just send a packet thru the switch
1070 """
1071 def runTest(self):
1072 pkt = simple_tcp_packet()
1073 of_ports = pa_port_map.keys()
1074 of_ports.sort()
1075 ing_port = of_ports[0]
1076 pa_logger.info("Sending packet to " + str(ing_port))
1077 pa_logger.debug("Data: " + str(pkt).encode('hex'))
1078 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001079
Dan Talayco551befa2010-07-15 17:05:32 -07001080class PacketOnlyTagged(basic.DataPlaneOnly):
1081 """
1082 Just send a packet thru the switch
1083 """
1084 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001085 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001086 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
1087 of_ports = pa_port_map.keys()
1088 of_ports.sort()
1089 ing_port = of_ports[0]
1090 pa_logger.info("Sending packet to " + str(ing_port))
1091 pa_logger.debug("Data: " + str(pkt).encode('hex'))
1092 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001093
Dan Talayco551befa2010-07-15 17:05:32 -07001094test_prio["PacketOnly"] = -1
1095test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001096
Dan Talayco551befa2010-07-15 17:05:32 -07001097class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001098 """
1099 Modify the VLAN ID in the VLAN tag of a tagged packet
1100 """
Dan Talayco551befa2010-07-15 17:05:32 -07001101 def runTest(self):
1102 old_vid = 2
1103 new_vid = 3
1104 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001105 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001106 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001107 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001108
Dan Talayco551befa2010-07-15 17:05:32 -07001109 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1110 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
1111 vid_act = action.action_set_vlan_vid()
1112 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001113
Dan Talayco551befa2010-07-15 17:05:32 -07001114 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1115 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001116
Howard Pershc1199d52012-04-11 14:21:32 -07001117class ModifyVlanPcp(BaseMatchCase):
1118 """
1119 Modify the priority field of the VLAN tag of a tagged packet
1120 """
1121 def runTest(self):
1122 vid = 123
1123 old_vlan_pcp = 2
1124 new_vlan_pcp = 3
1125 sup_acts = supported_actions_get(self)
1126 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1127 skip_message_emit(self, "Modify VLAN tag test")
1128 return
1129
1130 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1131 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1132 vid_act = action.action_set_vlan_pcp()
1133 vid_act.vlan_pcp = new_vlan_pcp
1134
1135 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1136 action_list=[vid_act])
1137
Dan Talayco551befa2010-07-15 17:05:32 -07001138class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001139 """
1140 Strip the VLAN tag from a tagged packet
1141 """
Dan Talayco551befa2010-07-15 17:05:32 -07001142 def runTest(self):
1143 old_vid = 2
1144 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -07001145 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001146 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001147 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001148
Dan Talayco551befa2010-07-15 17:05:32 -07001149 len_w_vid = 104
1150 len = 100
1151 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1152 dl_vlan=old_vid)
1153 exp_pkt = simple_tcp_packet(pktlen=len)
1154 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001155
Dan Talayco551befa2010-07-15 17:05:32 -07001156 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1157 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001158
Dan Talayco4b2bee62010-07-20 14:10:05 -07001159def init_pkt_args():
1160 """
1161 Pass back a dictionary with default packet arguments
1162 """
1163 args = {}
1164 args["dl_src"] = '00:23:45:67:89:AB'
1165
1166 dl_vlan_enable=False
1167 dl_vlan=-1
1168 if pa_config["test-params"]["vid"]:
1169 dl_vlan_enable=True
1170 dl_vlan = pa_config["test-params"]["vid"]
1171
1172# Unpack operator is ** on a dictionary
1173
1174 return args
1175
Dan Talayco551befa2010-07-15 17:05:32 -07001176class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001177 """
1178 Modify the source MAC address (TP1)
1179 """
Dan Talayco551befa2010-07-15 17:05:32 -07001180 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001181 sup_acts = supported_actions_get(self)
1182 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001183 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001184 return
1185
1186 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1187 check_test_params=True)
1188 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1189 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001190
Dan Talayco551befa2010-07-15 17:05:32 -07001191class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001192 """
1193 Modify the dest MAC address (TP1)
1194 """
Dan Talayco551befa2010-07-15 17:05:32 -07001195 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001196 sup_acts = supported_actions_get(self)
1197 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001198 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001199 return
1200
1201 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1202 check_test_params=True)
1203 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1204 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001205
Dan Talayco551befa2010-07-15 17:05:32 -07001206class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001207 """
1208 Modify the source IP address of an IP packet (TP1)
1209 """
Dan Talayco551befa2010-07-15 17:05:32 -07001210 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001211 sup_acts = supported_actions_get(self)
1212 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001213 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001214 return
1215
1216 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1217 check_test_params=True)
1218 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1219 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001220
Dan Talayco551befa2010-07-15 17:05:32 -07001221class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001222 """
1223 Modify the dest IP address of an IP packet (TP1)
1224 """
Dan Talayco551befa2010-07-15 17:05:32 -07001225 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001226 sup_acts = supported_actions_get(self)
1227 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001228 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001229 return
1230
1231 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1232 check_test_params=True)
1233 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1234 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001235
1236class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001237 """
1238 Modify the source TCP port of a TCP packet (TP1)
1239 """
Dan Talayco551befa2010-07-15 17:05:32 -07001240 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001241 sup_acts = supported_actions_get(self)
1242 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001243 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001244 return
1245
1246 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1247 check_test_params=True)
1248 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1249 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001250
1251class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001252 """
1253 Modify the dest TCP port of a TCP packet (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_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001258 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001259 return
1260
1261 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
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)
Dan Talayco551befa2010-07-15 17:05:32 -07001265
1266class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001267 """
1268 Modify the IP type of service of an IP packet (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_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001273 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001274 return
Dan Talayco551befa2010-07-15 17:05:32 -07001275
Dan Talayco4b2bee62010-07-20 14:10:05 -07001276 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1277 check_test_params=True)
1278 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001279 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001280
Dan Talaycof6e76c02012-03-23 10:56:12 -07001281class ModifyL2DstMC(BaseMatchCase):
1282 """
1283 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001284 """
1285 def runTest(self):
1286 sup_acts = supported_actions_get(self)
1287 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001288 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001289 return
1290
Dan Talaycof6e76c02012-03-23 10:56:12 -07001291 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1292 check_test_params=True)
1293 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001294 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001295
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001296class ModifyL2DstIngress(BaseMatchCase):
1297 """
1298 Modify the L2 dest and send to the ingress port
1299 """
1300 def runTest(self):
1301 sup_acts = supported_actions_get(self)
1302 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001303 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001304 return
1305
1306 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_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, egr_count=0,
1310 ing_port=True)
1311
Dan Talaycod8ae7582012-03-23 12:24:56 -07001312class ModifyL2DstIngressMC(BaseMatchCase):
1313 """
1314 Modify the L2 dest and send to the ingress port
1315 """
1316 def runTest(self):
1317 sup_acts = supported_actions_get(self)
1318 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1319 skip_message_emit(self, "ModifyL2dstMC test")
1320 return
1321
1322 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1323 check_test_params=True)
1324 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1325 action_list=acts, max_test=2, egr_count=-1,
1326 ing_port=True)
1327
Dan Talaycof6e76c02012-03-23 10:56:12 -07001328class ModifyL2SrcMC(BaseMatchCase):
1329 """
1330 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001331 """
1332 def runTest(self):
1333 sup_acts = supported_actions_get(self)
1334 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001335 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001336 return
1337
Dan Talaycof6e76c02012-03-23 10:56:12 -07001338 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1339 check_test_params=True)
1340 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001341 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001342
1343class ModifyL2SrcDstMC(BaseMatchCase):
1344 """
1345 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001346 """
1347 def runTest(self):
1348 sup_acts = supported_actions_get(self)
Dan Talaycocfa172f2012-03-23 12:03:00 -07001349 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1350 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1351 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001352 return
1353
Dan Talaycof6e76c02012-03-23 10:56:12 -07001354 mod_fields = ['dl_dst', 'dl_src']
1355 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1356 check_test_params=True)
1357 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001358 action_list=acts, max_test=2, egr_count=-1)
1359
1360class ModifyL2DstVIDMC(BaseMatchCase):
1361 """
1362 Modify the L2 dest and send to 2 ports
1363 """
1364 def runTest(self):
1365 sup_acts = supported_actions_get(self)
1366 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1367 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1368 skip_message_emit(self, "ModifyL2DstVIDMC test")
1369 return
1370
1371 mod_fields = ['dl_dst', 'dl_vlan']
1372 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1373 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
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, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001377
Dan Talaycofa6454f2012-04-05 10:04:13 -07001378class FlowToggle(BaseMatchCase):
1379 """
1380 Add flows to the table and modify them repeatedly
1381 """
1382 def runTest(self):
Dan Talayco50be7672012-04-05 11:38:08 -07001383 flow_count = test_param_get(self.config, 'ft_flow_count', default=20)
1384 iter_count = test_param_get(self.config, 'ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001385
1386 pa_logger.info("Running flow toggle with %d flows, %d iterations" %
1387 (flow_count, iter_count))
1388 acts = []
1389 acts.append(action.action_output())
1390 acts.append(action.action_output())
1391
1392 of_ports = pa_port_map.keys()
1393 if len(of_ports) < 3:
1394 self.assertTrue(False, "Too few ports for test")
1395
1396 for idx in range(2):
1397 acts[idx].port = of_ports[idx]
1398
1399 flows = []
1400 flows.append([])
1401 flows.append([])
1402
Dan Talayco50be7672012-04-05 11:38:08 -07001403 wildcards = ofp.OFPFW_DL_SRC | ofp.OFPFW_DL_DST
Dan Talaycofa6454f2012-04-05 10:04:13 -07001404 # Create up the flows in an array
1405 for toggle in range(2):
1406 for f_idx in range(flow_count):
1407 pkt = simple_tcp_packet(tcp_sport=f_idx)
1408 msg = message.flow_mod()
1409 match = parse.packet_to_flow_match(pkt)
1410 match.in_port = of_ports[3]
Dan Talayco50be7672012-04-05 11:38:08 -07001411 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001412 msg.match = match
1413 msg.buffer_id = 0xffffffff
1414 msg.actions.add(acts[toggle])
1415 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001416
1417 # Show two sample flows
1418 pa_logger.debug(flows[0][0].show())
1419 pa_logger.debug(flows[1][0].show())
1420
Dan Talaycofa6454f2012-04-05 10:04:13 -07001421 # Install the first set of flows
1422 for f_idx in range(flow_count):
1423 rv = self.controller.message_send(flows[0][f_idx])
1424 self.assertTrue(rv != -1, "Error installing flow %d" % f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001425 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycofa6454f2012-04-05 10:04:13 -07001426
1427 pa_logger.info("Installed %d flows" % flow_count)
1428
1429 # Repeatedly modify all the flows back and forth
1430 updates = 0
1431 # Report status about 5 times
1432 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001433 start = time.time()
1434 for iter_idx in range(iter_count):
1435 if not iter_idx % mod_val:
1436 pa_logger.info("Flow Toggle: iter %d of %d. " %
1437 (iter_idx, iter_count) +
1438 "%d updates in %d secs" %
1439 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001440 for toggle in range(2):
1441 t_idx = 1 - toggle
1442 for f_idx in range(flow_count):
1443 rv = self.controller.message_send(flows[t_idx][f_idx])
1444 updates += 1
1445 self.assertTrue(rv != -1, "Error modifying flow %d" %
1446 f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001447 self.assertEqual(do_barrier(self.controller), 0,
1448 "Barrier failed")
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001449
1450 end = time.time()
1451 divisor = end - start or (end - start + 1)
1452 pa_logger.info("Flow toggle: %d iterations" % iter_count)
1453 pa_logger.info(" %d flow mods in %d secs, %d mods/sec" %
1454 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001455
1456
Dan Talayco8a64e332012-03-28 14:53:20 -07001457# You can pick and choose these by commenting tests in or out
1458iter_classes = [
1459 basic.PacketIn,
1460 basic.PacketOut,
1461 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001462 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001463 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001464 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001465 AllWildcardMatch,
1466 AllWildcardMatchTagged,
1467 SingleWildcardMatch,
1468 SingleWildcardMatchTagged,
1469 ExactMatch,
1470 ExactMatchTagged,
1471 SingleWildcardMatch,
1472 ModifyL2Src,
1473 ModifyL2Dst,
1474 ModifyL2SrcMC,
1475 ModifyL2DstMC,
1476 ModifyL2SrcDstMC
1477 ]
1478
1479class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001480 """
1481 Iterate over a bunch of test cases
1482
1483 The cases come from the list above
1484 """
1485
Dan Talayco8a64e332012-03-28 14:53:20 -07001486 def runTest(self):
1487 count = test_param_get(self.config, 'iter_count', default=10)
1488 tests_done = 0
1489 pa_logger.info("Running iteration test " + str(count) + " times")
1490 start = time.time()
1491 last = start
1492 for idx in range(count):
1493 pa_logger.info("Iteration " + str(idx + 1))
1494 for cls in iter_classes:
1495 test = cls()
1496 test.inheritSetup(self)
1497 test.runTest()
1498 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001499 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001500 if time.time() - last > 60:
1501 last = time.time()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001502 pa_logger.info(
1503 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1504 (idx, count, tests_done, last - start) +
1505 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001506 stats = all_stats_get(self)
1507 last = time.time()
1508 pa_logger.info("\nIterCases ran %d tests in %d seconds." %
1509 (tests_done, last - start))
1510 pa_logger.info(" flows: %d. packets: %d. bytes: %d" %
1511 (stats["flows"], stats["packets"], stats["bytes"]))
1512 pa_logger.info(" active: %d. lookups: %d. matched %d." %
1513 (stats["active"], stats["lookups"], stats["matched"]))
1514
1515# Don't run by default
1516test_prio["IterCases"] = -1
Dan Talaycof6e76c02012-03-23 10:56:12 -07001517
Dan Talayco4b2bee62010-07-20 14:10:05 -07001518#@todo Need to implement tagged versions of the above tests
1519#
1520#@todo Implement a test case that strips tag 2, adds tag 3
1521# and modifies tag 4 to tag 5. Then verify (in addition) that
1522# tag 6 does not get modified.
1523
1524class MixedVLAN(BaseMatchCase):
1525 """
1526 Test mixture of VLAN tag actions
1527
1528 Strip tag 2 on port 1, send to port 2
1529 Add tag 3 on port 1, send to port 2
1530 Modify tag 4 to 5 on port 1, send to port 2
1531 All other traffic from port 1, send to port 3
1532 All traffic from port 2 sent to port 4
1533 Use exact matches with different packets for all mods
1534 Verify the following: (port, vid)
1535 (port 1, vid 2) => VLAN tag stripped, out port 2
1536 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1537 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1538 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1539 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1540 (port 2, no tag) => untagged packet out port 4
1541 (port 2, vid 2-6) => unmodified packet out port 4
1542
1543 Variation: Might try sending VID 5 to port 3 and check.
1544 If only VID 5 distinguishes pkt, this will fail on some platforms
1545 """
1546
1547test_prio["MixedVLAN"] = -1
1548
Dan Talayco551befa2010-07-15 17:05:32 -07001549def supported_actions_get(parent, use_cache=True):
1550 """
1551 Get the bitmap of supported actions from the switch
1552 If use_cache is false, the cached value will be updated
1553 """
1554 global cached_supported_actions
1555 if cached_supported_actions is None or not use_cache:
1556 request = message.features_request()
1557 (reply, pkt) = parent.controller.transact(request, timeout=2)
1558 parent.assertTrue(reply is not None, "Did not get response to ftr req")
1559 cached_supported_actions = reply.actions
1560 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
1561
1562 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -07001563
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001564if __name__ == "__main__":
1565 print "Please run through oft script: ./oft --test_spec=basic"