blob: ef7505e5acf23832ec659fc573463a875a559f19 [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
Rich Laneda3b5ad2012-10-03 09:05:32 -070033from oftest.testutils import *
Dan Talayco5eba8442010-03-10 13:58:43 -080034
35#@var port_map Local copy of the configuration map from OF port
36# numbers to OS interfaces
37pa_port_map = None
Dan Talayco5eba8442010-03-10 13:58:43 -080038#@var pa_config Local copy of global configuration data
39pa_config = None
40
Dan Talayco551befa2010-07-15 17:05:32 -070041# For test priority
42#@var test_prio Set test priority for local tests
43test_prio = {}
44
45WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
Dan Talayco488fbc52012-04-09 16:30:41 -070046 ofp.OFPFW_DL_VLAN | ofp.OFPFW_DL_VLAN_PCP,
Dan Talayco551befa2010-07-15 17:05:32 -070047 ofp.OFPFW_DL_SRC,
48 ofp.OFPFW_DL_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070049 (ofp.OFPFW_DL_TYPE | ofp.OFPFW_NW_SRC_ALL |
50 ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS | ofp.OFPFW_NW_PROTO |
51 ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
52 (ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
Dan Talayco551befa2010-07-15 17:05:32 -070053 ofp.OFPFW_TP_SRC,
54 ofp.OFPFW_TP_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070055 ofp.OFPFW_NW_SRC_MASK,
56 ofp.OFPFW_NW_DST_MASK,
Dan Talayco551befa2010-07-15 17:05:32 -070057 ofp.OFPFW_DL_VLAN_PCP,
58 ofp.OFPFW_NW_TOS]
59
Dan Talayco488fbc52012-04-09 16:30:41 -070060NO_WILDCARD_VALUES = [(ofp.OFPFW_ALL ^ ofp.OFPFW_IN_PORT),
61 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN),
62 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_SRC),
63 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_DST),
64 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE),
65 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO),
66 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
67 ofp.OFPFW_TP_SRC),
68 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
69 ofp.OFPFW_TP_DST),
70 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
71 ofp.OFPFW_NW_SRC_MASK),
72 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
73 ofp.OFPFW_NW_DST_MASK),
74 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN ^ ofp.OFPFW_DL_VLAN_PCP),
75 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
76 ofp.OFPFW_NW_TOS)]
77
Dan Talayco551befa2010-07-15 17:05:32 -070078MODIFY_ACTION_VALUES = [ofp.OFPAT_SET_VLAN_VID,
79 ofp.OFPAT_SET_VLAN_PCP,
80 ofp.OFPAT_STRIP_VLAN,
81 ofp.OFPAT_SET_DL_SRC,
82 ofp.OFPAT_SET_DL_DST,
83 ofp.OFPAT_SET_NW_SRC,
84 ofp.OFPAT_SET_NW_DST,
85 ofp.OFPAT_SET_NW_TOS,
86 ofp.OFPAT_SET_TP_SRC,
87 ofp.OFPAT_SET_TP_DST]
88
Dan Talayco21381562010-07-17 00:34:47 -070089TEST_VID_DEFAULT = 2
90
Dan Talayco5eba8442010-03-10 13:58:43 -080091def test_set_init(config):
92 """
93 Set up function for packet action test classes
94
95 @param config The configuration dictionary; see oft
96 """
97
Ed Swierk89f78352012-03-29 12:32:32 -070098 basic.test_set_init(config)
99
Dan Talayco5eba8442010-03-10 13:58:43 -0800100 global pa_port_map
Dan Talayco5eba8442010-03-10 13:58:43 -0800101 global pa_config
102
Dan Talayco5eba8442010-03-10 13:58:43 -0800103 pa_port_map = config["port_map"]
104 pa_config = config
105
106class DirectPacket(basic.SimpleDataPlane):
107 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700108 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -0800109
110 Generate a packet
111 Generate and install a matching flow
112 Add action to direct the packet to an egress port
113 Send the packet to ingress dataplane port
114 Verify the packet is received at the egress port only
115 """
116 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700117 self.handleFlow()
118
119 def handleFlow(self, pkttype='TCP'):
Dan Talayco5eba8442010-03-10 13:58:43 -0800120 of_ports = pa_port_map.keys()
121 of_ports.sort()
122 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
123
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700124 if (pkttype == 'ICMP'):
125 pkt = simple_icmp_packet()
126 else:
127 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700128 match = packet_to_flow_match(self, pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700129 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800130 self.assertTrue(match is not None,
131 "Could not generate flow match from pkt")
132 act = action.action_output()
133
134 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700135 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700136 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700137
Dan Talayco5eba8442010-03-10 13:58:43 -0800138 ingress_port = of_ports[idx]
139 egress_port = of_ports[(idx + 1) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700140 logging.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700141 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800142
143 match.in_port = ingress_port
144
145 request = message.flow_mod()
146 request.match = match
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700147
Dan Talayco5eba8442010-03-10 13:58:43 -0800148 request.buffer_id = 0xffffffff
149 act.port = egress_port
150 self.assertTrue(request.actions.add(act), "Could not add action")
151
Rich Lane9a003812012-10-04 17:17:59 -0700152 logging.info("Inserting flow")
Dan Talayco5eba8442010-03-10 13:58:43 -0800153 rv = self.controller.message_send(request)
154 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700155 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco5eba8442010-03-10 13:58:43 -0800156
Rich Lane9a003812012-10-04 17:17:59 -0700157 logging.info("Sending packet to dp port " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800158 str(ingress_port))
159 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700160
161 exp_pkt_arg = None
162 exp_port = None
163 if pa_config["relax"]:
164 exp_pkt_arg = pkt
165 exp_port = egress_port
166
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700167 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700168 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800169 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700170 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800171 str(rcv_port))
172 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
173 self.assertEqual(str(pkt), str(rcv_pkt),
174 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700175
Rich Lane51c23b32012-07-27 16:37:25 -0700176class DirectPacketController(basic.SimpleDataPlane):
177 """
178 Send packet to the controller port
179
180 Generate a packet
181 Generate and install a matching flow
182 Add action to direct the packet to the controller port
183 Send the packet to ingress dataplane port
184 Verify the packet is received at the controller port
185 """
186 def runTest(self):
187 self.handleFlow()
188
189 def handleFlow(self, pkttype='TCP'):
190 of_ports = pa_port_map.keys()
191 of_ports.sort()
192 self.assertTrue(len(of_ports) > 0, "Not enough ports for test")
193
194 if (pkttype == 'ICMP'):
195 pkt = simple_icmp_packet()
196 else:
197 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700198 match = packet_to_flow_match(self, pkt)
Rich Lane51c23b32012-07-27 16:37:25 -0700199 match.wildcards &= ~ofp.OFPFW_IN_PORT
200 self.assertTrue(match is not None,
201 "Could not generate flow match from pkt")
202 act = action.action_output()
203
Rich Lane9a003812012-10-04 17:17:59 -0700204 rv = delete_all_flows(self.controller)
Rich Lane51c23b32012-07-27 16:37:25 -0700205 self.assertEqual(rv, 0, "Failed to delete all flows")
206
207 ingress_port = of_ports[0]
208 match.in_port = ingress_port
209
210 request = message.flow_mod()
211 request.match = match
212
213 request.buffer_id = 0xffffffff
214 act.port = ofp.OFPP_CONTROLLER
215 act.max_len = 65535
216 self.assertTrue(request.actions.add(act), "Could not add action")
217
Rich Lane9a003812012-10-04 17:17:59 -0700218 logging.info("Inserting flow")
Rich Lane51c23b32012-07-27 16:37:25 -0700219 rv = self.controller.message_send(request)
220 self.assertTrue(rv != -1, "Error installing flow mod")
221 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
222
Rich Lane9a003812012-10-04 17:17:59 -0700223 logging.info("Sending packet to dp port " +
Rich Lane51c23b32012-07-27 16:37:25 -0700224 str(ingress_port))
225 self.dataplane.send(ingress_port, str(pkt))
226
227 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
228
229 self.assertTrue(response is not None,
230 'Packet in message not received by controller')
231 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700232 logging.debug("Sent %s" % format_packet(pkt))
233 logging.debug("Resp %s" % format_packet(response.data))
Rich Lane51c23b32012-07-27 16:37:25 -0700234 self.assertTrue(False,
235 'Response packet does not match send packet' +
236 ' for controller port')
237
Howard Pershf97840f2012-04-10 16:30:42 -0700238
239class DirectPacketQueue(basic.SimpleDataPlane):
240 """
241 Send packet to single queue on single egress port
242
243 Generate a packet
244 Generate and install a matching flow
245 Add action to direct the packet to an egress port and queue
246 Send the packet to ingress dataplane port
247 Verify the packet is received at the egress port only
248 """
249 def runTest(self):
250 self.handleFlow()
251
Howard Persh670b5672012-04-13 09:08:29 -0700252 def portQueuesGet(self, queue_stats, port_num):
253 result = []
254 for qs in queue_stats.stats:
255 if qs.port_no != port_num:
256 continue
257 result.append(qs.queue_id)
258 return result
259
Howard Pershf97840f2012-04-10 16:30:42 -0700260 def handleFlow(self, pkttype='TCP'):
261 of_ports = pa_port_map.keys()
262 of_ports.sort()
263 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
264
265 if (pkttype == 'ICMP'):
266 pkt = simple_icmp_packet()
267 else:
268 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700269 match = packet_to_flow_match(self, pkt)
Howard Pershf97840f2012-04-10 16:30:42 -0700270 match.wildcards &= ~ofp.OFPFW_IN_PORT
271 self.assertTrue(match is not None,
272 "Could not generate flow match from pkt")
273
Howard Persh670b5672012-04-13 09:08:29 -0700274 # Get queue stats from switch
275
276 request = message.queue_stats_request()
277 request.port_no = ofp.OFPP_ALL
278 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700279 (queue_stats, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700280 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
281
282 act = action.action_enqueue()
Howard Pershf97840f2012-04-10 16:30:42 -0700283
284 for idx in range(len(of_ports)):
Howard Pershf97840f2012-04-10 16:30:42 -0700285 ingress_port = of_ports[idx]
286 egress_port = of_ports[(idx + 1) % len(of_ports)]
Howard Pershf97840f2012-04-10 16:30:42 -0700287
Howard Persh670b5672012-04-13 09:08:29 -0700288 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700289 logging.info("Ingress " + str(ingress_port)
Howard Persh670b5672012-04-13 09:08:29 -0700290 + " to egress " + str(egress_port)
291 + " queue " + str(egress_queue_id)
292 )
Howard Pershf97840f2012-04-10 16:30:42 -0700293
Rich Lane9a003812012-10-04 17:17:59 -0700294 rv = delete_all_flows(self.controller)
Howard Persh670b5672012-04-13 09:08:29 -0700295 self.assertEqual(rv, 0, "Failed to delete all flows")
Howard Pershf97840f2012-04-10 16:30:42 -0700296
Howard Persh670b5672012-04-13 09:08:29 -0700297 match.in_port = ingress_port
298
299 request = message.flow_mod()
300 request.match = match
Howard Pershf97840f2012-04-10 16:30:42 -0700301
Howard Persh670b5672012-04-13 09:08:29 -0700302 request.buffer_id = 0xffffffff
303 act.port = egress_port
304 act.queue_id = egress_queue_id
305 self.assertTrue(request.actions.add(act), "Could not add action")
Howard Pershf97840f2012-04-10 16:30:42 -0700306
Rich Lane9a003812012-10-04 17:17:59 -0700307 logging.info("Inserting flow")
Howard Persh670b5672012-04-13 09:08:29 -0700308 rv = self.controller.message_send(request)
309 self.assertTrue(rv != -1, "Error installing flow mod")
310 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Howard Pershf97840f2012-04-10 16:30:42 -0700311
Howard Persh670b5672012-04-13 09:08:29 -0700312 # Get current stats for selected egress queue
Howard Pershf97840f2012-04-10 16:30:42 -0700313
Howard Persh670b5672012-04-13 09:08:29 -0700314 request = message.queue_stats_request()
315 request.port_no = egress_port
316 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700317 (qs_before, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700318 self.assertNotEqual(qs_before, None, "Queue stats request failed")
319
Rich Lane9a003812012-10-04 17:17:59 -0700320 logging.info("Sending packet to dp port " +
Howard Persh670b5672012-04-13 09:08:29 -0700321 str(ingress_port))
322 self.dataplane.send(ingress_port, str(pkt))
323
324 exp_pkt_arg = None
325 exp_port = None
326 if pa_config["relax"]:
327 exp_pkt_arg = pkt
328 exp_port = egress_port
329
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700330 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Howard Persh670b5672012-04-13 09:08:29 -0700331 exp_pkt=exp_pkt_arg)
332 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700333 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Howard Persh670b5672012-04-13 09:08:29 -0700334 str(rcv_port))
335 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
336 self.assertEqual(str(pkt), str(rcv_pkt),
337 'Response packet does not match send packet')
338
Ed Swierkb8a86512012-04-18 18:45:58 -0700339 # FIXME: instead of sleeping, keep requesting queue stats until
340 # the expected queue counter increases or some large timeout is
341 # reached
342 time.sleep(2)
343
Howard Persh670b5672012-04-13 09:08:29 -0700344 # Get current stats for selected egress queue again
345
346 request = message.queue_stats_request()
347 request.port_no = egress_port
348 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700349 (qs_after, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700350 self.assertNotEqual(qs_after, None, "Queue stats request failed")
351
352 # Make sure that tx packet counter for selected egress queue was
353 # incremented
354
Ed Swierk22f59152012-04-17 16:36:47 -0700355 self.assertEqual(qs_after.stats[0].tx_packets, \
356 qs_before.stats[0].tx_packets + 1, \
Howard Persh670b5672012-04-13 09:08:29 -0700357 "Verification of egress queue tx packet count failed"
358 )
359
360
Ken Chiang899ff8e2012-05-23 18:26:12 -0700361class DirectPacketControllerQueue(basic.SimpleDataPlane):
362 """
363 Send a packet from each of the openflow ports
364 to each of the queues configured on the controller port.
365 If no queues have been configured, no packets are sent.
Howard Pershf97840f2012-04-10 16:30:42 -0700366
Ken Chiang899ff8e2012-05-23 18:26:12 -0700367 Generate a packet
368 Generate and install a matching flow
369 Add action to direct the packet to one of the controller port queues
370 Send the packet to ingress dataplane port
371 Verify the packet is received on the controller port queue
372 """
373 def runTest(self):
374 self.handleFlow()
375
376 def portQueuesGet(self, queue_stats, port_num):
377 result = []
378 for qs in queue_stats.stats:
379 if qs.port_no != port_num:
380 continue
381 result.append(qs.queue_id)
382 return result
383
384 def handleFlow(self, pkttype='TCP'):
385 of_ports = pa_port_map.keys()
386 of_ports.sort()
387 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
388
389 if (pkttype == 'ICMP'):
390 pkt = simple_icmp_packet()
391 else:
392 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700393 match = packet_to_flow_match(self, pkt)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700394 match.wildcards &= ~ofp.OFPFW_IN_PORT
395 self.assertTrue(match is not None,
396 "Could not generate flow match from pkt")
397
398 # Get queue stats from switch
399
400 request = message.queue_stats_request()
401 request.port_no = ofp.OFPP_CONTROLLER
402 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700403 (queue_stats, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700404 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
405
406 act = action.action_enqueue()
407
408 for idx in range(len(of_ports)):
409 ingress_port = of_ports[idx]
410 egress_port = ofp.OFPP_CONTROLLER
411
Rich Lane9a003812012-10-04 17:17:59 -0700412 logging.info("Ingress port " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700413 + ", controller port queues "
414 + str(self.portQueuesGet(queue_stats, egress_port)))
415
416 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700417 logging.info("Ingress " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700418 + " to egress " + str(egress_port)
419 + " queue " + str(egress_queue_id)
420 )
421
Rich Lane9a003812012-10-04 17:17:59 -0700422 rv = delete_all_flows(self.controller)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700423 self.assertEqual(rv, 0, "Failed to delete all flows")
424
425 match.in_port = ingress_port
426
427 request = message.flow_mod()
428 request.match = match
429
430 request.buffer_id = 0xffffffff
431 act.port = egress_port
432 act.queue_id = egress_queue_id
433 self.assertTrue(request.actions.add(act), "Could not add action")
434
Rich Lane9a003812012-10-04 17:17:59 -0700435 logging.info("Inserting flow")
Ken Chiang899ff8e2012-05-23 18:26:12 -0700436 rv = self.controller.message_send(request)
437 self.assertTrue(rv != -1, "Error installing flow mod")
438 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
439
440 # Get current stats for selected egress queue
441
442 request = message.queue_stats_request()
443 request.port_no = egress_port
444 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700445 (qs_before, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700446 self.assertNotEqual(qs_before, None, "Queue stats request failed")
447
Rich Lane9a003812012-10-04 17:17:59 -0700448 logging.info("Sending packet to dp port " +
Ken Chiang899ff8e2012-05-23 18:26:12 -0700449 str(ingress_port))
450 self.dataplane.send(ingress_port, str(pkt))
451
452 exp_pkt_arg = None
453 exp_port = None
454
455 while True:
Dan Talaycoc689a792012-09-28 14:22:53 -0700456 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700457 if not response: # Timeout
458 break
459 if dataplane.match_exp_pkt(pkt, response.data): # Got match
460 break
461 if not basic_config["relax"]: # Only one attempt to match
462 break
463 count += 1
464 if count > 10: # Too many tries
465 break
466
467 self.assertTrue(response is not None,
468 'Packet in message not received by controller')
469 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700470 logging.debug("Sent %s" % format_packet(pkt))
471 logging.debug("Resp %s" % format_packet(response.data))
Ken Chiang899ff8e2012-05-23 18:26:12 -0700472 self.assertTrue(False,
473 'Response packet does not match send packet' +
474 ' for controller port')
475
476 # FIXME: instead of sleeping, keep requesting queue stats until
477 # the expected queue counter increases or some large timeout is
478 # reached
479 time.sleep(2)
480
481 # Get current stats for selected egress queue again
482
483 request = message.queue_stats_request()
484 request.port_no = egress_port
485 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700486 (qs_after, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700487 self.assertNotEqual(qs_after, None, "Queue stats request failed")
488
489 # Make sure that tx packet counter for selected egress queue was
490 # incremented
491
492 self.assertEqual(qs_after.stats[0].tx_packets, \
493 qs_before.stats[0].tx_packets + 1, \
494 "Verification of egress queue tx packet count failed"
495 )
496
Howard Pershf97840f2012-04-10 16:30:42 -0700497
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700498class DirectPacketICMP(DirectPacket):
499 """
500 Send ICMP packet to single egress port
501
502 Generate a ICMP packet
503 Generate and install a matching flow
504 Add action to direct the packet to an egress port
505 Send the packet to ingress dataplane port
506 Verify the packet is received at the egress port only
507 Difference from DirectPacket test is that sent packet is ICMP
508 """
509 def runTest(self):
510 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700511
512class DirectTwoPorts(basic.SimpleDataPlane):
513 """
514 Send packet to two egress ports
515
516 Generate a packet
517 Generate and install a matching flow
518 Add action to direct the packet to two egress ports
519 Send the packet to ingress dataplane port
520 Verify the packet is received at the two egress ports
521 """
522 def runTest(self):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700523 of_ports = pa_port_map.keys()
524 of_ports.sort()
525 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
526
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700527 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700528 match = packet_to_flow_match(self, pkt)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700529 match.wildcards &= ~ofp.OFPFW_IN_PORT
530 self.assertTrue(match is not None,
531 "Could not generate flow match from pkt")
532 act = action.action_output()
533
534 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700535 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700536 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700537
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700538 ingress_port = of_ports[idx]
539 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
540 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700541 logging.info("Ingress " + str(ingress_port) +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700542 " to egress " + str(egress_port1) + " and " +
543 str(egress_port2))
544
545 match.in_port = ingress_port
546
547 request = message.flow_mod()
548 request.match = match
549 request.buffer_id = 0xffffffff
550 act.port = egress_port1
551 self.assertTrue(request.actions.add(act), "Could not add action1")
552 act.port = egress_port2
553 self.assertTrue(request.actions.add(act), "Could not add action2")
Rich Lane9a003812012-10-04 17:17:59 -0700554 # logging.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700555
Rich Lane9a003812012-10-04 17:17:59 -0700556 logging.info("Inserting flow")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700557 rv = self.controller.message_send(request)
558 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700559 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700560
Rich Lane9a003812012-10-04 17:17:59 -0700561 logging.info("Sending packet to dp port " +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700562 str(ingress_port))
563 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700564 yes_ports = set([egress_port1, egress_port2])
565 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700566
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700567 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Rich Lane9a003812012-10-04 17:17:59 -0700568 self, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700569
570class DirectMCNonIngress(basic.SimpleDataPlane):
571 """
572 Multicast to all non-ingress ports
573
574 Generate a packet
575 Generate and install a matching flow
576 Add action to direct the packet to all non-ingress ports
577 Send the packet to ingress dataplane port
578 Verify the packet is received at all non-ingress ports
579
580 Does not use the flood action
581 """
582 def runTest(self):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700583 of_ports = pa_port_map.keys()
584 of_ports.sort()
585 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
586
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700587 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700588 match = packet_to_flow_match(self, pkt)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700589 match.wildcards &= ~ofp.OFPFW_IN_PORT
590 self.assertTrue(match is not None,
591 "Could not generate flow match from pkt")
592 act = action.action_output()
593
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700594 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700595 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700596 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700597
Rich Lane9a003812012-10-04 17:17:59 -0700598 logging.info("Ingress " + str(ingress_port) +
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700599 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700600 match.in_port = ingress_port
601
602 request = message.flow_mod()
603 request.match = match
604 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700605 for egress_port in of_ports:
606 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700607 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700608 act.port = egress_port
609 self.assertTrue(request.actions.add(act),
610 "Could not add output to " + str(egress_port))
Rich Lane9a003812012-10-04 17:17:59 -0700611 logging.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700612
Rich Lane9a003812012-10-04 17:17:59 -0700613 logging.info("Inserting flow")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700614 rv = self.controller.message_send(request)
615 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700616 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700617
Rich Lane9a003812012-10-04 17:17:59 -0700618 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700619 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700620 yes_ports = set(of_ports).difference([ingress_port])
621 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane9a003812012-10-04 17:17:59 -0700622 self, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700623
Dan Talayco32fa6542010-05-11 15:54:08 -0700624
625class DirectMC(basic.SimpleDataPlane):
626 """
627 Multicast to all ports including ingress
628
629 Generate a packet
630 Generate and install a matching flow
631 Add action to direct the packet to all non-ingress ports
632 Send the packet to ingress dataplane port
633 Verify the packet is received at all ports
634
635 Does not use the flood action
636 """
637 def runTest(self):
Dan Talayco32fa6542010-05-11 15:54:08 -0700638 of_ports = pa_port_map.keys()
639 of_ports.sort()
640 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
641
Dan Talayco32fa6542010-05-11 15:54:08 -0700642 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700643 match = packet_to_flow_match(self, pkt)
Dan Talayco32fa6542010-05-11 15:54:08 -0700644 match.wildcards &= ~ofp.OFPFW_IN_PORT
645 self.assertTrue(match is not None,
646 "Could not generate flow match from pkt")
647 act = action.action_output()
648
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700649 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700650 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700651 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700652
Rich Lane9a003812012-10-04 17:17:59 -0700653 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700654 match.in_port = ingress_port
655
656 request = message.flow_mod()
657 request.match = match
658 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700659 for egress_port in of_ports:
660 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700661 act.port = ofp.OFPP_IN_PORT
662 else:
663 act.port = egress_port
664 self.assertTrue(request.actions.add(act),
665 "Could not add output to " + str(egress_port))
Rich Lane9a003812012-10-04 17:17:59 -0700666 # logging.info(request.show())
Dan Talayco2e77a842010-05-12 15:39:46 -0700667
Rich Lane9a003812012-10-04 17:17:59 -0700668 logging.info("Inserting flow")
Dan Talayco2e77a842010-05-12 15:39:46 -0700669 rv = self.controller.message_send(request)
670 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700671 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2e77a842010-05-12 15:39:46 -0700672
Rich Lane9a003812012-10-04 17:17:59 -0700673 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700674 self.dataplane.send(ingress_port, str(pkt))
Rich Lane9a003812012-10-04 17:17:59 -0700675 receive_pkt_check(self.dataplane, pkt, of_ports, [], self, pa_config)
Dan Talayco2e77a842010-05-12 15:39:46 -0700676
677class Flood(basic.SimpleDataPlane):
678 """
679 Flood to all ports except ingress
680
681 Generate a packet
682 Generate and install a matching flow
683 Add action to flood the packet
684 Send the packet to ingress dataplane port
685 Verify the packet is received at all other ports
686 """
687 def runTest(self):
Dan Talayco2e77a842010-05-12 15:39:46 -0700688 of_ports = pa_port_map.keys()
689 of_ports.sort()
690 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
691
692 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700693 match = packet_to_flow_match(self, pkt)
Dan Talayco2e77a842010-05-12 15:39:46 -0700694 match.wildcards &= ~ofp.OFPFW_IN_PORT
695 self.assertTrue(match is not None,
696 "Could not generate flow match from pkt")
697 act = action.action_output()
698
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700699 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700700 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700701 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700702
Rich Lane9a003812012-10-04 17:17:59 -0700703 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700704 match.in_port = ingress_port
705
706 request = message.flow_mod()
707 request.match = match
708 request.buffer_id = 0xffffffff
709 act.port = ofp.OFPP_FLOOD
710 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700711 "Could not add flood port action")
Rich Lane9a003812012-10-04 17:17:59 -0700712 logging.info(request.show())
Dan Talayco32fa6542010-05-11 15:54:08 -0700713
Rich Lane9a003812012-10-04 17:17:59 -0700714 logging.info("Inserting flow")
Dan Talayco32fa6542010-05-11 15:54:08 -0700715 rv = self.controller.message_send(request)
716 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700717 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco32fa6542010-05-11 15:54:08 -0700718
Rich Lane9a003812012-10-04 17:17:59 -0700719 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco32fa6542010-05-11 15:54:08 -0700720 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700721 yes_ports = set(of_ports).difference([ingress_port])
722 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane9a003812012-10-04 17:17:59 -0700723 self, pa_config)
Dan Talayco3be5b062010-05-12 15:46:21 -0700724
Dan Talayco3be5b062010-05-12 15:46:21 -0700725class FloodPlusIngress(basic.SimpleDataPlane):
726 """
727 Flood to all ports plus send to ingress port
728
729 Generate a packet
730 Generate and install a matching flow
731 Add action to flood the packet
732 Add action to send to ingress port
733 Send the packet to ingress dataplane port
734 Verify the packet is received at all other ports
735 """
736 def runTest(self):
Dan Talayco3be5b062010-05-12 15:46:21 -0700737 of_ports = pa_port_map.keys()
738 of_ports.sort()
739 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
740
741 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700742 match = packet_to_flow_match(self, pkt)
Dan Talayco3be5b062010-05-12 15:46:21 -0700743 match.wildcards &= ~ofp.OFPFW_IN_PORT
744 self.assertTrue(match is not None,
745 "Could not generate flow match from pkt")
746 act = action.action_output()
747
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700748 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700749 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700750 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700751
Rich Lane9a003812012-10-04 17:17:59 -0700752 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700753 match.in_port = ingress_port
754
755 request = message.flow_mod()
756 request.match = match
757 request.buffer_id = 0xffffffff
758 act.port = ofp.OFPP_FLOOD
759 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700760 "Could not add flood port action")
761 act.port = ofp.OFPP_IN_PORT
762 self.assertTrue(request.actions.add(act),
763 "Could not add ingress port for output")
Rich Lane9a003812012-10-04 17:17:59 -0700764 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700765
Rich Lane9a003812012-10-04 17:17:59 -0700766 logging.info("Inserting flow")
Dan Talayco4aa13122010-05-12 15:54:44 -0700767 rv = self.controller.message_send(request)
768 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700769 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700770
Rich Lane9a003812012-10-04 17:17:59 -0700771 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700772 self.dataplane.send(ingress_port, str(pkt))
Rich Lane9a003812012-10-04 17:17:59 -0700773 receive_pkt_check(self.dataplane, pkt, of_ports, [], self, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700774
775class All(basic.SimpleDataPlane):
776 """
777 Send to OFPP_ALL port
778
779 Generate a packet
780 Generate and install a matching flow
781 Add action to forward to OFPP_ALL
782 Send the packet to ingress dataplane port
783 Verify the packet is received at all other ports
784 """
785 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700786 of_ports = pa_port_map.keys()
787 of_ports.sort()
788 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
789
790 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700791 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700792 match.wildcards &= ~ofp.OFPFW_IN_PORT
793 self.assertTrue(match is not None,
794 "Could not generate flow match from pkt")
795 act = action.action_output()
796
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700797 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700798 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700799 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700800
Rich Lane9a003812012-10-04 17:17:59 -0700801 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700802 match.in_port = ingress_port
803
804 request = message.flow_mod()
805 request.match = match
806 request.buffer_id = 0xffffffff
807 act.port = ofp.OFPP_ALL
808 self.assertTrue(request.actions.add(act),
809 "Could not add ALL port action")
Rich Lane9a003812012-10-04 17:17:59 -0700810 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700811
Rich Lane9a003812012-10-04 17:17:59 -0700812 logging.info("Inserting flow")
Dan Talayco4aa13122010-05-12 15:54:44 -0700813 rv = self.controller.message_send(request)
814 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700815 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700816
Rich Lane9a003812012-10-04 17:17:59 -0700817 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700818 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700819 yes_ports = set(of_ports).difference([ingress_port])
820 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane9a003812012-10-04 17:17:59 -0700821 self, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700822
823class AllPlusIngress(basic.SimpleDataPlane):
824 """
825 Send to OFPP_ALL port and ingress port
826
827 Generate a packet
828 Generate and install a matching flow
829 Add action to forward to OFPP_ALL
830 Add action to forward to ingress port
831 Send the packet to ingress dataplane port
832 Verify the packet is received at all other ports
833 """
834 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700835 of_ports = pa_port_map.keys()
836 of_ports.sort()
837 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
838
839 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700840 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700841 match.wildcards &= ~ofp.OFPFW_IN_PORT
842 self.assertTrue(match is not None,
843 "Could not generate flow match from pkt")
844 act = action.action_output()
845
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700846 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700847 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700848 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700849
Rich Lane9a003812012-10-04 17:17:59 -0700850 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700851 match.in_port = ingress_port
852
853 request = message.flow_mod()
854 request.match = match
855 request.buffer_id = 0xffffffff
856 act.port = ofp.OFPP_ALL
857 self.assertTrue(request.actions.add(act),
858 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700859 act.port = ofp.OFPP_IN_PORT
860 self.assertTrue(request.actions.add(act),
861 "Could not add ingress port for output")
Rich Lane9a003812012-10-04 17:17:59 -0700862 logging.info(request.show())
Dan Talayco3be5b062010-05-12 15:46:21 -0700863
Rich Lane9a003812012-10-04 17:17:59 -0700864 logging.info("Inserting flow")
Dan Talayco3be5b062010-05-12 15:46:21 -0700865 rv = self.controller.message_send(request)
866 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700867 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco3be5b062010-05-12 15:46:21 -0700868
Rich Lane9a003812012-10-04 17:17:59 -0700869 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco3be5b062010-05-12 15:46:21 -0700870 self.dataplane.send(ingress_port, str(pkt))
Rich Lane9a003812012-10-04 17:17:59 -0700871 receive_pkt_check(self.dataplane, pkt, of_ports, [], self, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700872
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700873class FloodMinusPort(basic.SimpleDataPlane):
874 """
875 Config port with No_Flood and test Flood action
876
877 Generate a packet
878 Generate a matching flow
879 Add action to forward to OFPP_ALL
880 Set port to no-flood
881 Send the packet to ingress dataplane port
882 Verify the packet is received at all other ports except
883 the ingress port and the no_flood port
884 """
885 def runTest(self):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700886 of_ports = pa_port_map.keys()
887 of_ports.sort()
888 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
889
890 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700891 match = packet_to_flow_match(self, pkt)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700892 match.wildcards &= ~ofp.OFPFW_IN_PORT
893 self.assertTrue(match is not None,
894 "Could not generate flow match from pkt")
895 act = action.action_output()
896
897 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700898 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700899 self.assertEqual(rv, 0, "Failed to delete all flows")
900
901 ingress_port = of_ports[idx]
902 no_flood_idx = (idx + 1) % len(of_ports)
903 no_flood_port = of_ports[no_flood_idx]
904 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700905 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700906 self.assertEqual(rv, 0, "Failed to set port config")
907
908 match.in_port = ingress_port
909
910 request = message.flow_mod()
911 request.match = match
912 request.buffer_id = 0xffffffff
913 act.port = ofp.OFPP_FLOOD
914 self.assertTrue(request.actions.add(act),
915 "Could not add flood port action")
Rich Lane9a003812012-10-04 17:17:59 -0700916 logging.info(request.show())
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700917
Rich Lane9a003812012-10-04 17:17:59 -0700918 logging.info("Inserting flow")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700919 rv = self.controller.message_send(request)
920 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700921 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700922
Rich Lane9a003812012-10-04 17:17:59 -0700923 logging.info("Sending packet to dp port " + str(ingress_port))
924 logging.info("No flood port is " + str(no_flood_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700925 self.dataplane.send(ingress_port, str(pkt))
926 no_ports = set([ingress_port, no_flood_port])
927 yes_ports = set(of_ports).difference(no_ports)
Rich Lane9a003812012-10-04 17:17:59 -0700928 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700929
930 # Turn no flood off again
931 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700932 0, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700933 self.assertEqual(rv, 0, "Failed to reset port config")
934
935 #@todo Should check no other packets received
936
Dan Talayco21381562010-07-17 00:34:47 -0700937
938
Dan Talayco551befa2010-07-15 17:05:32 -0700939################################################################
940
941class BaseMatchCase(basic.SimpleDataPlane):
942 def setUp(self):
943 basic.SimpleDataPlane.setUp(self)
Dan Talayco551befa2010-07-15 17:05:32 -0700944 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -0700945 logging.info("BaseMatchCase")
Dan Talayco551befa2010-07-15 17:05:32 -0700946
947class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700948 """
Dan Talayco551befa2010-07-15 17:05:32 -0700949 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700950
951 Generate a packet
952 Generate and install a matching flow without wildcard mask
953 Add action to forward to a port
954 Send the packet to the port
955 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700956 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700957
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700958 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700959 flow_match_test(self, pa_port_map)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700960
Dan Talayco551befa2010-07-15 17:05:32 -0700961class ExactMatchTagged(BaseMatchCase):
962 """
963 Exact match for all port pairs with tagged pkts
964 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700965
Dan Talayco551befa2010-07-15 17:05:32 -0700966 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700967 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700968 flow_match_test(self, pa_port_map, dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700969
Dan Talayco551befa2010-07-15 17:05:32 -0700970class ExactMatchTaggedMany(BaseMatchCase):
971 """
972 ExactMatchTagged with many VLANS
973 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700974
Dan Talayco551befa2010-07-15 17:05:32 -0700975 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700976 for vid in range(2,100,10):
Dan Talayco551befa2010-07-15 17:05:32 -0700977 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
978 for vid in range(100,4000,389):
979 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
980 flow_match_test(self, pa_port_map, dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700981
Dan Talayco551befa2010-07-15 17:05:32 -0700982# Don't run by default
983test_prio["ExactMatchTaggedMany"] = -1
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700984
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700985
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700986class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700987 """
988 SingleWildcardMatchPriority
989 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700990
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700991 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700992 self.pkt = simple_tcp_packet()
993 self.flowMsgs = {}
994
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700995 def _ClearTable(self):
Rich Lane9a003812012-10-04 17:17:59 -0700996 rc = delete_all_flows(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700997 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700998 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700999
1000 def runTest(self):
1001
1002 self._Init()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001003 of_ports = pa_port_map.keys()
1004 of_ports.sort()
1005
1006 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001007 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001008
1009 # Run several combinations, each at lower priority settings.
1010 # At the end of each call to runPrioFlows(), the table should
1011 # be empty. If its not, we'll catch it as the priorities decreases
1012 portA = of_ports[0]
1013 portB = of_ports[1]
1014 portC = of_ports[2]
1015
1016 # TODO -- these priority numbers should be validated somehow?
1017 self.runPrioFlows(portA, portB, portC, 1000, 999)
1018 self.runPrioFlows(portB, portC, portA, 998, 997)
1019 self.runPrioFlows(portC, portA, portB, 996, 995)
1020 self.runPrioFlows(portA, portC, portB, 994, 993)
1021
1022
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001023
1024 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
1025 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001026
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001027 if clearTable:
1028 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001029
1030 # Sanity check flow at lower priority from pA to pB
Rich Lane9a003812012-10-04 17:17:59 -07001031 logging.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001032 % (portA, portB, portC, prioHigher, prioLower))
1033
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001034 # Sanity check flow at lower priority from pA to pC
1035 self.installFlow(prioLower, portA, portC)
1036 self.verifyFlow(portA, portC)
1037 self.removeFlow(prioLower)
1038
1039 # Install and verify pA->pB @ prioLower
1040 self.installFlow(prioLower, portA, portB)
1041 self.verifyFlow(portA, portB)
1042
1043 # Install and verify pA->pC @ prioHigher, should override pA->pB
1044 self.installFlow(prioHigher, portA, portC)
1045 self.verifyFlow(portA, portC)
1046 # remove pA->pC
1047 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001048 # Old flow pA -> pB @ prioLower should still be active
1049 self.verifyFlow(portA, portB)
1050 self.removeFlow(prioLower)
1051
1052 # Table should be empty at this point, leave it alone as
1053 # an assumption for future test runs
1054
1055
1056
Ed Swierk99a74de2012-08-22 06:40:54 -07001057 def installFlow(self, prio, inp, egp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001058 wildcards=ofp.OFPFW_DL_SRC):
Ed Swierk99a74de2012-08-22 06:40:54 -07001059 wildcards |= required_wildcards(self)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001060 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001061 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001062 egr_ports=egp)
1063 request.priority = prio
Rich Lane9a003812012-10-04 17:17:59 -07001064 logging.debug("Install flow with priority " + str(prio))
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001065 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001066 self.flowMsgs[prio] = request
1067
1068 def removeFlow(self, prio):
1069 if self.flowMsgs.has_key(prio):
1070 msg = self.flowMsgs[prio]
1071 msg.command = ofp.OFPFC_DELETE_STRICT
1072 # This *must* be set for DELETE
1073 msg.out_port = ofp.OFPP_NONE
Rich Lane9a003812012-10-04 17:17:59 -07001074 logging.debug("Remove flow with priority " + str(prio))
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001075 self.controller.message_send(msg)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001076 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001077 else:
1078 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001079
1080
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001081 def verifyFlow(self, inp, egp, pkt=None):
1082 if pkt == None:
1083 pkt = self.pkt
1084
Rich Lane9a003812012-10-04 17:17:59 -07001085 logging.info("Pkt match test: " + str(inp) + " to " + str(egp))
1086 logging.debug("Send packet: " + str(inp) + " to " + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001087 self.dataplane.send(inp, str(pkt))
1088 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001089
1090
1091
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001092class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
1093
1094 def runTest(self):
1095
1096 self._Init()
1097
1098 of_ports = pa_port_map.keys()
1099 of_ports.sort()
1100
1101 # Install an entry from 0 -> 1 @ prio 1000
1102 self._ClearTable()
1103 self.installFlow(1000, of_ports[0], of_ports[1])
1104 self.verifyFlow(of_ports[0], of_ports[1])
1105 self.installFlow(1000, of_ports[1], of_ports[0])
1106 self.verifyFlow(of_ports[1], of_ports[0])
1107 self.installFlow(1001, of_ports[0], of_ports[1])
1108 self.verifyFlow(of_ports[0], of_ports[1])
1109 self.installFlow(1001, of_ports[1], of_ports[0])
1110 self.verifyFlow(of_ports[1], of_ports[0])
1111 self.removeFlow(1001)
1112 self.verifyFlow(of_ports[0], of_ports[1])
1113 self.removeFlow(1000)
1114
1115
1116
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001117class WildcardPriority(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001118 """
1119 1. Add wildcard flow, verify packet received.
1120 2. Add exact match flow with higher priority, verify packet received
1121 on port specified by this flow.
1122 3. Add wildcard flow with even higher priority, verify packet received
1123 on port specified by this flow.
1124 """
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001125
1126 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001127
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001128 self._Init()
1129
1130 of_ports = pa_port_map.keys()
1131 of_ports.sort()
1132
1133 self._ClearTable()
Ken Chiang38d7a152012-05-24 15:33:50 -07001134
1135 # Install a flow with wildcards
1136 self.installFlow(999, of_ports[0], of_ports[1],
1137 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001138 self.verifyFlow(of_ports[0], of_ports[1])
Ken Chiang38d7a152012-05-24 15:33:50 -07001139 # Install a flow with no wildcards for our packet
1140 self.installFlow(1000, of_ports[0], of_ports[2], wildcards=0)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001141 self.verifyFlow(of_ports[0], of_ports[2])
Ken Chiang38d7a152012-05-24 15:33:50 -07001142 # Install a flow with wildcards for our packet with higher
1143 # priority
1144 self.installFlow(1001, of_ports[0], of_ports[3])
1145 self.verifyFlow(of_ports[0], of_ports[3])
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001146
1147
Ken Chiang3978f242012-06-13 14:14:09 -07001148class WildcardPriorityWithDelete(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001149 """
1150 1. Add exact match flow, verify packet received.
1151 2. Add wildcard flow with higher priority, verify packet received on port
1152 specified by this flow.
1153 3. Add exact match flow with even higher priority, verify packet received
1154 on port specified by this flow.
1155 4. Delete lowest priority flow, verify packet received on port specified
1156 by highest priority flow.
1157 5. Delete highest priority flow, verify packet received on port specified
1158 by remaining flow.
1159 """
1160
1161 def runTest(self):
1162
1163 self._Init()
1164
1165 of_ports = pa_port_map.keys()
1166 of_ports.sort()
1167
1168 self._ClearTable()
1169
1170 # Install an exact match flow
1171 self.installFlow(250, of_ports[0], of_ports[1], wildcards=0)
1172 self.verifyFlow(of_ports[0], of_ports[1])
1173 # Install a flow with wildcards of higher priority
1174 self.installFlow(1250, of_ports[0], of_ports[2],
1175 wildcards=ofp.OFPFW_DL_DST)
1176 self.verifyFlow(of_ports[0], of_ports[2])
1177 # Install an exact match flow with even higher priority
1178 self.installFlow(2001, of_ports[0], of_ports[3], wildcards=0)
1179 self.verifyFlow(of_ports[0], of_ports[3])
1180 # Delete lowest priority flow
1181 self.removeFlow(250)
1182 self.verifyFlow(of_ports[0], of_ports[3])
1183 # Delete highest priority flow
1184 self.removeFlow(2001)
1185 self.verifyFlow(of_ports[0], of_ports[2])
1186
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001187
Dan Talayco551befa2010-07-15 17:05:32 -07001188class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001189 """
1190 Exercise wildcard matching for all ports
1191
1192 Generate a packet
1193 Generate and install a matching flow with wildcard mask
1194 Add action to forward to a port
1195 Send the packet to the port
1196 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001197 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001198 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001199 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -07001200 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001201 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001202 wc |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001203 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001204 # Set nonzero VLAN id to avoid sending priority-tagged packet
1205 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001206 else:
1207 dl_vlan = -1
1208 flow_match_test(self, pa_port_map, wildcards=wc,
1209 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001210
Dan Talayco551befa2010-07-15 17:05:32 -07001211class SingleWildcardMatchTagged(BaseMatchCase):
1212 """
1213 SingleWildcardMatch with tagged packets
1214 """
1215 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001216 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001217 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001218 wc |= required_wildcards(self)
Dan Talayco21381562010-07-17 00:34:47 -07001219 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -07001220 max_test=10)
1221
1222class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001223 """
Dan Talayco80b54ed2010-07-13 09:48:35 -07001224 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001225
1226 Generate a packet
1227 Generate and install a matching flow with wildcard all except one filed
1228 Add action to forward to a port
1229 Send the packet to the port
1230 Verify the packet is received at all other ports (one port at a time)
1231 Verify flow_expiration message is correct when command option is set
1232 """
1233 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -07001234 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001235 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001236 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001237 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001238 # Set nonzero VLAN id to avoid sending priority-tagged packet
1239 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001240 else:
1241 dl_vlan = -1
1242 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
1243 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001244
Dan Talayco551befa2010-07-15 17:05:32 -07001245class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1246 """
1247 Match one field with tagged packets
1248 """
1249 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001250 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001251 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001252 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco21381562010-07-17 00:34:47 -07001253 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
1254 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001255
1256class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001257 """
1258 Create Wildcard-all flow and exercise for all ports
1259
1260 Generate a packet
1261 Generate and install a matching flow with wildcard-all
1262 Add action to forward to a port
1263 Send the packet to the port
1264 Verify the packet is received at all other ports (one port at a time)
1265 Verify flow_expiration message is correct when command option is set
1266 """
1267 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -07001268 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001269
Dan Talayco551befa2010-07-15 17:05:32 -07001270class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001271 """
Dan Talayco551befa2010-07-15 17:05:32 -07001272 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001273 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001274 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001275 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -07001276 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
1277 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001278
Dan Talaycoba3745c2010-07-21 21:51:08 -07001279
Dan Talayco551befa2010-07-15 17:05:32 -07001280class AddVLANTag(BaseMatchCase):
1281 """
1282 Add a VLAN tag to an untagged packet
1283 """
1284 def runTest(self):
1285 new_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001286 sup_acts = self.supported_actions
Dan Talayco551befa2010-07-15 17:05:32 -07001287 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001288 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001289 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001290
Dan Talayco551befa2010-07-15 17:05:32 -07001291 len = 100
1292 len_w_vid = 104
1293 pkt = simple_tcp_packet(pktlen=len)
1294 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1295 dl_vlan=new_vid)
1296 vid_act = action.action_set_vlan_vid()
1297 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001298
Dan Talayco551befa2010-07-15 17:05:32 -07001299 flow_match_test(self, pa_port_map, pkt=pkt,
1300 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001301
Dan Talayco551befa2010-07-15 17:05:32 -07001302class PacketOnly(basic.DataPlaneOnly):
1303 """
1304 Just send a packet thru the switch
1305 """
1306 def runTest(self):
1307 pkt = simple_tcp_packet()
1308 of_ports = pa_port_map.keys()
1309 of_ports.sort()
1310 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001311 logging.info("Sending packet to " + str(ing_port))
1312 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001313 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001314
Dan Talayco551befa2010-07-15 17:05:32 -07001315class PacketOnlyTagged(basic.DataPlaneOnly):
1316 """
1317 Just send a packet thru the switch
1318 """
1319 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001320 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001321 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
1322 of_ports = pa_port_map.keys()
1323 of_ports.sort()
1324 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001325 logging.info("Sending packet to " + str(ing_port))
1326 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001327 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001328
Dan Talayco551befa2010-07-15 17:05:32 -07001329test_prio["PacketOnly"] = -1
1330test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001331
Dan Talayco551befa2010-07-15 17:05:32 -07001332class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001333 """
1334 Modify the VLAN ID in the VLAN tag of a tagged packet
1335 """
Dan Talaycoaf669322012-09-12 22:51:22 -07001336 def setUp(self):
1337 BaseMatchCase.setUp(self)
1338 self.ing_port=False
1339
Dan Talayco551befa2010-07-15 17:05:32 -07001340 def runTest(self):
1341 old_vid = 2
1342 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001343 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001344 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001345 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001346 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001347
Dan Talayco551befa2010-07-15 17:05:32 -07001348 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1349 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
1350 vid_act = action.action_set_vlan_vid()
1351 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001352
Dan Talayco551befa2010-07-15 17:05:32 -07001353 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoaf669322012-09-12 22:51:22 -07001354 action_list=[vid_act], ing_port=self.ing_port)
1355
1356class ModifyVIDToIngress(ModifyVID):
1357 """
1358 Modify the VLAN ID in the VLAN tag of a tagged packet and send to
1359 ingress port
1360 """
1361 def setUp(self):
1362 BaseMatchCase.setUp(self)
1363 self.ing_port=True
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001364
Ken Chiange9a211d2012-04-20 14:52:11 -07001365class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1366 """
1367 With vlan ID and priority wildcarded, perform SET_VLAN_VID action.
1368 The same flow should match on both untagged and tagged packets.
1369 """
1370 def runTest(self):
1371 old_vid = 2
1372 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001373 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001374 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1375 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1376 return
1377
1378 of_ports = pa_port_map.keys()
1379 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1380 ing_port = of_ports[0]
1381 egr_ports = of_ports[1]
1382
Rich Lane9a003812012-10-04 17:17:59 -07001383 rv = delete_all_flows(self.controller)
Ken Chiange9a211d2012-04-20 14:52:11 -07001384 self.assertEqual(rv, 0, "Failed to delete all flows")
1385
1386 len_untagged = 100
1387 len_w_vid = 104
1388 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1389 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
1390 dl_vlan_enable=True, dl_vlan=old_vid)
1391 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1392 dl_vlan=new_vid)
Ed Swierk99a74de2012-08-22 06:40:54 -07001393 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1394 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001395 vid_act = action.action_set_vlan_vid()
1396 vid_act.vlan_vid = new_vid
1397 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
1398 wildcards=wildcards, egr_ports=egr_ports,
1399 action_list=[vid_act])
1400 flow_msg_install(self, request)
1401
Rich Lane9a003812012-10-04 17:17:59 -07001402 logging.debug("Send untagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001403 str(egr_ports))
1404 self.dataplane.send(ing_port, str(untagged_pkt))
1405 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1406
Rich Lane9a003812012-10-04 17:17:59 -07001407 logging.debug("Send tagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001408 str(egr_ports))
1409 self.dataplane.send(ing_port, str(tagged_pkt))
1410 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1411
Howard Pershc1199d52012-04-11 14:21:32 -07001412class ModifyVlanPcp(BaseMatchCase):
1413 """
1414 Modify the priority field of the VLAN tag of a tagged packet
1415 """
1416 def runTest(self):
1417 vid = 123
1418 old_vlan_pcp = 2
1419 new_vlan_pcp = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001420 sup_acts = self.supported_actions
Ed Swierk8c3af7f2012-04-24 14:19:17 -07001421 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_PCP):
1422 skip_message_emit(self, "Modify VLAN priority test")
Howard Pershc1199d52012-04-11 14:21:32 -07001423 return
1424
1425 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1426 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1427 vid_act = action.action_set_vlan_pcp()
1428 vid_act.vlan_pcp = new_vlan_pcp
1429
1430 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1431 action_list=[vid_act])
1432
Dan Talayco551befa2010-07-15 17:05:32 -07001433class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001434 """
1435 Strip the VLAN tag from a tagged packet
1436 """
Dan Talayco551befa2010-07-15 17:05:32 -07001437 def runTest(self):
1438 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001439 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001440 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001441 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001442 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001443
Dan Talayco551befa2010-07-15 17:05:32 -07001444 len_w_vid = 104
1445 len = 100
1446 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1447 dl_vlan=old_vid)
1448 exp_pkt = simple_tcp_packet(pktlen=len)
1449 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001450
Dan Talayco551befa2010-07-15 17:05:32 -07001451 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1452 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001453
Ken Chiange9a211d2012-04-20 14:52:11 -07001454class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1455 """
1456 Strip the VLAN tag from a tagged packet.
1457 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1458 """
1459 def runTest(self):
1460 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001461 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001462 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1463 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1464 return
1465
1466 len_w_vid = 104
1467 len_untagged = 100
1468 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1469 dl_vlan=old_vid)
1470 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
Ed Swierk99a74de2012-08-22 06:40:54 -07001471 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1472 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001473 vid_act = action.action_strip_vlan()
1474
1475 flow_match_test(self, pa_port_map,
Ed Swierk99a74de2012-08-22 06:40:54 -07001476 wildcards=wildcards,
Ken Chiange9a211d2012-04-20 14:52:11 -07001477 pkt=pkt, exp_pkt=exp_pkt,
1478 action_list=[vid_act])
1479
Dan Talayco4b2bee62010-07-20 14:10:05 -07001480def init_pkt_args():
1481 """
1482 Pass back a dictionary with default packet arguments
1483 """
1484 args = {}
1485 args["dl_src"] = '00:23:45:67:89:AB'
1486
1487 dl_vlan_enable=False
1488 dl_vlan=-1
1489 if pa_config["test-params"]["vid"]:
1490 dl_vlan_enable=True
1491 dl_vlan = pa_config["test-params"]["vid"]
1492
1493# Unpack operator is ** on a dictionary
1494
1495 return args
1496
Dan Talayco551befa2010-07-15 17:05:32 -07001497class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001498 """
1499 Modify the source MAC address (TP1)
1500 """
Dan Talayco551befa2010-07-15 17:05:32 -07001501 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001502 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001503 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001504 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001505 return
1506
1507 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1508 check_test_params=True)
1509 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1510 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001511
Dan Talayco551befa2010-07-15 17:05:32 -07001512class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001513 """
1514 Modify the dest MAC address (TP1)
1515 """
Dan Talayco551befa2010-07-15 17:05:32 -07001516 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001517 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001518 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001519 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001520 return
1521
1522 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1523 check_test_params=True)
1524 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1525 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001526
Dan Talayco551befa2010-07-15 17:05:32 -07001527class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001528 """
1529 Modify the source IP address of an IP packet (TP1)
1530 """
Dan Talayco551befa2010-07-15 17:05:32 -07001531 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001532 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001533 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001534 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001535 return
1536
1537 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1538 check_test_params=True)
1539 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1540 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001541
Dan Talayco551befa2010-07-15 17:05:32 -07001542class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001543 """
1544 Modify the dest IP address of an IP packet (TP1)
1545 """
Dan Talayco551befa2010-07-15 17:05:32 -07001546 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001547 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001548 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001549 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001550 return
1551
1552 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1553 check_test_params=True)
1554 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1555 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001556
1557class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001558 """
1559 Modify the source TCP port of a TCP packet (TP1)
1560 """
Dan Talayco551befa2010-07-15 17:05:32 -07001561 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001562 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001563 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001564 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001565 return
1566
1567 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1568 check_test_params=True)
1569 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1570 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001571
1572class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001573 """
1574 Modify the dest TCP port of a TCP packet (TP1)
1575 """
Dan Talayco551befa2010-07-15 17:05:32 -07001576 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001577 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001578 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001579 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001580 return
1581
1582 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1583 check_test_params=True)
1584 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1585 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001586
1587class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001588 """
1589 Modify the IP type of service of an IP packet (TP1)
1590 """
Dan Talayco551befa2010-07-15 17:05:32 -07001591 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001592 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001593 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001594 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001595 return
Dan Talayco551befa2010-07-15 17:05:32 -07001596
Dan Talayco4b2bee62010-07-20 14:10:05 -07001597 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1598 check_test_params=True)
1599 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001600 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001601
Dan Talaycof6e76c02012-03-23 10:56:12 -07001602class ModifyL2DstMC(BaseMatchCase):
1603 """
1604 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001605 """
1606 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001607 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001608 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001609 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001610 return
1611
Dan Talaycof6e76c02012-03-23 10:56:12 -07001612 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1613 check_test_params=True)
1614 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001615 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001616
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001617class ModifyL2DstIngress(BaseMatchCase):
1618 """
1619 Modify the L2 dest and send to the ingress port
1620 """
1621 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001622 sup_acts = self.supported_actions
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001623 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001624 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001625 return
1626
1627 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1628 check_test_params=True)
1629 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1630 action_list=acts, max_test=2, egr_count=0,
1631 ing_port=True)
1632
Dan Talaycod8ae7582012-03-23 12:24:56 -07001633class ModifyL2DstIngressMC(BaseMatchCase):
1634 """
1635 Modify the L2 dest and send to the ingress port
1636 """
1637 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001638 sup_acts = self.supported_actions
Dan Talaycod8ae7582012-03-23 12:24:56 -07001639 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1640 skip_message_emit(self, "ModifyL2dstMC test")
1641 return
1642
1643 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1644 check_test_params=True)
1645 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1646 action_list=acts, max_test=2, egr_count=-1,
1647 ing_port=True)
1648
Dan Talaycof6e76c02012-03-23 10:56:12 -07001649class ModifyL2SrcMC(BaseMatchCase):
1650 """
1651 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001652 """
1653 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001654 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001655 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001656 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001657 return
1658
Dan Talaycof6e76c02012-03-23 10:56:12 -07001659 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1660 check_test_params=True)
1661 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001662 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001663
1664class ModifyL2SrcDstMC(BaseMatchCase):
1665 """
1666 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001667 """
1668 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001669 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001670 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1671 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1672 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001673 return
1674
Dan Talaycof6e76c02012-03-23 10:56:12 -07001675 mod_fields = ['dl_dst', 'dl_src']
1676 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1677 check_test_params=True)
1678 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001679 action_list=acts, max_test=2, egr_count=-1)
1680
1681class ModifyL2DstVIDMC(BaseMatchCase):
1682 """
1683 Modify the L2 dest and send to 2 ports
1684 """
1685 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001686 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001687 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1688 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1689 skip_message_emit(self, "ModifyL2DstVIDMC test")
1690 return
1691
1692 mod_fields = ['dl_dst', 'dl_vlan']
1693 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1694 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1695 check_test_params=True)
1696 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1697 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001698
Dan Talaycofa6454f2012-04-05 10:04:13 -07001699class FlowToggle(BaseMatchCase):
1700 """
1701 Add flows to the table and modify them repeatedly
Dan Talaycof7c41312012-07-23 12:53:19 -07001702
1703 This is done by using only "add" flow messages. Since the check overlap
1704 flag is not set, the switch is supposed to modify the existing flow if
1705 the match already exists.
1706
1707 Would probably be better to exercise more of the flow modify commands
1708 (add, modify, delete +/- strict).
Dan Talaycofa6454f2012-04-05 10:04:13 -07001709 """
1710 def runTest(self):
Dan Talayco50be7672012-04-05 11:38:08 -07001711 flow_count = test_param_get(self.config, 'ft_flow_count', default=20)
1712 iter_count = test_param_get(self.config, 'ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001713
Rich Lane9a003812012-10-04 17:17:59 -07001714 logging.info("Running flow toggle with %d flows, %d iterations" %
Dan Talaycofa6454f2012-04-05 10:04:13 -07001715 (flow_count, iter_count))
1716 acts = []
1717 acts.append(action.action_output())
1718 acts.append(action.action_output())
1719
1720 of_ports = pa_port_map.keys()
1721 if len(of_ports) < 3:
1722 self.assertTrue(False, "Too few ports for test")
1723
1724 for idx in range(2):
1725 acts[idx].port = of_ports[idx]
1726
1727 flows = []
1728 flows.append([])
1729 flows.append([])
1730
Ed Swierk99a74de2012-08-22 06:40:54 -07001731 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_SRC |
1732 ofp.OFPFW_DL_DST)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001733 # Create up the flows in an array
1734 for toggle in range(2):
1735 for f_idx in range(flow_count):
1736 pkt = simple_tcp_packet(tcp_sport=f_idx)
1737 msg = message.flow_mod()
Ed Swierk99a74de2012-08-22 06:40:54 -07001738 match = packet_to_flow_match(self, pkt)
Shudong Zhou031373c2012-07-19 17:37:42 -07001739 match.in_port = of_ports[2]
Dan Talayco50be7672012-04-05 11:38:08 -07001740 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001741 msg.match = match
1742 msg.buffer_id = 0xffffffff
Dan Talaycof7c41312012-07-23 12:53:19 -07001743 msg.command = ofp.OFPFC_ADD
Dan Talaycofa6454f2012-04-05 10:04:13 -07001744 msg.actions.add(acts[toggle])
1745 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001746
1747 # Show two sample flows
Rich Lane9a003812012-10-04 17:17:59 -07001748 logging.debug(flows[0][0].show())
1749 logging.debug(flows[1][0].show())
Dan Talayco50be7672012-04-05 11:38:08 -07001750
Dan Talaycofa6454f2012-04-05 10:04:13 -07001751 # Install the first set of flows
1752 for f_idx in range(flow_count):
1753 rv = self.controller.message_send(flows[0][f_idx])
1754 self.assertTrue(rv != -1, "Error installing flow %d" % f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001755 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycofa6454f2012-04-05 10:04:13 -07001756
Rich Lane9a003812012-10-04 17:17:59 -07001757 logging.info("Installed %d flows" % flow_count)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001758
1759 # Repeatedly modify all the flows back and forth
1760 updates = 0
1761 # Report status about 5 times
1762 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001763 start = time.time()
1764 for iter_idx in range(iter_count):
1765 if not iter_idx % mod_val:
Rich Lane9a003812012-10-04 17:17:59 -07001766 logging.info("Flow Toggle: iter %d of %d. " %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001767 (iter_idx, iter_count) +
1768 "%d updates in %d secs" %
1769 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001770 for toggle in range(2):
1771 t_idx = 1 - toggle
1772 for f_idx in range(flow_count):
1773 rv = self.controller.message_send(flows[t_idx][f_idx])
1774 updates += 1
1775 self.assertTrue(rv != -1, "Error modifying flow %d" %
1776 f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001777 self.assertEqual(do_barrier(self.controller), 0,
1778 "Barrier failed")
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001779
1780 end = time.time()
1781 divisor = end - start or (end - start + 1)
Rich Lane9a003812012-10-04 17:17:59 -07001782 logging.info("Flow toggle: %d iterations" % iter_count)
1783 logging.info(" %d flow mods in %d secs, %d mods/sec" %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001784 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001785
1786
Dan Talayco8a64e332012-03-28 14:53:20 -07001787# You can pick and choose these by commenting tests in or out
1788iter_classes = [
1789 basic.PacketIn,
1790 basic.PacketOut,
1791 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001792 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001793 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001794 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001795 AllWildcardMatch,
1796 AllWildcardMatchTagged,
1797 SingleWildcardMatch,
1798 SingleWildcardMatchTagged,
1799 ExactMatch,
1800 ExactMatchTagged,
1801 SingleWildcardMatch,
1802 ModifyL2Src,
1803 ModifyL2Dst,
1804 ModifyL2SrcMC,
1805 ModifyL2DstMC,
1806 ModifyL2SrcDstMC
1807 ]
1808
1809class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001810 """
1811 Iterate over a bunch of test cases
1812
1813 The cases come from the list above
1814 """
1815
Dan Talayco8a64e332012-03-28 14:53:20 -07001816 def runTest(self):
1817 count = test_param_get(self.config, 'iter_count', default=10)
1818 tests_done = 0
Rich Lane9a003812012-10-04 17:17:59 -07001819 logging.info("Running iteration test " + str(count) + " times")
Dan Talayco8a64e332012-03-28 14:53:20 -07001820 start = time.time()
1821 last = start
1822 for idx in range(count):
Rich Lane9a003812012-10-04 17:17:59 -07001823 logging.info("Iteration " + str(idx + 1))
Dan Talayco8a64e332012-03-28 14:53:20 -07001824 for cls in iter_classes:
1825 test = cls()
1826 test.inheritSetup(self)
1827 test.runTest()
1828 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001829 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001830 if time.time() - last > 60:
1831 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001832 logging.info(
Dan Talaycofa6454f2012-04-05 10:04:13 -07001833 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1834 (idx, count, tests_done, last - start) +
1835 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001836 stats = all_stats_get(self)
1837 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001838 logging.info("\nIterCases ran %d tests in %d seconds." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001839 (tests_done, last - start))
Rich Lane9a003812012-10-04 17:17:59 -07001840 logging.info(" flows: %d. packets: %d. bytes: %d" %
Dan Talayco8a64e332012-03-28 14:53:20 -07001841 (stats["flows"], stats["packets"], stats["bytes"]))
Rich Lane9a003812012-10-04 17:17:59 -07001842 logging.info(" active: %d. lookups: %d. matched %d." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001843 (stats["active"], stats["lookups"], stats["matched"]))
1844
1845# Don't run by default
1846test_prio["IterCases"] = -1
Dan Talaycof6e76c02012-03-23 10:56:12 -07001847
Dan Talayco4b2bee62010-07-20 14:10:05 -07001848#@todo Need to implement tagged versions of the above tests
1849#
1850#@todo Implement a test case that strips tag 2, adds tag 3
1851# and modifies tag 4 to tag 5. Then verify (in addition) that
1852# tag 6 does not get modified.
1853
1854class MixedVLAN(BaseMatchCase):
1855 """
1856 Test mixture of VLAN tag actions
1857
1858 Strip tag 2 on port 1, send to port 2
1859 Add tag 3 on port 1, send to port 2
1860 Modify tag 4 to 5 on port 1, send to port 2
1861 All other traffic from port 1, send to port 3
1862 All traffic from port 2 sent to port 4
1863 Use exact matches with different packets for all mods
1864 Verify the following: (port, vid)
1865 (port 1, vid 2) => VLAN tag stripped, out port 2
1866 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1867 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1868 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1869 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1870 (port 2, no tag) => untagged packet out port 4
1871 (port 2, vid 2-6) => unmodified packet out port 4
1872
1873 Variation: Might try sending VID 5 to port 3 and check.
1874 If only VID 5 distinguishes pkt, this will fail on some platforms
1875 """
1876
1877test_prio["MixedVLAN"] = -1
Rich Lane8d6ab272012-09-23 18:06:20 -07001878
1879class MatchEach(basic.SimpleDataPlane):
1880 """
1881 Check that each match field is actually matched on.
1882 Installs two flows that differ in one field. The flow that should not
1883 match has a higher priority, so if that field is ignored during matching
1884 the packet will be sent out the wrong port.
1885
1886 TODO test UDP, ARP, ICMP, etc.
1887 """
1888 def runTest(self):
1889 of_ports = pa_port_map.keys()
1890 of_ports.sort()
1891 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1892
Rich Lane9a003812012-10-04 17:17:59 -07001893 delete_all_flows(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001894
1895 pkt = simple_tcp_packet()
1896 ingress_port = of_ports[0]
1897 egress_port = of_ports[1]
1898
1899 def testField(field, mask):
Rich Lane9a003812012-10-04 17:17:59 -07001900 logging.info("Testing field %s" % field)
Rich Lane8d6ab272012-09-23 18:06:20 -07001901
1902 def addFlow(matching, priority, output_port):
1903 match = packet_to_flow_match(self, pkt)
1904 self.assertTrue(match is not None, "Could not generate flow match from pkt")
1905 match.wildcards &= ~ofp.OFPFW_IN_PORT
1906 match.in_port = ingress_port
1907 if not matching:
1908 # Make sure flow doesn't match
1909 orig = getattr(match, field)
1910 if isinstance(orig, list):
1911 new = map(lambda a: ~a[0] & a[1], zip(orig, mask))
1912 else:
1913 new = ~orig & mask
1914 setattr(match, field, new)
1915 request = message.flow_mod()
1916 request.match = match
1917 request.buffer_id = 0xffffffff
1918 request.priority = priority
1919 act = action.action_output()
1920 act.port = output_port
1921 self.assertTrue(request.actions.add(act), "Could not add action")
Rich Lane9a003812012-10-04 17:17:59 -07001922 logging.info("Inserting flow")
Rich Lane8d6ab272012-09-23 18:06:20 -07001923 self.controller.message_send(request)
1924
1925 # This flow should match.
1926 addFlow(matching=True, priority=0, output_port=egress_port)
1927 # This flow should not match, but it has a higher priority.
1928 addFlow(matching=False, priority=1, output_port=ofp.OFPP_IN_PORT)
1929
1930 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
1931
Rich Lane9a003812012-10-04 17:17:59 -07001932 logging.info("Sending packet to dp port " + str(ingress_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001933 self.dataplane.send(ingress_port, str(pkt))
1934
1935 exp_pkt_arg = None
1936 exp_port = None
1937 if pa_config["relax"]:
1938 exp_pkt_arg = pkt
1939 exp_port = egress_port
1940
1941 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
1942 exp_pkt=exp_pkt_arg)
1943 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -07001944 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001945 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
1946 self.assertEqual(str(pkt), str(rcv_pkt), 'Response packet does not match send packet')
1947
1948 # TODO in_port
1949 testField("dl_src", [0xff]*6)
1950 testField("dl_dst", [0xff]*6)
1951 testField("dl_type", 0xffff)
1952 testField("dl_vlan", 0xfff)
1953 # TODO dl_vlan_pcp
1954 testField("nw_src", 0xffffffff)
1955 testField("nw_dst", 0xffffffff)
1956 testField("nw_tos", 0x3f)
1957 testField("nw_proto", 0xff)
1958 testField("tp_src", 0xffff)
1959 testField("tp_dst", 0xffff)
1960
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001961if __name__ == "__main__":
1962 print "Please run through oft script: ./oft --test_spec=basic"