blob: d22690c41de3ee7367f838a24d7155ef35635ff9 [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 -070041WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
Dan Talayco488fbc52012-04-09 16:30:41 -070042 ofp.OFPFW_DL_VLAN | ofp.OFPFW_DL_VLAN_PCP,
Dan Talayco551befa2010-07-15 17:05:32 -070043 ofp.OFPFW_DL_SRC,
44 ofp.OFPFW_DL_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070045 (ofp.OFPFW_DL_TYPE | ofp.OFPFW_NW_SRC_ALL |
46 ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS | ofp.OFPFW_NW_PROTO |
47 ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
48 (ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
Dan Talayco551befa2010-07-15 17:05:32 -070049 ofp.OFPFW_TP_SRC,
50 ofp.OFPFW_TP_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070051 ofp.OFPFW_NW_SRC_MASK,
52 ofp.OFPFW_NW_DST_MASK,
Dan Talayco551befa2010-07-15 17:05:32 -070053 ofp.OFPFW_DL_VLAN_PCP,
54 ofp.OFPFW_NW_TOS]
55
Dan Talayco488fbc52012-04-09 16:30:41 -070056NO_WILDCARD_VALUES = [(ofp.OFPFW_ALL ^ ofp.OFPFW_IN_PORT),
57 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN),
58 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_SRC),
59 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_DST),
60 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE),
61 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO),
62 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
63 ofp.OFPFW_TP_SRC),
64 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
65 ofp.OFPFW_TP_DST),
66 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
67 ofp.OFPFW_NW_SRC_MASK),
68 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
69 ofp.OFPFW_NW_DST_MASK),
70 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN ^ ofp.OFPFW_DL_VLAN_PCP),
71 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
72 ofp.OFPFW_NW_TOS)]
73
Dan Talayco551befa2010-07-15 17:05:32 -070074MODIFY_ACTION_VALUES = [ofp.OFPAT_SET_VLAN_VID,
75 ofp.OFPAT_SET_VLAN_PCP,
76 ofp.OFPAT_STRIP_VLAN,
77 ofp.OFPAT_SET_DL_SRC,
78 ofp.OFPAT_SET_DL_DST,
79 ofp.OFPAT_SET_NW_SRC,
80 ofp.OFPAT_SET_NW_DST,
81 ofp.OFPAT_SET_NW_TOS,
82 ofp.OFPAT_SET_TP_SRC,
83 ofp.OFPAT_SET_TP_DST]
84
Dan Talayco21381562010-07-17 00:34:47 -070085TEST_VID_DEFAULT = 2
86
Dan Talayco5eba8442010-03-10 13:58:43 -080087def test_set_init(config):
88 """
89 Set up function for packet action test classes
90
91 @param config The configuration dictionary; see oft
92 """
93
Ed Swierk89f78352012-03-29 12:32:32 -070094 basic.test_set_init(config)
95
Dan Talayco5eba8442010-03-10 13:58:43 -080096 global pa_port_map
Dan Talayco5eba8442010-03-10 13:58:43 -080097 global pa_config
98
Dan Talayco5eba8442010-03-10 13:58:43 -080099 pa_port_map = config["port_map"]
100 pa_config = config
101
102class DirectPacket(basic.SimpleDataPlane):
103 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700104 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -0800105
106 Generate a packet
107 Generate and install a matching flow
108 Add action to direct the packet to an egress port
109 Send the packet to ingress dataplane port
110 Verify the packet is received at the egress port only
111 """
112 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700113 self.handleFlow()
114
115 def handleFlow(self, pkttype='TCP'):
Dan Talayco5eba8442010-03-10 13:58:43 -0800116 of_ports = pa_port_map.keys()
117 of_ports.sort()
118 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
119
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700120 if (pkttype == 'ICMP'):
121 pkt = simple_icmp_packet()
122 else:
123 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700124 match = packet_to_flow_match(self, pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700125 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800126 self.assertTrue(match is not None,
127 "Could not generate flow match from pkt")
128 act = action.action_output()
129
130 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700131 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700132 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700133
Dan Talayco5eba8442010-03-10 13:58:43 -0800134 ingress_port = of_ports[idx]
135 egress_port = of_ports[(idx + 1) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700136 logging.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700137 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800138
139 match.in_port = ingress_port
140
141 request = message.flow_mod()
142 request.match = match
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700143
Dan Talayco5eba8442010-03-10 13:58:43 -0800144 request.buffer_id = 0xffffffff
145 act.port = egress_port
146 self.assertTrue(request.actions.add(act), "Could not add action")
147
Rich Lane9a003812012-10-04 17:17:59 -0700148 logging.info("Inserting flow")
Dan Talayco5eba8442010-03-10 13:58:43 -0800149 rv = self.controller.message_send(request)
150 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700151 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco5eba8442010-03-10 13:58:43 -0800152
Rich Lane9a003812012-10-04 17:17:59 -0700153 logging.info("Sending packet to dp port " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800154 str(ingress_port))
155 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700156
157 exp_pkt_arg = None
158 exp_port = None
159 if pa_config["relax"]:
160 exp_pkt_arg = pkt
161 exp_port = egress_port
162
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700163 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700164 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800165 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700166 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800167 str(rcv_port))
168 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
169 self.assertEqual(str(pkt), str(rcv_pkt),
170 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700171
Rich Lane51c23b32012-07-27 16:37:25 -0700172class DirectPacketController(basic.SimpleDataPlane):
173 """
174 Send packet to the controller port
175
176 Generate a packet
177 Generate and install a matching flow
178 Add action to direct the packet to the controller port
179 Send the packet to ingress dataplane port
180 Verify the packet is received at the controller port
181 """
182 def runTest(self):
183 self.handleFlow()
184
185 def handleFlow(self, pkttype='TCP'):
186 of_ports = pa_port_map.keys()
187 of_ports.sort()
188 self.assertTrue(len(of_ports) > 0, "Not enough ports for test")
189
190 if (pkttype == 'ICMP'):
191 pkt = simple_icmp_packet()
192 else:
193 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700194 match = packet_to_flow_match(self, pkt)
Rich Lane51c23b32012-07-27 16:37:25 -0700195 match.wildcards &= ~ofp.OFPFW_IN_PORT
196 self.assertTrue(match is not None,
197 "Could not generate flow match from pkt")
198 act = action.action_output()
199
Rich Lane9a003812012-10-04 17:17:59 -0700200 rv = delete_all_flows(self.controller)
Rich Lane51c23b32012-07-27 16:37:25 -0700201 self.assertEqual(rv, 0, "Failed to delete all flows")
202
203 ingress_port = of_ports[0]
204 match.in_port = ingress_port
205
206 request = message.flow_mod()
207 request.match = match
208
209 request.buffer_id = 0xffffffff
210 act.port = ofp.OFPP_CONTROLLER
211 act.max_len = 65535
212 self.assertTrue(request.actions.add(act), "Could not add action")
213
Rich Lane9a003812012-10-04 17:17:59 -0700214 logging.info("Inserting flow")
Rich Lane51c23b32012-07-27 16:37:25 -0700215 rv = self.controller.message_send(request)
216 self.assertTrue(rv != -1, "Error installing flow mod")
217 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
218
Rich Lane9a003812012-10-04 17:17:59 -0700219 logging.info("Sending packet to dp port " +
Rich Lane51c23b32012-07-27 16:37:25 -0700220 str(ingress_port))
221 self.dataplane.send(ingress_port, str(pkt))
222
223 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
224
225 self.assertTrue(response is not None,
226 'Packet in message not received by controller')
227 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700228 logging.debug("Sent %s" % format_packet(pkt))
229 logging.debug("Resp %s" % format_packet(response.data))
Rich Lane51c23b32012-07-27 16:37:25 -0700230 self.assertTrue(False,
231 'Response packet does not match send packet' +
232 ' for controller port')
233
Howard Pershf97840f2012-04-10 16:30:42 -0700234
235class DirectPacketQueue(basic.SimpleDataPlane):
236 """
237 Send packet to single queue on single egress port
238
239 Generate a packet
240 Generate and install a matching flow
241 Add action to direct the packet to an egress port and queue
242 Send the packet to ingress dataplane port
243 Verify the packet is received at the egress port only
244 """
245 def runTest(self):
246 self.handleFlow()
247
Howard Persh670b5672012-04-13 09:08:29 -0700248 def portQueuesGet(self, queue_stats, port_num):
249 result = []
250 for qs in queue_stats.stats:
251 if qs.port_no != port_num:
252 continue
253 result.append(qs.queue_id)
254 return result
255
Howard Pershf97840f2012-04-10 16:30:42 -0700256 def handleFlow(self, pkttype='TCP'):
257 of_ports = pa_port_map.keys()
258 of_ports.sort()
259 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
260
261 if (pkttype == 'ICMP'):
262 pkt = simple_icmp_packet()
263 else:
264 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700265 match = packet_to_flow_match(self, pkt)
Howard Pershf97840f2012-04-10 16:30:42 -0700266 match.wildcards &= ~ofp.OFPFW_IN_PORT
267 self.assertTrue(match is not None,
268 "Could not generate flow match from pkt")
269
Howard Persh670b5672012-04-13 09:08:29 -0700270 # Get queue stats from switch
271
272 request = message.queue_stats_request()
273 request.port_no = ofp.OFPP_ALL
274 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700275 (queue_stats, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700276 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
277
278 act = action.action_enqueue()
Howard Pershf97840f2012-04-10 16:30:42 -0700279
280 for idx in range(len(of_ports)):
Howard Pershf97840f2012-04-10 16:30:42 -0700281 ingress_port = of_ports[idx]
282 egress_port = of_ports[(idx + 1) % len(of_ports)]
Howard Pershf97840f2012-04-10 16:30:42 -0700283
Howard Persh670b5672012-04-13 09:08:29 -0700284 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700285 logging.info("Ingress " + str(ingress_port)
Howard Persh670b5672012-04-13 09:08:29 -0700286 + " to egress " + str(egress_port)
287 + " queue " + str(egress_queue_id)
288 )
Howard Pershf97840f2012-04-10 16:30:42 -0700289
Rich Lane9a003812012-10-04 17:17:59 -0700290 rv = delete_all_flows(self.controller)
Howard Persh670b5672012-04-13 09:08:29 -0700291 self.assertEqual(rv, 0, "Failed to delete all flows")
Howard Pershf97840f2012-04-10 16:30:42 -0700292
Howard Persh670b5672012-04-13 09:08:29 -0700293 match.in_port = ingress_port
294
295 request = message.flow_mod()
296 request.match = match
Howard Pershf97840f2012-04-10 16:30:42 -0700297
Howard Persh670b5672012-04-13 09:08:29 -0700298 request.buffer_id = 0xffffffff
299 act.port = egress_port
300 act.queue_id = egress_queue_id
301 self.assertTrue(request.actions.add(act), "Could not add action")
Howard Pershf97840f2012-04-10 16:30:42 -0700302
Rich Lane9a003812012-10-04 17:17:59 -0700303 logging.info("Inserting flow")
Howard Persh670b5672012-04-13 09:08:29 -0700304 rv = self.controller.message_send(request)
305 self.assertTrue(rv != -1, "Error installing flow mod")
306 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Howard Pershf97840f2012-04-10 16:30:42 -0700307
Howard Persh670b5672012-04-13 09:08:29 -0700308 # Get current stats for selected egress queue
Howard Pershf97840f2012-04-10 16:30:42 -0700309
Howard Persh670b5672012-04-13 09:08:29 -0700310 request = message.queue_stats_request()
311 request.port_no = egress_port
312 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700313 (qs_before, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700314 self.assertNotEqual(qs_before, None, "Queue stats request failed")
315
Rich Lane9a003812012-10-04 17:17:59 -0700316 logging.info("Sending packet to dp port " +
Howard Persh670b5672012-04-13 09:08:29 -0700317 str(ingress_port))
318 self.dataplane.send(ingress_port, str(pkt))
319
320 exp_pkt_arg = None
321 exp_port = None
322 if pa_config["relax"]:
323 exp_pkt_arg = pkt
324 exp_port = egress_port
325
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700326 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Howard Persh670b5672012-04-13 09:08:29 -0700327 exp_pkt=exp_pkt_arg)
328 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700329 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Howard Persh670b5672012-04-13 09:08:29 -0700330 str(rcv_port))
331 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
332 self.assertEqual(str(pkt), str(rcv_pkt),
333 'Response packet does not match send packet')
334
Ed Swierkb8a86512012-04-18 18:45:58 -0700335 # FIXME: instead of sleeping, keep requesting queue stats until
336 # the expected queue counter increases or some large timeout is
337 # reached
338 time.sleep(2)
339
Howard Persh670b5672012-04-13 09:08:29 -0700340 # Get current stats for selected egress queue again
341
342 request = message.queue_stats_request()
343 request.port_no = egress_port
344 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700345 (qs_after, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700346 self.assertNotEqual(qs_after, None, "Queue stats request failed")
347
348 # Make sure that tx packet counter for selected egress queue was
349 # incremented
350
Ed Swierk22f59152012-04-17 16:36:47 -0700351 self.assertEqual(qs_after.stats[0].tx_packets, \
352 qs_before.stats[0].tx_packets + 1, \
Howard Persh670b5672012-04-13 09:08:29 -0700353 "Verification of egress queue tx packet count failed"
354 )
355
356
Ken Chiang899ff8e2012-05-23 18:26:12 -0700357class DirectPacketControllerQueue(basic.SimpleDataPlane):
358 """
359 Send a packet from each of the openflow ports
360 to each of the queues configured on the controller port.
361 If no queues have been configured, no packets are sent.
Howard Pershf97840f2012-04-10 16:30:42 -0700362
Ken Chiang899ff8e2012-05-23 18:26:12 -0700363 Generate a packet
364 Generate and install a matching flow
365 Add action to direct the packet to one of the controller port queues
366 Send the packet to ingress dataplane port
367 Verify the packet is received on the controller port queue
368 """
369 def runTest(self):
370 self.handleFlow()
371
372 def portQueuesGet(self, queue_stats, port_num):
373 result = []
374 for qs in queue_stats.stats:
375 if qs.port_no != port_num:
376 continue
377 result.append(qs.queue_id)
378 return result
379
380 def handleFlow(self, pkttype='TCP'):
381 of_ports = pa_port_map.keys()
382 of_ports.sort()
383 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
384
385 if (pkttype == 'ICMP'):
386 pkt = simple_icmp_packet()
387 else:
388 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700389 match = packet_to_flow_match(self, pkt)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700390 match.wildcards &= ~ofp.OFPFW_IN_PORT
391 self.assertTrue(match is not None,
392 "Could not generate flow match from pkt")
393
394 # Get queue stats from switch
395
396 request = message.queue_stats_request()
397 request.port_no = ofp.OFPP_CONTROLLER
398 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700399 (queue_stats, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700400 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
401
402 act = action.action_enqueue()
403
404 for idx in range(len(of_ports)):
405 ingress_port = of_ports[idx]
406 egress_port = ofp.OFPP_CONTROLLER
407
Rich Lane9a003812012-10-04 17:17:59 -0700408 logging.info("Ingress port " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700409 + ", controller port queues "
410 + str(self.portQueuesGet(queue_stats, egress_port)))
411
412 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700413 logging.info("Ingress " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700414 + " to egress " + str(egress_port)
415 + " queue " + str(egress_queue_id)
416 )
417
Rich Lane9a003812012-10-04 17:17:59 -0700418 rv = delete_all_flows(self.controller)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700419 self.assertEqual(rv, 0, "Failed to delete all flows")
420
421 match.in_port = ingress_port
422
423 request = message.flow_mod()
424 request.match = match
425
426 request.buffer_id = 0xffffffff
427 act.port = egress_port
428 act.queue_id = egress_queue_id
429 self.assertTrue(request.actions.add(act), "Could not add action")
430
Rich Lane9a003812012-10-04 17:17:59 -0700431 logging.info("Inserting flow")
Ken Chiang899ff8e2012-05-23 18:26:12 -0700432 rv = self.controller.message_send(request)
433 self.assertTrue(rv != -1, "Error installing flow mod")
434 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
435
436 # Get current stats for selected egress queue
437
438 request = message.queue_stats_request()
439 request.port_no = egress_port
440 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700441 (qs_before, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700442 self.assertNotEqual(qs_before, None, "Queue stats request failed")
443
Rich Lane9a003812012-10-04 17:17:59 -0700444 logging.info("Sending packet to dp port " +
Ken Chiang899ff8e2012-05-23 18:26:12 -0700445 str(ingress_port))
446 self.dataplane.send(ingress_port, str(pkt))
447
448 exp_pkt_arg = None
449 exp_port = None
450
451 while True:
Dan Talaycoc689a792012-09-28 14:22:53 -0700452 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700453 if not response: # Timeout
454 break
455 if dataplane.match_exp_pkt(pkt, response.data): # Got match
456 break
457 if not basic_config["relax"]: # Only one attempt to match
458 break
459 count += 1
460 if count > 10: # Too many tries
461 break
462
463 self.assertTrue(response is not None,
464 'Packet in message not received by controller')
465 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700466 logging.debug("Sent %s" % format_packet(pkt))
467 logging.debug("Resp %s" % format_packet(response.data))
Ken Chiang899ff8e2012-05-23 18:26:12 -0700468 self.assertTrue(False,
469 'Response packet does not match send packet' +
470 ' for controller port')
471
472 # FIXME: instead of sleeping, keep requesting queue stats until
473 # the expected queue counter increases or some large timeout is
474 # reached
475 time.sleep(2)
476
477 # Get current stats for selected egress queue again
478
479 request = message.queue_stats_request()
480 request.port_no = egress_port
481 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700482 (qs_after, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700483 self.assertNotEqual(qs_after, None, "Queue stats request failed")
484
485 # Make sure that tx packet counter for selected egress queue was
486 # incremented
487
488 self.assertEqual(qs_after.stats[0].tx_packets, \
489 qs_before.stats[0].tx_packets + 1, \
490 "Verification of egress queue tx packet count failed"
491 )
492
Howard Pershf97840f2012-04-10 16:30:42 -0700493
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700494class DirectPacketICMP(DirectPacket):
495 """
496 Send ICMP packet to single egress port
497
498 Generate a ICMP packet
499 Generate and install a matching flow
500 Add action to direct the packet to an egress port
501 Send the packet to ingress dataplane port
502 Verify the packet is received at the egress port only
503 Difference from DirectPacket test is that sent packet is ICMP
504 """
505 def runTest(self):
506 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700507
508class DirectTwoPorts(basic.SimpleDataPlane):
509 """
510 Send packet to two egress ports
511
512 Generate a packet
513 Generate and install a matching flow
514 Add action to direct the packet to two egress ports
515 Send the packet to ingress dataplane port
516 Verify the packet is received at the two egress ports
517 """
518 def runTest(self):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700519 of_ports = pa_port_map.keys()
520 of_ports.sort()
521 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
522
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700523 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700524 match = packet_to_flow_match(self, pkt)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700525 match.wildcards &= ~ofp.OFPFW_IN_PORT
526 self.assertTrue(match is not None,
527 "Could not generate flow match from pkt")
528 act = action.action_output()
529
530 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700531 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700532 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700533
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700534 ingress_port = of_ports[idx]
535 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
536 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700537 logging.info("Ingress " + str(ingress_port) +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700538 " to egress " + str(egress_port1) + " and " +
539 str(egress_port2))
540
541 match.in_port = ingress_port
542
543 request = message.flow_mod()
544 request.match = match
545 request.buffer_id = 0xffffffff
546 act.port = egress_port1
547 self.assertTrue(request.actions.add(act), "Could not add action1")
548 act.port = egress_port2
549 self.assertTrue(request.actions.add(act), "Could not add action2")
Rich Lane9a003812012-10-04 17:17:59 -0700550 # logging.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700551
Rich Lane9a003812012-10-04 17:17:59 -0700552 logging.info("Inserting flow")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700553 rv = self.controller.message_send(request)
554 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700555 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700556
Rich Lane9a003812012-10-04 17:17:59 -0700557 logging.info("Sending packet to dp port " +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700558 str(ingress_port))
559 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700560 yes_ports = set([egress_port1, egress_port2])
561 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700562
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700563 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Rich Lane9a003812012-10-04 17:17:59 -0700564 self, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700565
566class DirectMCNonIngress(basic.SimpleDataPlane):
567 """
568 Multicast to all non-ingress ports
569
570 Generate a packet
571 Generate and install a matching flow
572 Add action to direct the packet to all non-ingress ports
573 Send the packet to ingress dataplane port
574 Verify the packet is received at all non-ingress ports
575
576 Does not use the flood action
577 """
578 def runTest(self):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700579 of_ports = pa_port_map.keys()
580 of_ports.sort()
581 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
582
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700583 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700584 match = packet_to_flow_match(self, pkt)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700585 match.wildcards &= ~ofp.OFPFW_IN_PORT
586 self.assertTrue(match is not None,
587 "Could not generate flow match from pkt")
588 act = action.action_output()
589
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700590 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700591 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700592 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700593
Rich Lane9a003812012-10-04 17:17:59 -0700594 logging.info("Ingress " + str(ingress_port) +
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700595 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700596 match.in_port = ingress_port
597
598 request = message.flow_mod()
599 request.match = match
600 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700601 for egress_port in of_ports:
602 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700603 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700604 act.port = egress_port
605 self.assertTrue(request.actions.add(act),
606 "Could not add output to " + str(egress_port))
Rich Lane9a003812012-10-04 17:17:59 -0700607 logging.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700608
Rich Lane9a003812012-10-04 17:17:59 -0700609 logging.info("Inserting flow")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700610 rv = self.controller.message_send(request)
611 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700612 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700613
Rich Lane9a003812012-10-04 17:17:59 -0700614 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700615 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700616 yes_ports = set(of_ports).difference([ingress_port])
617 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane9a003812012-10-04 17:17:59 -0700618 self, pa_config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700619
Dan Talayco32fa6542010-05-11 15:54:08 -0700620
621class DirectMC(basic.SimpleDataPlane):
622 """
623 Multicast to all ports including ingress
624
625 Generate a packet
626 Generate and install a matching flow
627 Add action to direct the packet to all non-ingress ports
628 Send the packet to ingress dataplane port
629 Verify the packet is received at all ports
630
631 Does not use the flood action
632 """
633 def runTest(self):
Dan Talayco32fa6542010-05-11 15:54:08 -0700634 of_ports = pa_port_map.keys()
635 of_ports.sort()
636 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
637
Dan Talayco32fa6542010-05-11 15:54:08 -0700638 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700639 match = packet_to_flow_match(self, pkt)
Dan Talayco32fa6542010-05-11 15:54:08 -0700640 match.wildcards &= ~ofp.OFPFW_IN_PORT
641 self.assertTrue(match is not None,
642 "Could not generate flow match from pkt")
643 act = action.action_output()
644
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700645 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700646 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700647 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700648
Rich Lane9a003812012-10-04 17:17:59 -0700649 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700650 match.in_port = ingress_port
651
652 request = message.flow_mod()
653 request.match = match
654 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700655 for egress_port in of_ports:
656 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700657 act.port = ofp.OFPP_IN_PORT
658 else:
659 act.port = egress_port
660 self.assertTrue(request.actions.add(act),
661 "Could not add output to " + str(egress_port))
Rich Lane9a003812012-10-04 17:17:59 -0700662 # logging.info(request.show())
Dan Talayco2e77a842010-05-12 15:39:46 -0700663
Rich Lane9a003812012-10-04 17:17:59 -0700664 logging.info("Inserting flow")
Dan Talayco2e77a842010-05-12 15:39:46 -0700665 rv = self.controller.message_send(request)
666 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700667 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2e77a842010-05-12 15:39:46 -0700668
Rich Lane9a003812012-10-04 17:17:59 -0700669 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700670 self.dataplane.send(ingress_port, str(pkt))
Rich Lane9a003812012-10-04 17:17:59 -0700671 receive_pkt_check(self.dataplane, pkt, of_ports, [], self, pa_config)
Dan Talayco2e77a842010-05-12 15:39:46 -0700672
673class Flood(basic.SimpleDataPlane):
674 """
675 Flood to all ports except ingress
676
677 Generate a packet
678 Generate and install a matching flow
679 Add action to flood the packet
680 Send the packet to ingress dataplane port
681 Verify the packet is received at all other ports
682 """
683 def runTest(self):
Dan Talayco2e77a842010-05-12 15:39:46 -0700684 of_ports = pa_port_map.keys()
685 of_ports.sort()
686 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
687
688 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700689 match = packet_to_flow_match(self, pkt)
Dan Talayco2e77a842010-05-12 15:39:46 -0700690 match.wildcards &= ~ofp.OFPFW_IN_PORT
691 self.assertTrue(match is not None,
692 "Could not generate flow match from pkt")
693 act = action.action_output()
694
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700695 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700696 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700697 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700698
Rich Lane9a003812012-10-04 17:17:59 -0700699 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700700 match.in_port = ingress_port
701
702 request = message.flow_mod()
703 request.match = match
704 request.buffer_id = 0xffffffff
705 act.port = ofp.OFPP_FLOOD
706 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700707 "Could not add flood port action")
Rich Lane9a003812012-10-04 17:17:59 -0700708 logging.info(request.show())
Dan Talayco32fa6542010-05-11 15:54:08 -0700709
Rich Lane9a003812012-10-04 17:17:59 -0700710 logging.info("Inserting flow")
Dan Talayco32fa6542010-05-11 15:54:08 -0700711 rv = self.controller.message_send(request)
712 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700713 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco32fa6542010-05-11 15:54:08 -0700714
Rich Lane9a003812012-10-04 17:17:59 -0700715 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco32fa6542010-05-11 15:54:08 -0700716 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700717 yes_ports = set(of_ports).difference([ingress_port])
718 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane9a003812012-10-04 17:17:59 -0700719 self, pa_config)
Dan Talayco3be5b062010-05-12 15:46:21 -0700720
Dan Talayco3be5b062010-05-12 15:46:21 -0700721class FloodPlusIngress(basic.SimpleDataPlane):
722 """
723 Flood to all ports plus send to ingress port
724
725 Generate a packet
726 Generate and install a matching flow
727 Add action to flood the packet
728 Add action to send to ingress port
729 Send the packet to ingress dataplane port
730 Verify the packet is received at all other ports
731 """
732 def runTest(self):
Dan Talayco3be5b062010-05-12 15:46:21 -0700733 of_ports = pa_port_map.keys()
734 of_ports.sort()
735 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
736
737 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700738 match = packet_to_flow_match(self, pkt)
Dan Talayco3be5b062010-05-12 15:46:21 -0700739 match.wildcards &= ~ofp.OFPFW_IN_PORT
740 self.assertTrue(match is not None,
741 "Could not generate flow match from pkt")
742 act = action.action_output()
743
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700744 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700745 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700746 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700747
Rich Lane9a003812012-10-04 17:17:59 -0700748 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700749 match.in_port = ingress_port
750
751 request = message.flow_mod()
752 request.match = match
753 request.buffer_id = 0xffffffff
754 act.port = ofp.OFPP_FLOOD
755 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700756 "Could not add flood port action")
757 act.port = ofp.OFPP_IN_PORT
758 self.assertTrue(request.actions.add(act),
759 "Could not add ingress port for output")
Rich Lane9a003812012-10-04 17:17:59 -0700760 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700761
Rich Lane9a003812012-10-04 17:17:59 -0700762 logging.info("Inserting flow")
Dan Talayco4aa13122010-05-12 15:54:44 -0700763 rv = self.controller.message_send(request)
764 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700765 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700766
Rich Lane9a003812012-10-04 17:17:59 -0700767 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700768 self.dataplane.send(ingress_port, str(pkt))
Rich Lane9a003812012-10-04 17:17:59 -0700769 receive_pkt_check(self.dataplane, pkt, of_ports, [], self, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700770
771class All(basic.SimpleDataPlane):
772 """
773 Send to OFPP_ALL port
774
775 Generate a packet
776 Generate and install a matching flow
777 Add action to forward to OFPP_ALL
778 Send the packet to ingress dataplane port
779 Verify the packet is received at all other ports
780 """
781 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700782 of_ports = pa_port_map.keys()
783 of_ports.sort()
784 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
785
786 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700787 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700788 match.wildcards &= ~ofp.OFPFW_IN_PORT
789 self.assertTrue(match is not None,
790 "Could not generate flow match from pkt")
791 act = action.action_output()
792
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700793 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700794 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700795 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700796
Rich Lane9a003812012-10-04 17:17:59 -0700797 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700798 match.in_port = ingress_port
799
800 request = message.flow_mod()
801 request.match = match
802 request.buffer_id = 0xffffffff
803 act.port = ofp.OFPP_ALL
804 self.assertTrue(request.actions.add(act),
805 "Could not add ALL port action")
Rich Lane9a003812012-10-04 17:17:59 -0700806 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700807
Rich Lane9a003812012-10-04 17:17:59 -0700808 logging.info("Inserting flow")
Dan Talayco4aa13122010-05-12 15:54:44 -0700809 rv = self.controller.message_send(request)
810 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700811 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700812
Rich Lane9a003812012-10-04 17:17:59 -0700813 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700814 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700815 yes_ports = set(of_ports).difference([ingress_port])
816 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane9a003812012-10-04 17:17:59 -0700817 self, pa_config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700818
819class AllPlusIngress(basic.SimpleDataPlane):
820 """
821 Send to OFPP_ALL port and ingress port
822
823 Generate a packet
824 Generate and install a matching flow
825 Add action to forward to OFPP_ALL
826 Add action to forward to ingress port
827 Send the packet to ingress dataplane port
828 Verify the packet is received at all other ports
829 """
830 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700831 of_ports = pa_port_map.keys()
832 of_ports.sort()
833 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
834
835 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700836 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700837 match.wildcards &= ~ofp.OFPFW_IN_PORT
838 self.assertTrue(match is not None,
839 "Could not generate flow match from pkt")
840 act = action.action_output()
841
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700842 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700843 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700844 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700845
Rich Lane9a003812012-10-04 17:17:59 -0700846 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700847 match.in_port = ingress_port
848
849 request = message.flow_mod()
850 request.match = match
851 request.buffer_id = 0xffffffff
852 act.port = ofp.OFPP_ALL
853 self.assertTrue(request.actions.add(act),
854 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700855 act.port = ofp.OFPP_IN_PORT
856 self.assertTrue(request.actions.add(act),
857 "Could not add ingress port for output")
Rich Lane9a003812012-10-04 17:17:59 -0700858 logging.info(request.show())
Dan Talayco3be5b062010-05-12 15:46:21 -0700859
Rich Lane9a003812012-10-04 17:17:59 -0700860 logging.info("Inserting flow")
Dan Talayco3be5b062010-05-12 15:46:21 -0700861 rv = self.controller.message_send(request)
862 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700863 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco3be5b062010-05-12 15:46:21 -0700864
Rich Lane9a003812012-10-04 17:17:59 -0700865 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco3be5b062010-05-12 15:46:21 -0700866 self.dataplane.send(ingress_port, str(pkt))
Rich Lane9a003812012-10-04 17:17:59 -0700867 receive_pkt_check(self.dataplane, pkt, of_ports, [], self, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700868
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700869class FloodMinusPort(basic.SimpleDataPlane):
870 """
871 Config port with No_Flood and test Flood action
872
873 Generate a packet
874 Generate a matching flow
875 Add action to forward to OFPP_ALL
876 Set port to no-flood
877 Send the packet to ingress dataplane port
878 Verify the packet is received at all other ports except
879 the ingress port and the no_flood port
880 """
881 def runTest(self):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700882 of_ports = pa_port_map.keys()
883 of_ports.sort()
884 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
885
886 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700887 match = packet_to_flow_match(self, pkt)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700888 match.wildcards &= ~ofp.OFPFW_IN_PORT
889 self.assertTrue(match is not None,
890 "Could not generate flow match from pkt")
891 act = action.action_output()
892
893 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700894 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700895 self.assertEqual(rv, 0, "Failed to delete all flows")
896
897 ingress_port = of_ports[idx]
898 no_flood_idx = (idx + 1) % len(of_ports)
899 no_flood_port = of_ports[no_flood_idx]
900 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700901 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700902 self.assertEqual(rv, 0, "Failed to set port config")
903
904 match.in_port = ingress_port
905
906 request = message.flow_mod()
907 request.match = match
908 request.buffer_id = 0xffffffff
909 act.port = ofp.OFPP_FLOOD
910 self.assertTrue(request.actions.add(act),
911 "Could not add flood port action")
Rich Lane9a003812012-10-04 17:17:59 -0700912 logging.info(request.show())
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700913
Rich Lane9a003812012-10-04 17:17:59 -0700914 logging.info("Inserting flow")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700915 rv = self.controller.message_send(request)
916 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700917 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700918
Rich Lane9a003812012-10-04 17:17:59 -0700919 logging.info("Sending packet to dp port " + str(ingress_port))
920 logging.info("No flood port is " + str(no_flood_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700921 self.dataplane.send(ingress_port, str(pkt))
922 no_ports = set([ingress_port, no_flood_port])
923 yes_ports = set(of_ports).difference(no_ports)
Rich Lane9a003812012-10-04 17:17:59 -0700924 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self, pa_config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700925
926 # Turn no flood off again
927 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700928 0, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700929 self.assertEqual(rv, 0, "Failed to reset port config")
930
931 #@todo Should check no other packets received
932
Dan Talayco21381562010-07-17 00:34:47 -0700933
934
Dan Talayco551befa2010-07-15 17:05:32 -0700935################################################################
936
937class BaseMatchCase(basic.SimpleDataPlane):
938 def setUp(self):
939 basic.SimpleDataPlane.setUp(self)
Dan Talayco551befa2010-07-15 17:05:32 -0700940 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -0700941 logging.info("BaseMatchCase")
Dan Talayco551befa2010-07-15 17:05:32 -0700942
943class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700944 """
Dan Talayco551befa2010-07-15 17:05:32 -0700945 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700946
947 Generate a packet
948 Generate and install a matching flow without wildcard mask
949 Add action to forward to a port
950 Send the packet to the port
951 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700952 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700953
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700954 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700955 flow_match_test(self, pa_port_map)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700956
Dan Talayco551befa2010-07-15 17:05:32 -0700957class ExactMatchTagged(BaseMatchCase):
958 """
959 Exact match for all port pairs with tagged pkts
960 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700961
Dan Talayco551befa2010-07-15 17:05:32 -0700962 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700963 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700964 flow_match_test(self, pa_port_map, dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700965
Dan Talayco551befa2010-07-15 17:05:32 -0700966class ExactMatchTaggedMany(BaseMatchCase):
967 """
968 ExactMatchTagged with many VLANS
969 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700970
Rich Laned1d9c282012-10-04 22:07:10 -0700971 priority = -1
972
Dan Talayco551befa2010-07-15 17:05:32 -0700973 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700974 for vid in range(2,100,10):
Dan Talayco551befa2010-07-15 17:05:32 -0700975 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
976 for vid in range(100,4000,389):
977 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
978 flow_match_test(self, pa_port_map, dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700979
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700980class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700981 """
982 SingleWildcardMatchPriority
983 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700984
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700985 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700986 self.pkt = simple_tcp_packet()
987 self.flowMsgs = {}
988
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700989 def _ClearTable(self):
Rich Lane9a003812012-10-04 17:17:59 -0700990 rc = delete_all_flows(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700991 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700992 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700993
994 def runTest(self):
995
996 self._Init()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700997 of_ports = pa_port_map.keys()
998 of_ports.sort()
999
1000 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001001 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001002
1003 # Run several combinations, each at lower priority settings.
1004 # At the end of each call to runPrioFlows(), the table should
1005 # be empty. If its not, we'll catch it as the priorities decreases
1006 portA = of_ports[0]
1007 portB = of_ports[1]
1008 portC = of_ports[2]
1009
1010 # TODO -- these priority numbers should be validated somehow?
1011 self.runPrioFlows(portA, portB, portC, 1000, 999)
1012 self.runPrioFlows(portB, portC, portA, 998, 997)
1013 self.runPrioFlows(portC, portA, portB, 996, 995)
1014 self.runPrioFlows(portA, portC, portB, 994, 993)
1015
1016
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001017
1018 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
1019 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001020
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001021 if clearTable:
1022 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001023
1024 # Sanity check flow at lower priority from pA to pB
Rich Lane9a003812012-10-04 17:17:59 -07001025 logging.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001026 % (portA, portB, portC, prioHigher, prioLower))
1027
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001028 # Sanity check flow at lower priority from pA to pC
1029 self.installFlow(prioLower, portA, portC)
1030 self.verifyFlow(portA, portC)
1031 self.removeFlow(prioLower)
1032
1033 # Install and verify pA->pB @ prioLower
1034 self.installFlow(prioLower, portA, portB)
1035 self.verifyFlow(portA, portB)
1036
1037 # Install and verify pA->pC @ prioHigher, should override pA->pB
1038 self.installFlow(prioHigher, portA, portC)
1039 self.verifyFlow(portA, portC)
1040 # remove pA->pC
1041 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001042 # Old flow pA -> pB @ prioLower should still be active
1043 self.verifyFlow(portA, portB)
1044 self.removeFlow(prioLower)
1045
1046 # Table should be empty at this point, leave it alone as
1047 # an assumption for future test runs
1048
1049
1050
Ed Swierk99a74de2012-08-22 06:40:54 -07001051 def installFlow(self, prio, inp, egp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001052 wildcards=ofp.OFPFW_DL_SRC):
Ed Swierk99a74de2012-08-22 06:40:54 -07001053 wildcards |= required_wildcards(self)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001054 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001055 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001056 egr_ports=egp)
1057 request.priority = prio
Rich Lane9a003812012-10-04 17:17:59 -07001058 logging.debug("Install flow with priority " + str(prio))
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001059 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001060 self.flowMsgs[prio] = request
1061
1062 def removeFlow(self, prio):
1063 if self.flowMsgs.has_key(prio):
1064 msg = self.flowMsgs[prio]
1065 msg.command = ofp.OFPFC_DELETE_STRICT
1066 # This *must* be set for DELETE
1067 msg.out_port = ofp.OFPP_NONE
Rich Lane9a003812012-10-04 17:17:59 -07001068 logging.debug("Remove flow with priority " + str(prio))
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001069 self.controller.message_send(msg)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001070 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001071 else:
1072 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001073
1074
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001075 def verifyFlow(self, inp, egp, pkt=None):
1076 if pkt == None:
1077 pkt = self.pkt
1078
Rich Lane9a003812012-10-04 17:17:59 -07001079 logging.info("Pkt match test: " + str(inp) + " to " + str(egp))
1080 logging.debug("Send packet: " + str(inp) + " to " + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001081 self.dataplane.send(inp, str(pkt))
1082 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001083
1084
1085
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001086class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
1087
1088 def runTest(self):
1089
1090 self._Init()
1091
1092 of_ports = pa_port_map.keys()
1093 of_ports.sort()
1094
1095 # Install an entry from 0 -> 1 @ prio 1000
1096 self._ClearTable()
1097 self.installFlow(1000, of_ports[0], of_ports[1])
1098 self.verifyFlow(of_ports[0], of_ports[1])
1099 self.installFlow(1000, of_ports[1], of_ports[0])
1100 self.verifyFlow(of_ports[1], of_ports[0])
1101 self.installFlow(1001, of_ports[0], of_ports[1])
1102 self.verifyFlow(of_ports[0], of_ports[1])
1103 self.installFlow(1001, of_ports[1], of_ports[0])
1104 self.verifyFlow(of_ports[1], of_ports[0])
1105 self.removeFlow(1001)
1106 self.verifyFlow(of_ports[0], of_ports[1])
1107 self.removeFlow(1000)
1108
1109
1110
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001111class WildcardPriority(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001112 """
1113 1. Add wildcard flow, verify packet received.
1114 2. Add exact match flow with higher priority, verify packet received
1115 on port specified by this flow.
1116 3. Add wildcard flow with even higher priority, verify packet received
1117 on port specified by this flow.
1118 """
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001119
1120 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001121
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001122 self._Init()
1123
1124 of_ports = pa_port_map.keys()
1125 of_ports.sort()
1126
1127 self._ClearTable()
Ken Chiang38d7a152012-05-24 15:33:50 -07001128
1129 # Install a flow with wildcards
1130 self.installFlow(999, of_ports[0], of_ports[1],
1131 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001132 self.verifyFlow(of_ports[0], of_ports[1])
Ken Chiang38d7a152012-05-24 15:33:50 -07001133 # Install a flow with no wildcards for our packet
1134 self.installFlow(1000, of_ports[0], of_ports[2], wildcards=0)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001135 self.verifyFlow(of_ports[0], of_ports[2])
Ken Chiang38d7a152012-05-24 15:33:50 -07001136 # Install a flow with wildcards for our packet with higher
1137 # priority
1138 self.installFlow(1001, of_ports[0], of_ports[3])
1139 self.verifyFlow(of_ports[0], of_ports[3])
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001140
1141
Ken Chiang3978f242012-06-13 14:14:09 -07001142class WildcardPriorityWithDelete(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001143 """
1144 1. Add exact match flow, verify packet received.
1145 2. Add wildcard flow with higher priority, verify packet received on port
1146 specified by this flow.
1147 3. Add exact match flow with even higher priority, verify packet received
1148 on port specified by this flow.
1149 4. Delete lowest priority flow, verify packet received on port specified
1150 by highest priority flow.
1151 5. Delete highest priority flow, verify packet received on port specified
1152 by remaining flow.
1153 """
1154
1155 def runTest(self):
1156
1157 self._Init()
1158
1159 of_ports = pa_port_map.keys()
1160 of_ports.sort()
1161
1162 self._ClearTable()
1163
1164 # Install an exact match flow
1165 self.installFlow(250, of_ports[0], of_ports[1], wildcards=0)
1166 self.verifyFlow(of_ports[0], of_ports[1])
1167 # Install a flow with wildcards of higher priority
1168 self.installFlow(1250, of_ports[0], of_ports[2],
1169 wildcards=ofp.OFPFW_DL_DST)
1170 self.verifyFlow(of_ports[0], of_ports[2])
1171 # Install an exact match flow with even higher priority
1172 self.installFlow(2001, of_ports[0], of_ports[3], wildcards=0)
1173 self.verifyFlow(of_ports[0], of_ports[3])
1174 # Delete lowest priority flow
1175 self.removeFlow(250)
1176 self.verifyFlow(of_ports[0], of_ports[3])
1177 # Delete highest priority flow
1178 self.removeFlow(2001)
1179 self.verifyFlow(of_ports[0], of_ports[2])
1180
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001181
Dan Talayco551befa2010-07-15 17:05:32 -07001182class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001183 """
1184 Exercise wildcard matching for all ports
1185
1186 Generate a packet
1187 Generate and install a matching flow with wildcard mask
1188 Add action to forward to a port
1189 Send the packet to the port
1190 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001191 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001192 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001193 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -07001194 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001195 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001196 wc |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001197 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001198 # Set nonzero VLAN id to avoid sending priority-tagged packet
1199 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001200 else:
1201 dl_vlan = -1
1202 flow_match_test(self, pa_port_map, wildcards=wc,
1203 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001204
Dan Talayco551befa2010-07-15 17:05:32 -07001205class SingleWildcardMatchTagged(BaseMatchCase):
1206 """
1207 SingleWildcardMatch with tagged packets
1208 """
1209 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001210 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001211 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001212 wc |= required_wildcards(self)
Dan Talayco21381562010-07-17 00:34:47 -07001213 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -07001214 max_test=10)
1215
1216class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001217 """
Dan Talayco80b54ed2010-07-13 09:48:35 -07001218 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001219
1220 Generate a packet
1221 Generate and install a matching flow with wildcard all except one filed
1222 Add action to forward to a port
1223 Send the packet to the port
1224 Verify the packet is received at all other ports (one port at a time)
1225 Verify flow_expiration message is correct when command option is set
1226 """
1227 def runTest(self):
Ken Chiang5be06dd2012-04-03 10:03:50 -07001228 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001229 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001230 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001231 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001232 # Set nonzero VLAN id to avoid sending priority-tagged packet
1233 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001234 else:
1235 dl_vlan = -1
1236 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
1237 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001238
Dan Talayco551befa2010-07-15 17:05:32 -07001239class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1240 """
1241 Match one field with tagged packets
1242 """
1243 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001244 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001245 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001246 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco21381562010-07-17 00:34:47 -07001247 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
1248 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001249
1250class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001251 """
1252 Create Wildcard-all flow and exercise for all ports
1253
1254 Generate a packet
1255 Generate and install a matching flow with wildcard-all
1256 Add action to forward to a port
1257 Send the packet to the port
1258 Verify the packet is received at all other ports (one port at a time)
1259 Verify flow_expiration message is correct when command option is set
1260 """
1261 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -07001262 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001263
Dan Talayco551befa2010-07-15 17:05:32 -07001264class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001265 """
Dan Talayco551befa2010-07-15 17:05:32 -07001266 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001267 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001268 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001269 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -07001270 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
1271 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001272
Dan Talaycoba3745c2010-07-21 21:51:08 -07001273
Dan Talayco551befa2010-07-15 17:05:32 -07001274class AddVLANTag(BaseMatchCase):
1275 """
1276 Add a VLAN tag to an untagged packet
1277 """
1278 def runTest(self):
1279 new_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001280 sup_acts = self.supported_actions
Dan Talayco551befa2010-07-15 17:05:32 -07001281 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001282 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001283 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001284
Dan Talayco551befa2010-07-15 17:05:32 -07001285 len = 100
1286 len_w_vid = 104
1287 pkt = simple_tcp_packet(pktlen=len)
1288 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1289 dl_vlan=new_vid)
1290 vid_act = action.action_set_vlan_vid()
1291 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001292
Dan Talayco551befa2010-07-15 17:05:32 -07001293 flow_match_test(self, pa_port_map, pkt=pkt,
1294 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001295
Dan Talayco551befa2010-07-15 17:05:32 -07001296class PacketOnly(basic.DataPlaneOnly):
1297 """
1298 Just send a packet thru the switch
1299 """
Rich Laned1d9c282012-10-04 22:07:10 -07001300
1301 priority = -1
1302
Dan Talayco551befa2010-07-15 17:05:32 -07001303 def runTest(self):
1304 pkt = simple_tcp_packet()
1305 of_ports = pa_port_map.keys()
1306 of_ports.sort()
1307 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001308 logging.info("Sending packet to " + str(ing_port))
1309 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001310 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001311
Dan Talayco551befa2010-07-15 17:05:32 -07001312class PacketOnlyTagged(basic.DataPlaneOnly):
1313 """
1314 Just send a packet thru the switch
1315 """
Rich Laned1d9c282012-10-04 22:07:10 -07001316
1317 priority = -1
1318
Dan Talayco551befa2010-07-15 17:05:32 -07001319 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 -07001329class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001330 """
1331 Modify the VLAN ID in the VLAN tag of a tagged packet
1332 """
Dan Talaycoaf669322012-09-12 22:51:22 -07001333 def setUp(self):
1334 BaseMatchCase.setUp(self)
1335 self.ing_port=False
1336
Dan Talayco551befa2010-07-15 17:05:32 -07001337 def runTest(self):
1338 old_vid = 2
1339 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001340 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001341 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001342 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001343 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001344
Dan Talayco551befa2010-07-15 17:05:32 -07001345 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1346 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
1347 vid_act = action.action_set_vlan_vid()
1348 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001349
Dan Talayco551befa2010-07-15 17:05:32 -07001350 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoaf669322012-09-12 22:51:22 -07001351 action_list=[vid_act], ing_port=self.ing_port)
1352
1353class ModifyVIDToIngress(ModifyVID):
1354 """
1355 Modify the VLAN ID in the VLAN tag of a tagged packet and send to
1356 ingress port
1357 """
1358 def setUp(self):
1359 BaseMatchCase.setUp(self)
1360 self.ing_port=True
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001361
Ken Chiange9a211d2012-04-20 14:52:11 -07001362class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1363 """
1364 With vlan ID and priority wildcarded, perform SET_VLAN_VID action.
1365 The same flow should match on both untagged and tagged packets.
1366 """
1367 def runTest(self):
1368 old_vid = 2
1369 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001370 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001371 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1372 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1373 return
1374
1375 of_ports = pa_port_map.keys()
1376 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1377 ing_port = of_ports[0]
1378 egr_ports = of_ports[1]
1379
Rich Lane9a003812012-10-04 17:17:59 -07001380 rv = delete_all_flows(self.controller)
Ken Chiange9a211d2012-04-20 14:52:11 -07001381 self.assertEqual(rv, 0, "Failed to delete all flows")
1382
1383 len_untagged = 100
1384 len_w_vid = 104
1385 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1386 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
1387 dl_vlan_enable=True, dl_vlan=old_vid)
1388 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1389 dl_vlan=new_vid)
Ed Swierk99a74de2012-08-22 06:40:54 -07001390 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1391 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001392 vid_act = action.action_set_vlan_vid()
1393 vid_act.vlan_vid = new_vid
1394 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
1395 wildcards=wildcards, egr_ports=egr_ports,
1396 action_list=[vid_act])
1397 flow_msg_install(self, request)
1398
Rich Lane9a003812012-10-04 17:17:59 -07001399 logging.debug("Send untagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001400 str(egr_ports))
1401 self.dataplane.send(ing_port, str(untagged_pkt))
1402 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1403
Rich Lane9a003812012-10-04 17:17:59 -07001404 logging.debug("Send tagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001405 str(egr_ports))
1406 self.dataplane.send(ing_port, str(tagged_pkt))
1407 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1408
Howard Pershc1199d52012-04-11 14:21:32 -07001409class ModifyVlanPcp(BaseMatchCase):
1410 """
1411 Modify the priority field of the VLAN tag of a tagged packet
1412 """
1413 def runTest(self):
1414 vid = 123
1415 old_vlan_pcp = 2
1416 new_vlan_pcp = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001417 sup_acts = self.supported_actions
Ed Swierk8c3af7f2012-04-24 14:19:17 -07001418 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_PCP):
1419 skip_message_emit(self, "Modify VLAN priority test")
Howard Pershc1199d52012-04-11 14:21:32 -07001420 return
1421
1422 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1423 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1424 vid_act = action.action_set_vlan_pcp()
1425 vid_act.vlan_pcp = new_vlan_pcp
1426
1427 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1428 action_list=[vid_act])
1429
Dan Talayco551befa2010-07-15 17:05:32 -07001430class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001431 """
1432 Strip the VLAN tag from a tagged packet
1433 """
Dan Talayco551befa2010-07-15 17:05:32 -07001434 def runTest(self):
1435 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001436 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001437 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001438 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001439 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001440
Dan Talayco551befa2010-07-15 17:05:32 -07001441 len_w_vid = 104
1442 len = 100
1443 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1444 dl_vlan=old_vid)
1445 exp_pkt = simple_tcp_packet(pktlen=len)
1446 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001447
Dan Talayco551befa2010-07-15 17:05:32 -07001448 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1449 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001450
Ken Chiange9a211d2012-04-20 14:52:11 -07001451class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1452 """
1453 Strip the VLAN tag from a tagged packet.
1454 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1455 """
1456 def runTest(self):
1457 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001458 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001459 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1460 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1461 return
1462
1463 len_w_vid = 104
1464 len_untagged = 100
1465 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1466 dl_vlan=old_vid)
1467 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
Ed Swierk99a74de2012-08-22 06:40:54 -07001468 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1469 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001470 vid_act = action.action_strip_vlan()
1471
1472 flow_match_test(self, pa_port_map,
Ed Swierk99a74de2012-08-22 06:40:54 -07001473 wildcards=wildcards,
Ken Chiange9a211d2012-04-20 14:52:11 -07001474 pkt=pkt, exp_pkt=exp_pkt,
1475 action_list=[vid_act])
1476
Dan Talayco4b2bee62010-07-20 14:10:05 -07001477def init_pkt_args():
1478 """
1479 Pass back a dictionary with default packet arguments
1480 """
1481 args = {}
1482 args["dl_src"] = '00:23:45:67:89:AB'
1483
1484 dl_vlan_enable=False
1485 dl_vlan=-1
1486 if pa_config["test-params"]["vid"]:
1487 dl_vlan_enable=True
1488 dl_vlan = pa_config["test-params"]["vid"]
1489
1490# Unpack operator is ** on a dictionary
1491
1492 return args
1493
Dan Talayco551befa2010-07-15 17:05:32 -07001494class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001495 """
1496 Modify the source MAC address (TP1)
1497 """
Dan Talayco551befa2010-07-15 17:05:32 -07001498 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001499 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001500 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001501 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001502 return
1503
1504 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1505 check_test_params=True)
1506 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1507 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001508
Dan Talayco551befa2010-07-15 17:05:32 -07001509class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001510 """
1511 Modify the dest MAC address (TP1)
1512 """
Dan Talayco551befa2010-07-15 17:05:32 -07001513 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001514 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001515 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001516 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001517 return
1518
1519 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1520 check_test_params=True)
1521 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1522 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001523
Dan Talayco551befa2010-07-15 17:05:32 -07001524class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001525 """
1526 Modify the source IP address of an IP packet (TP1)
1527 """
Dan Talayco551befa2010-07-15 17:05:32 -07001528 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001529 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001530 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001531 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001532 return
1533
1534 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1535 check_test_params=True)
1536 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1537 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001538
Dan Talayco551befa2010-07-15 17:05:32 -07001539class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001540 """
1541 Modify the dest IP address of an IP packet (TP1)
1542 """
Dan Talayco551befa2010-07-15 17:05:32 -07001543 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001544 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001545 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001546 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001547 return
1548
1549 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1550 check_test_params=True)
1551 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1552 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001553
1554class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001555 """
1556 Modify the source TCP port of a TCP packet (TP1)
1557 """
Dan Talayco551befa2010-07-15 17:05:32 -07001558 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001559 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001560 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001561 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001562 return
1563
1564 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1565 check_test_params=True)
1566 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1567 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001568
1569class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001570 """
1571 Modify the dest TCP port of a TCP packet (TP1)
1572 """
Dan Talayco551befa2010-07-15 17:05:32 -07001573 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001574 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001575 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001576 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001577 return
1578
1579 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1580 check_test_params=True)
1581 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1582 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001583
1584class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001585 """
1586 Modify the IP type of service of an IP packet (TP1)
1587 """
Dan Talayco551befa2010-07-15 17:05:32 -07001588 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001589 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001590 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001591 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001592 return
Dan Talayco551befa2010-07-15 17:05:32 -07001593
Dan Talayco4b2bee62010-07-20 14:10:05 -07001594 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1595 check_test_params=True)
1596 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001597 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001598
Dan Talaycof6e76c02012-03-23 10:56:12 -07001599class ModifyL2DstMC(BaseMatchCase):
1600 """
1601 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001602 """
1603 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001604 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001605 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001606 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001607 return
1608
Dan Talaycof6e76c02012-03-23 10:56:12 -07001609 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1610 check_test_params=True)
1611 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001612 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001613
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001614class ModifyL2DstIngress(BaseMatchCase):
1615 """
1616 Modify the L2 dest and send to the ingress port
1617 """
1618 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001619 sup_acts = self.supported_actions
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001620 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001621 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001622 return
1623
1624 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1625 check_test_params=True)
1626 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1627 action_list=acts, max_test=2, egr_count=0,
1628 ing_port=True)
1629
Dan Talaycod8ae7582012-03-23 12:24:56 -07001630class ModifyL2DstIngressMC(BaseMatchCase):
1631 """
1632 Modify the L2 dest and send to the ingress port
1633 """
1634 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001635 sup_acts = self.supported_actions
Dan Talaycod8ae7582012-03-23 12:24:56 -07001636 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1637 skip_message_emit(self, "ModifyL2dstMC test")
1638 return
1639
1640 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1641 check_test_params=True)
1642 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1643 action_list=acts, max_test=2, egr_count=-1,
1644 ing_port=True)
1645
Dan Talaycof6e76c02012-03-23 10:56:12 -07001646class ModifyL2SrcMC(BaseMatchCase):
1647 """
1648 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001649 """
1650 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001651 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001652 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001653 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001654 return
1655
Dan Talaycof6e76c02012-03-23 10:56:12 -07001656 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1657 check_test_params=True)
1658 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001659 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001660
1661class ModifyL2SrcDstMC(BaseMatchCase):
1662 """
1663 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001664 """
1665 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001666 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001667 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1668 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1669 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001670 return
1671
Dan Talaycof6e76c02012-03-23 10:56:12 -07001672 mod_fields = ['dl_dst', 'dl_src']
1673 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1674 check_test_params=True)
1675 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001676 action_list=acts, max_test=2, egr_count=-1)
1677
1678class ModifyL2DstVIDMC(BaseMatchCase):
1679 """
1680 Modify the L2 dest and send to 2 ports
1681 """
1682 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001683 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001684 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1685 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1686 skip_message_emit(self, "ModifyL2DstVIDMC test")
1687 return
1688
1689 mod_fields = ['dl_dst', 'dl_vlan']
1690 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1691 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1692 check_test_params=True)
1693 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
1694 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001695
Dan Talaycofa6454f2012-04-05 10:04:13 -07001696class FlowToggle(BaseMatchCase):
1697 """
1698 Add flows to the table and modify them repeatedly
Dan Talaycof7c41312012-07-23 12:53:19 -07001699
1700 This is done by using only "add" flow messages. Since the check overlap
1701 flag is not set, the switch is supposed to modify the existing flow if
1702 the match already exists.
1703
1704 Would probably be better to exercise more of the flow modify commands
1705 (add, modify, delete +/- strict).
Dan Talaycofa6454f2012-04-05 10:04:13 -07001706 """
1707 def runTest(self):
Dan Talayco50be7672012-04-05 11:38:08 -07001708 flow_count = test_param_get(self.config, 'ft_flow_count', default=20)
1709 iter_count = test_param_get(self.config, 'ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001710
Rich Lane9a003812012-10-04 17:17:59 -07001711 logging.info("Running flow toggle with %d flows, %d iterations" %
Dan Talaycofa6454f2012-04-05 10:04:13 -07001712 (flow_count, iter_count))
1713 acts = []
1714 acts.append(action.action_output())
1715 acts.append(action.action_output())
1716
1717 of_ports = pa_port_map.keys()
1718 if len(of_ports) < 3:
1719 self.assertTrue(False, "Too few ports for test")
1720
1721 for idx in range(2):
1722 acts[idx].port = of_ports[idx]
1723
1724 flows = []
1725 flows.append([])
1726 flows.append([])
1727
Ed Swierk99a74de2012-08-22 06:40:54 -07001728 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_SRC |
1729 ofp.OFPFW_DL_DST)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001730 # Create up the flows in an array
1731 for toggle in range(2):
1732 for f_idx in range(flow_count):
1733 pkt = simple_tcp_packet(tcp_sport=f_idx)
1734 msg = message.flow_mod()
Ed Swierk99a74de2012-08-22 06:40:54 -07001735 match = packet_to_flow_match(self, pkt)
Shudong Zhou031373c2012-07-19 17:37:42 -07001736 match.in_port = of_ports[2]
Dan Talayco50be7672012-04-05 11:38:08 -07001737 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001738 msg.match = match
1739 msg.buffer_id = 0xffffffff
Dan Talaycof7c41312012-07-23 12:53:19 -07001740 msg.command = ofp.OFPFC_ADD
Dan Talaycofa6454f2012-04-05 10:04:13 -07001741 msg.actions.add(acts[toggle])
1742 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001743
1744 # Show two sample flows
Rich Lane9a003812012-10-04 17:17:59 -07001745 logging.debug(flows[0][0].show())
1746 logging.debug(flows[1][0].show())
Dan Talayco50be7672012-04-05 11:38:08 -07001747
Dan Talaycofa6454f2012-04-05 10:04:13 -07001748 # Install the first set of flows
1749 for f_idx in range(flow_count):
1750 rv = self.controller.message_send(flows[0][f_idx])
1751 self.assertTrue(rv != -1, "Error installing flow %d" % f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001752 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycofa6454f2012-04-05 10:04:13 -07001753
Rich Lane9a003812012-10-04 17:17:59 -07001754 logging.info("Installed %d flows" % flow_count)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001755
1756 # Repeatedly modify all the flows back and forth
1757 updates = 0
1758 # Report status about 5 times
1759 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001760 start = time.time()
1761 for iter_idx in range(iter_count):
1762 if not iter_idx % mod_val:
Rich Lane9a003812012-10-04 17:17:59 -07001763 logging.info("Flow Toggle: iter %d of %d. " %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001764 (iter_idx, iter_count) +
1765 "%d updates in %d secs" %
1766 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001767 for toggle in range(2):
1768 t_idx = 1 - toggle
1769 for f_idx in range(flow_count):
1770 rv = self.controller.message_send(flows[t_idx][f_idx])
1771 updates += 1
1772 self.assertTrue(rv != -1, "Error modifying flow %d" %
1773 f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001774 self.assertEqual(do_barrier(self.controller), 0,
1775 "Barrier failed")
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001776
1777 end = time.time()
1778 divisor = end - start or (end - start + 1)
Rich Lane9a003812012-10-04 17:17:59 -07001779 logging.info("Flow toggle: %d iterations" % iter_count)
1780 logging.info(" %d flow mods in %d secs, %d mods/sec" %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001781 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001782
1783
Dan Talayco8a64e332012-03-28 14:53:20 -07001784# You can pick and choose these by commenting tests in or out
1785iter_classes = [
1786 basic.PacketIn,
1787 basic.PacketOut,
1788 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001789 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001790 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001791 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001792 AllWildcardMatch,
1793 AllWildcardMatchTagged,
1794 SingleWildcardMatch,
1795 SingleWildcardMatchTagged,
1796 ExactMatch,
1797 ExactMatchTagged,
1798 SingleWildcardMatch,
1799 ModifyL2Src,
1800 ModifyL2Dst,
1801 ModifyL2SrcMC,
1802 ModifyL2DstMC,
1803 ModifyL2SrcDstMC
1804 ]
1805
1806class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001807 """
1808 Iterate over a bunch of test cases
1809
1810 The cases come from the list above
1811 """
1812
Rich Laned1d9c282012-10-04 22:07:10 -07001813 priority = -1
1814
Dan Talayco8a64e332012-03-28 14:53:20 -07001815 def runTest(self):
1816 count = test_param_get(self.config, 'iter_count', default=10)
1817 tests_done = 0
Rich Lane9a003812012-10-04 17:17:59 -07001818 logging.info("Running iteration test " + str(count) + " times")
Dan Talayco8a64e332012-03-28 14:53:20 -07001819 start = time.time()
1820 last = start
1821 for idx in range(count):
Rich Lane9a003812012-10-04 17:17:59 -07001822 logging.info("Iteration " + str(idx + 1))
Dan Talayco8a64e332012-03-28 14:53:20 -07001823 for cls in iter_classes:
1824 test = cls()
1825 test.inheritSetup(self)
1826 test.runTest()
1827 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001828 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001829 if time.time() - last > 60:
1830 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001831 logging.info(
Dan Talaycofa6454f2012-04-05 10:04:13 -07001832 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1833 (idx, count, tests_done, last - start) +
1834 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001835 stats = all_stats_get(self)
1836 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001837 logging.info("\nIterCases ran %d tests in %d seconds." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001838 (tests_done, last - start))
Rich Lane9a003812012-10-04 17:17:59 -07001839 logging.info(" flows: %d. packets: %d. bytes: %d" %
Dan Talayco8a64e332012-03-28 14:53:20 -07001840 (stats["flows"], stats["packets"], stats["bytes"]))
Rich Lane9a003812012-10-04 17:17:59 -07001841 logging.info(" active: %d. lookups: %d. matched %d." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001842 (stats["active"], stats["lookups"], stats["matched"]))
1843
Dan Talayco4b2bee62010-07-20 14:10:05 -07001844#@todo Need to implement tagged versions of the above tests
1845#
1846#@todo Implement a test case that strips tag 2, adds tag 3
1847# and modifies tag 4 to tag 5. Then verify (in addition) that
1848# tag 6 does not get modified.
1849
1850class MixedVLAN(BaseMatchCase):
1851 """
1852 Test mixture of VLAN tag actions
1853
1854 Strip tag 2 on port 1, send to port 2
1855 Add tag 3 on port 1, send to port 2
1856 Modify tag 4 to 5 on port 1, send to port 2
1857 All other traffic from port 1, send to port 3
1858 All traffic from port 2 sent to port 4
1859 Use exact matches with different packets for all mods
1860 Verify the following: (port, vid)
1861 (port 1, vid 2) => VLAN tag stripped, out port 2
1862 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1863 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1864 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1865 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1866 (port 2, no tag) => untagged packet out port 4
1867 (port 2, vid 2-6) => unmodified packet out port 4
1868
1869 Variation: Might try sending VID 5 to port 3 and check.
1870 If only VID 5 distinguishes pkt, this will fail on some platforms
1871 """
1872
Rich Laned1d9c282012-10-04 22:07:10 -07001873 priority = -1
Rich Lane8d6ab272012-09-23 18:06:20 -07001874
1875class MatchEach(basic.SimpleDataPlane):
1876 """
1877 Check that each match field is actually matched on.
1878 Installs two flows that differ in one field. The flow that should not
1879 match has a higher priority, so if that field is ignored during matching
1880 the packet will be sent out the wrong port.
1881
1882 TODO test UDP, ARP, ICMP, etc.
1883 """
1884 def runTest(self):
1885 of_ports = pa_port_map.keys()
1886 of_ports.sort()
1887 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1888
Rich Lane9a003812012-10-04 17:17:59 -07001889 delete_all_flows(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001890
1891 pkt = simple_tcp_packet()
1892 ingress_port = of_ports[0]
1893 egress_port = of_ports[1]
1894
1895 def testField(field, mask):
Rich Lane9a003812012-10-04 17:17:59 -07001896 logging.info("Testing field %s" % field)
Rich Lane8d6ab272012-09-23 18:06:20 -07001897
1898 def addFlow(matching, priority, output_port):
1899 match = packet_to_flow_match(self, pkt)
1900 self.assertTrue(match is not None, "Could not generate flow match from pkt")
1901 match.wildcards &= ~ofp.OFPFW_IN_PORT
1902 match.in_port = ingress_port
1903 if not matching:
1904 # Make sure flow doesn't match
1905 orig = getattr(match, field)
1906 if isinstance(orig, list):
1907 new = map(lambda a: ~a[0] & a[1], zip(orig, mask))
1908 else:
1909 new = ~orig & mask
1910 setattr(match, field, new)
1911 request = message.flow_mod()
1912 request.match = match
1913 request.buffer_id = 0xffffffff
1914 request.priority = priority
1915 act = action.action_output()
1916 act.port = output_port
1917 self.assertTrue(request.actions.add(act), "Could not add action")
Rich Lane9a003812012-10-04 17:17:59 -07001918 logging.info("Inserting flow")
Rich Lane8d6ab272012-09-23 18:06:20 -07001919 self.controller.message_send(request)
1920
1921 # This flow should match.
1922 addFlow(matching=True, priority=0, output_port=egress_port)
1923 # This flow should not match, but it has a higher priority.
1924 addFlow(matching=False, priority=1, output_port=ofp.OFPP_IN_PORT)
1925
1926 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
1927
Rich Lane9a003812012-10-04 17:17:59 -07001928 logging.info("Sending packet to dp port " + str(ingress_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001929 self.dataplane.send(ingress_port, str(pkt))
1930
1931 exp_pkt_arg = None
1932 exp_port = None
1933 if pa_config["relax"]:
1934 exp_pkt_arg = pkt
1935 exp_port = egress_port
1936
1937 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
1938 exp_pkt=exp_pkt_arg)
1939 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -07001940 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001941 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
1942 self.assertEqual(str(pkt), str(rcv_pkt), 'Response packet does not match send packet')
1943
1944 # TODO in_port
1945 testField("dl_src", [0xff]*6)
1946 testField("dl_dst", [0xff]*6)
1947 testField("dl_type", 0xffff)
1948 testField("dl_vlan", 0xfff)
1949 # TODO dl_vlan_pcp
1950 testField("nw_src", 0xffffffff)
1951 testField("nw_dst", 0xffffffff)
1952 testField("nw_tos", 0x3f)
1953 testField("nw_proto", 0xff)
1954 testField("tp_src", 0xffff)
1955 testField("tp_dst", 0xffff)
1956
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001957if __name__ == "__main__":
1958 print "Please run through oft script: ./oft --test_spec=basic"