blob: 5c1d7027dca90a4548f8d7132790d82631b4a97f [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
Rich Lane477f4812012-10-04 22:49:00 -070010The switch is actively attempting to contact the controller at the address
11indicated in config.
Dan Talayco5eba8442010-03-10 13:58:43 -080012
13"""
14
Dan Talayco9f47f4d2010-06-03 13:54:37 -070015import copy
16
Dan Talayco5eba8442010-03-10 13:58:43 -080017import logging
18
19import unittest
20
Rich Lane477f4812012-10-04 22:49:00 -070021from oftest import config
Dan Talayco5eba8442010-03-10 13:58:43 -080022import oftest.controller as controller
23import oftest.cstruct as ofp
24import oftest.message as message
25import oftest.dataplane as dataplane
26import oftest.action as action
27import oftest.parse as parse
28import basic
Dan Talayco8a64e332012-03-28 14:53:20 -070029import time
Dan Talayco5eba8442010-03-10 13:58:43 -080030
Rich Laneda3b5ad2012-10-03 09:05:32 -070031from oftest.testutils import *
Dan Talayco5eba8442010-03-10 13:58:43 -080032
Dan Talayco551befa2010-07-15 17:05:32 -070033WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
Dan Talayco488fbc52012-04-09 16:30:41 -070034 ofp.OFPFW_DL_VLAN | ofp.OFPFW_DL_VLAN_PCP,
Dan Talayco551befa2010-07-15 17:05:32 -070035 ofp.OFPFW_DL_SRC,
36 ofp.OFPFW_DL_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070037 (ofp.OFPFW_DL_TYPE | ofp.OFPFW_NW_SRC_ALL |
38 ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS | ofp.OFPFW_NW_PROTO |
39 ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
40 (ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
Dan Talayco551befa2010-07-15 17:05:32 -070041 ofp.OFPFW_TP_SRC,
42 ofp.OFPFW_TP_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070043 ofp.OFPFW_NW_SRC_MASK,
44 ofp.OFPFW_NW_DST_MASK,
Dan Talayco551befa2010-07-15 17:05:32 -070045 ofp.OFPFW_DL_VLAN_PCP,
46 ofp.OFPFW_NW_TOS]
47
Dan Talayco488fbc52012-04-09 16:30:41 -070048NO_WILDCARD_VALUES = [(ofp.OFPFW_ALL ^ ofp.OFPFW_IN_PORT),
49 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN),
50 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_SRC),
51 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_DST),
52 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE),
53 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO),
54 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
55 ofp.OFPFW_TP_SRC),
56 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
57 ofp.OFPFW_TP_DST),
58 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
59 ofp.OFPFW_NW_SRC_MASK),
60 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
61 ofp.OFPFW_NW_DST_MASK),
62 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN ^ ofp.OFPFW_DL_VLAN_PCP),
63 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
64 ofp.OFPFW_NW_TOS)]
65
Dan Talayco551befa2010-07-15 17:05:32 -070066MODIFY_ACTION_VALUES = [ofp.OFPAT_SET_VLAN_VID,
67 ofp.OFPAT_SET_VLAN_PCP,
68 ofp.OFPAT_STRIP_VLAN,
69 ofp.OFPAT_SET_DL_SRC,
70 ofp.OFPAT_SET_DL_DST,
71 ofp.OFPAT_SET_NW_SRC,
72 ofp.OFPAT_SET_NW_DST,
73 ofp.OFPAT_SET_NW_TOS,
74 ofp.OFPAT_SET_TP_SRC,
75 ofp.OFPAT_SET_TP_DST]
76
Dan Talayco21381562010-07-17 00:34:47 -070077TEST_VID_DEFAULT = 2
78
Dan Talayco5eba8442010-03-10 13:58:43 -080079class DirectPacket(basic.SimpleDataPlane):
80 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -070081 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -080082
83 Generate a packet
84 Generate and install a matching flow
85 Add action to direct the packet to an egress port
86 Send the packet to ingress dataplane port
87 Verify the packet is received at the egress port only
88 """
89 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -070090 self.handleFlow()
91
92 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -070093 of_ports = config["port_map"].keys()
Dan Talayco5eba8442010-03-10 13:58:43 -080094 of_ports.sort()
95 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
96
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -070097 if (pkttype == 'ICMP'):
98 pkt = simple_icmp_packet()
99 else:
100 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700101 match = packet_to_flow_match(self, pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700102 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800103 self.assertTrue(match is not None,
104 "Could not generate flow match from pkt")
105 act = action.action_output()
106
107 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700108 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700109 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700110
Dan Talayco5eba8442010-03-10 13:58:43 -0800111 ingress_port = of_ports[idx]
112 egress_port = of_ports[(idx + 1) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700113 logging.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700114 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800115
116 match.in_port = ingress_port
117
118 request = message.flow_mod()
119 request.match = match
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700120
Dan Talayco5eba8442010-03-10 13:58:43 -0800121 request.buffer_id = 0xffffffff
122 act.port = egress_port
123 self.assertTrue(request.actions.add(act), "Could not add action")
124
Rich Lane9a003812012-10-04 17:17:59 -0700125 logging.info("Inserting flow")
Dan Talayco5eba8442010-03-10 13:58:43 -0800126 rv = self.controller.message_send(request)
127 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700128 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco5eba8442010-03-10 13:58:43 -0800129
Rich Lane9a003812012-10-04 17:17:59 -0700130 logging.info("Sending packet to dp port " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800131 str(ingress_port))
132 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700133
134 exp_pkt_arg = None
135 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700136 if config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700137 exp_pkt_arg = pkt
138 exp_port = egress_port
139
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700140 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700141 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800142 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700143 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800144 str(rcv_port))
145 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
146 self.assertEqual(str(pkt), str(rcv_pkt),
147 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700148
Rich Lane51c23b32012-07-27 16:37:25 -0700149class DirectPacketController(basic.SimpleDataPlane):
150 """
151 Send packet to the controller port
152
153 Generate a packet
154 Generate and install a matching flow
155 Add action to direct the packet to the controller port
156 Send the packet to ingress dataplane port
157 Verify the packet is received at the controller port
158 """
159 def runTest(self):
160 self.handleFlow()
161
162 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700163 of_ports = config["port_map"].keys()
Rich Lane51c23b32012-07-27 16:37:25 -0700164 of_ports.sort()
165 self.assertTrue(len(of_ports) > 0, "Not enough ports for test")
166
167 if (pkttype == 'ICMP'):
168 pkt = simple_icmp_packet()
169 else:
170 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700171 match = packet_to_flow_match(self, pkt)
Rich Lane51c23b32012-07-27 16:37:25 -0700172 match.wildcards &= ~ofp.OFPFW_IN_PORT
173 self.assertTrue(match is not None,
174 "Could not generate flow match from pkt")
175 act = action.action_output()
176
Rich Lane9a003812012-10-04 17:17:59 -0700177 rv = delete_all_flows(self.controller)
Rich Lane51c23b32012-07-27 16:37:25 -0700178 self.assertEqual(rv, 0, "Failed to delete all flows")
179
180 ingress_port = of_ports[0]
181 match.in_port = ingress_port
182
183 request = message.flow_mod()
184 request.match = match
185
186 request.buffer_id = 0xffffffff
187 act.port = ofp.OFPP_CONTROLLER
188 act.max_len = 65535
189 self.assertTrue(request.actions.add(act), "Could not add action")
190
Rich Lane9a003812012-10-04 17:17:59 -0700191 logging.info("Inserting flow")
Rich Lane51c23b32012-07-27 16:37:25 -0700192 rv = self.controller.message_send(request)
193 self.assertTrue(rv != -1, "Error installing flow mod")
194 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
195
Rich Lane9a003812012-10-04 17:17:59 -0700196 logging.info("Sending packet to dp port " +
Rich Lane51c23b32012-07-27 16:37:25 -0700197 str(ingress_port))
198 self.dataplane.send(ingress_port, str(pkt))
199
200 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
201
202 self.assertTrue(response is not None,
203 'Packet in message not received by controller')
204 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700205 logging.debug("Sent %s" % format_packet(pkt))
206 logging.debug("Resp %s" % format_packet(response.data))
Rich Lane51c23b32012-07-27 16:37:25 -0700207 self.assertTrue(False,
208 'Response packet does not match send packet' +
209 ' for controller port')
210
Howard Pershf97840f2012-04-10 16:30:42 -0700211
212class DirectPacketQueue(basic.SimpleDataPlane):
213 """
214 Send packet to single queue on single egress port
215
216 Generate a packet
217 Generate and install a matching flow
218 Add action to direct the packet to an egress port and queue
219 Send the packet to ingress dataplane port
220 Verify the packet is received at the egress port only
221 """
222 def runTest(self):
223 self.handleFlow()
224
Howard Persh670b5672012-04-13 09:08:29 -0700225 def portQueuesGet(self, queue_stats, port_num):
226 result = []
227 for qs in queue_stats.stats:
228 if qs.port_no != port_num:
229 continue
230 result.append(qs.queue_id)
231 return result
232
Howard Pershf97840f2012-04-10 16:30:42 -0700233 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700234 of_ports = config["port_map"].keys()
Howard Pershf97840f2012-04-10 16:30:42 -0700235 of_ports.sort()
236 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
237
238 if (pkttype == 'ICMP'):
239 pkt = simple_icmp_packet()
240 else:
241 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700242 match = packet_to_flow_match(self, pkt)
Howard Pershf97840f2012-04-10 16:30:42 -0700243 match.wildcards &= ~ofp.OFPFW_IN_PORT
244 self.assertTrue(match is not None,
245 "Could not generate flow match from pkt")
246
Howard Persh670b5672012-04-13 09:08:29 -0700247 # Get queue stats from switch
248
249 request = message.queue_stats_request()
250 request.port_no = ofp.OFPP_ALL
251 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700252 (queue_stats, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700253 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
254
255 act = action.action_enqueue()
Howard Pershf97840f2012-04-10 16:30:42 -0700256
257 for idx in range(len(of_ports)):
Howard Pershf97840f2012-04-10 16:30:42 -0700258 ingress_port = of_ports[idx]
259 egress_port = of_ports[(idx + 1) % len(of_ports)]
Howard Pershf97840f2012-04-10 16:30:42 -0700260
Howard Persh670b5672012-04-13 09:08:29 -0700261 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700262 logging.info("Ingress " + str(ingress_port)
Howard Persh670b5672012-04-13 09:08:29 -0700263 + " to egress " + str(egress_port)
264 + " queue " + str(egress_queue_id)
265 )
Howard Pershf97840f2012-04-10 16:30:42 -0700266
Rich Lane9a003812012-10-04 17:17:59 -0700267 rv = delete_all_flows(self.controller)
Howard Persh670b5672012-04-13 09:08:29 -0700268 self.assertEqual(rv, 0, "Failed to delete all flows")
Howard Pershf97840f2012-04-10 16:30:42 -0700269
Howard Persh670b5672012-04-13 09:08:29 -0700270 match.in_port = ingress_port
271
272 request = message.flow_mod()
273 request.match = match
Howard Pershf97840f2012-04-10 16:30:42 -0700274
Howard Persh670b5672012-04-13 09:08:29 -0700275 request.buffer_id = 0xffffffff
276 act.port = egress_port
277 act.queue_id = egress_queue_id
278 self.assertTrue(request.actions.add(act), "Could not add action")
Howard Pershf97840f2012-04-10 16:30:42 -0700279
Rich Lane9a003812012-10-04 17:17:59 -0700280 logging.info("Inserting flow")
Howard Persh670b5672012-04-13 09:08:29 -0700281 rv = self.controller.message_send(request)
282 self.assertTrue(rv != -1, "Error installing flow mod")
283 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Howard Pershf97840f2012-04-10 16:30:42 -0700284
Howard Persh670b5672012-04-13 09:08:29 -0700285 # Get current stats for selected egress queue
Howard Pershf97840f2012-04-10 16:30:42 -0700286
Howard Persh670b5672012-04-13 09:08:29 -0700287 request = message.queue_stats_request()
288 request.port_no = egress_port
289 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700290 (qs_before, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700291 self.assertNotEqual(qs_before, None, "Queue stats request failed")
292
Rich Lane9a003812012-10-04 17:17:59 -0700293 logging.info("Sending packet to dp port " +
Howard Persh670b5672012-04-13 09:08:29 -0700294 str(ingress_port))
295 self.dataplane.send(ingress_port, str(pkt))
296
297 exp_pkt_arg = None
298 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700299 if config["relax"]:
Howard Persh670b5672012-04-13 09:08:29 -0700300 exp_pkt_arg = pkt
301 exp_port = egress_port
302
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700303 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Howard Persh670b5672012-04-13 09:08:29 -0700304 exp_pkt=exp_pkt_arg)
305 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700306 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Howard Persh670b5672012-04-13 09:08:29 -0700307 str(rcv_port))
308 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
309 self.assertEqual(str(pkt), str(rcv_pkt),
310 'Response packet does not match send packet')
311
Ed Swierkb8a86512012-04-18 18:45:58 -0700312 # FIXME: instead of sleeping, keep requesting queue stats until
313 # the expected queue counter increases or some large timeout is
314 # reached
315 time.sleep(2)
316
Howard Persh670b5672012-04-13 09:08:29 -0700317 # Get current stats for selected egress queue again
318
319 request = message.queue_stats_request()
320 request.port_no = egress_port
321 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700322 (qs_after, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700323 self.assertNotEqual(qs_after, None, "Queue stats request failed")
324
325 # Make sure that tx packet counter for selected egress queue was
326 # incremented
327
Ed Swierk22f59152012-04-17 16:36:47 -0700328 self.assertEqual(qs_after.stats[0].tx_packets, \
329 qs_before.stats[0].tx_packets + 1, \
Howard Persh670b5672012-04-13 09:08:29 -0700330 "Verification of egress queue tx packet count failed"
331 )
332
333
Ken Chiang899ff8e2012-05-23 18:26:12 -0700334class DirectPacketControllerQueue(basic.SimpleDataPlane):
335 """
336 Send a packet from each of the openflow ports
337 to each of the queues configured on the controller port.
338 If no queues have been configured, no packets are sent.
Howard Pershf97840f2012-04-10 16:30:42 -0700339
Ken Chiang899ff8e2012-05-23 18:26:12 -0700340 Generate a packet
341 Generate and install a matching flow
342 Add action to direct the packet to one of the controller port queues
343 Send the packet to ingress dataplane port
344 Verify the packet is received on the controller port queue
345 """
346 def runTest(self):
347 self.handleFlow()
348
349 def portQueuesGet(self, queue_stats, port_num):
350 result = []
351 for qs in queue_stats.stats:
352 if qs.port_no != port_num:
353 continue
354 result.append(qs.queue_id)
355 return result
356
357 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700358 of_ports = config["port_map"].keys()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700359 of_ports.sort()
360 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
361
362 if (pkttype == 'ICMP'):
363 pkt = simple_icmp_packet()
364 else:
365 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700366 match = packet_to_flow_match(self, pkt)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700367 match.wildcards &= ~ofp.OFPFW_IN_PORT
368 self.assertTrue(match is not None,
369 "Could not generate flow match from pkt")
370
371 # Get queue stats from switch
372
373 request = message.queue_stats_request()
374 request.port_no = ofp.OFPP_CONTROLLER
375 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700376 (queue_stats, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700377 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
378
379 act = action.action_enqueue()
380
381 for idx in range(len(of_ports)):
382 ingress_port = of_ports[idx]
383 egress_port = ofp.OFPP_CONTROLLER
384
Rich Lane9a003812012-10-04 17:17:59 -0700385 logging.info("Ingress port " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700386 + ", controller port queues "
387 + str(self.portQueuesGet(queue_stats, egress_port)))
388
389 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700390 logging.info("Ingress " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700391 + " to egress " + str(egress_port)
392 + " queue " + str(egress_queue_id)
393 )
394
Rich Lane9a003812012-10-04 17:17:59 -0700395 rv = delete_all_flows(self.controller)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700396 self.assertEqual(rv, 0, "Failed to delete all flows")
397
398 match.in_port = ingress_port
399
400 request = message.flow_mod()
401 request.match = match
402
403 request.buffer_id = 0xffffffff
404 act.port = egress_port
405 act.queue_id = egress_queue_id
406 self.assertTrue(request.actions.add(act), "Could not add action")
407
Rich Lane9a003812012-10-04 17:17:59 -0700408 logging.info("Inserting flow")
Ken Chiang899ff8e2012-05-23 18:26:12 -0700409 rv = self.controller.message_send(request)
410 self.assertTrue(rv != -1, "Error installing flow mod")
411 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
412
413 # Get current stats for selected egress queue
414
415 request = message.queue_stats_request()
416 request.port_no = egress_port
417 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700418 (qs_before, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700419 self.assertNotEqual(qs_before, None, "Queue stats request failed")
420
Rich Lane9a003812012-10-04 17:17:59 -0700421 logging.info("Sending packet to dp port " +
Ken Chiang899ff8e2012-05-23 18:26:12 -0700422 str(ingress_port))
423 self.dataplane.send(ingress_port, str(pkt))
424
425 exp_pkt_arg = None
426 exp_port = None
427
428 while True:
Dan Talaycoc689a792012-09-28 14:22:53 -0700429 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700430 if not response: # Timeout
431 break
432 if dataplane.match_exp_pkt(pkt, response.data): # Got match
433 break
Rich Lane477f4812012-10-04 22:49:00 -0700434 if not config["relax"]: # Only one attempt to match
Ken Chiang899ff8e2012-05-23 18:26:12 -0700435 break
436 count += 1
437 if count > 10: # Too many tries
438 break
439
440 self.assertTrue(response is not None,
441 'Packet in message not received by controller')
442 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700443 logging.debug("Sent %s" % format_packet(pkt))
444 logging.debug("Resp %s" % format_packet(response.data))
Ken Chiang899ff8e2012-05-23 18:26:12 -0700445 self.assertTrue(False,
446 'Response packet does not match send packet' +
447 ' for controller port')
448
449 # FIXME: instead of sleeping, keep requesting queue stats until
450 # the expected queue counter increases or some large timeout is
451 # reached
452 time.sleep(2)
453
454 # Get current stats for selected egress queue again
455
456 request = message.queue_stats_request()
457 request.port_no = egress_port
458 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700459 (qs_after, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700460 self.assertNotEqual(qs_after, None, "Queue stats request failed")
461
462 # Make sure that tx packet counter for selected egress queue was
463 # incremented
464
465 self.assertEqual(qs_after.stats[0].tx_packets, \
466 qs_before.stats[0].tx_packets + 1, \
467 "Verification of egress queue tx packet count failed"
468 )
469
Howard Pershf97840f2012-04-10 16:30:42 -0700470
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700471class DirectPacketICMP(DirectPacket):
472 """
473 Send ICMP packet to single egress port
474
475 Generate a ICMP packet
476 Generate and install a matching flow
477 Add action to direct the packet to an egress port
478 Send the packet to ingress dataplane port
479 Verify the packet is received at the egress port only
480 Difference from DirectPacket test is that sent packet is ICMP
481 """
482 def runTest(self):
483 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700484
485class DirectTwoPorts(basic.SimpleDataPlane):
486 """
487 Send packet to two egress ports
488
489 Generate a packet
490 Generate and install a matching flow
491 Add action to direct the packet to two egress ports
492 Send the packet to ingress dataplane port
493 Verify the packet is received at the two egress ports
494 """
495 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700496 of_ports = config["port_map"].keys()
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700497 of_ports.sort()
498 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
499
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700500 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700501 match = packet_to_flow_match(self, pkt)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700502 match.wildcards &= ~ofp.OFPFW_IN_PORT
503 self.assertTrue(match is not None,
504 "Could not generate flow match from pkt")
505 act = action.action_output()
506
507 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700508 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700509 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700510
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700511 ingress_port = of_ports[idx]
512 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
513 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700514 logging.info("Ingress " + str(ingress_port) +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700515 " to egress " + str(egress_port1) + " and " +
516 str(egress_port2))
517
518 match.in_port = ingress_port
519
520 request = message.flow_mod()
521 request.match = match
522 request.buffer_id = 0xffffffff
523 act.port = egress_port1
524 self.assertTrue(request.actions.add(act), "Could not add action1")
525 act.port = egress_port2
526 self.assertTrue(request.actions.add(act), "Could not add action2")
Rich Lane9a003812012-10-04 17:17:59 -0700527 # logging.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700528
Rich Lane9a003812012-10-04 17:17:59 -0700529 logging.info("Inserting flow")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700530 rv = self.controller.message_send(request)
531 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700532 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700533
Rich Lane9a003812012-10-04 17:17:59 -0700534 logging.info("Sending packet to dp port " +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700535 str(ingress_port))
536 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700537 yes_ports = set([egress_port1, egress_port2])
538 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700539
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700540 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Rich Lane477f4812012-10-04 22:49:00 -0700541 self, config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700542
543class DirectMCNonIngress(basic.SimpleDataPlane):
544 """
545 Multicast to all non-ingress ports
546
547 Generate a packet
548 Generate and install a matching flow
549 Add action to direct the packet to all non-ingress ports
550 Send the packet to ingress dataplane port
551 Verify the packet is received at all non-ingress ports
552
553 Does not use the flood action
554 """
555 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700556 of_ports = config["port_map"].keys()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700557 of_ports.sort()
558 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
559
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700560 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700561 match = packet_to_flow_match(self, pkt)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700562 match.wildcards &= ~ofp.OFPFW_IN_PORT
563 self.assertTrue(match is not None,
564 "Could not generate flow match from pkt")
565 act = action.action_output()
566
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700567 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700568 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700569 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700570
Rich Lane9a003812012-10-04 17:17:59 -0700571 logging.info("Ingress " + str(ingress_port) +
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700572 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700573 match.in_port = ingress_port
574
575 request = message.flow_mod()
576 request.match = match
577 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700578 for egress_port in of_ports:
579 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700580 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700581 act.port = egress_port
582 self.assertTrue(request.actions.add(act),
583 "Could not add output to " + str(egress_port))
Rich Lane9a003812012-10-04 17:17:59 -0700584 logging.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700585
Rich Lane9a003812012-10-04 17:17:59 -0700586 logging.info("Inserting flow")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700587 rv = self.controller.message_send(request)
588 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700589 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700590
Rich Lane9a003812012-10-04 17:17:59 -0700591 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700592 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700593 yes_ports = set(of_ports).difference([ingress_port])
594 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane477f4812012-10-04 22:49:00 -0700595 self, config)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700596
Dan Talayco32fa6542010-05-11 15:54:08 -0700597
598class DirectMC(basic.SimpleDataPlane):
599 """
600 Multicast to all ports including ingress
601
602 Generate a packet
603 Generate and install a matching flow
604 Add action to direct the packet to all non-ingress ports
605 Send the packet to ingress dataplane port
606 Verify the packet is received at all ports
607
608 Does not use the flood action
609 """
610 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700611 of_ports = config["port_map"].keys()
Dan Talayco32fa6542010-05-11 15:54:08 -0700612 of_ports.sort()
613 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
614
Dan Talayco32fa6542010-05-11 15:54:08 -0700615 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700616 match = packet_to_flow_match(self, pkt)
Dan Talayco32fa6542010-05-11 15:54:08 -0700617 match.wildcards &= ~ofp.OFPFW_IN_PORT
618 self.assertTrue(match is not None,
619 "Could not generate flow match from pkt")
620 act = action.action_output()
621
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700622 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700623 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700624 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700625
Rich Lane9a003812012-10-04 17:17:59 -0700626 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700627 match.in_port = ingress_port
628
629 request = message.flow_mod()
630 request.match = match
631 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700632 for egress_port in of_ports:
633 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700634 act.port = ofp.OFPP_IN_PORT
635 else:
636 act.port = egress_port
637 self.assertTrue(request.actions.add(act),
638 "Could not add output to " + str(egress_port))
Rich Lane9a003812012-10-04 17:17:59 -0700639 # logging.info(request.show())
Dan Talayco2e77a842010-05-12 15:39:46 -0700640
Rich Lane9a003812012-10-04 17:17:59 -0700641 logging.info("Inserting flow")
Dan Talayco2e77a842010-05-12 15:39:46 -0700642 rv = self.controller.message_send(request)
643 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700644 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2e77a842010-05-12 15:39:46 -0700645
Rich Lane9a003812012-10-04 17:17:59 -0700646 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700647 self.dataplane.send(ingress_port, str(pkt))
Rich Lane477f4812012-10-04 22:49:00 -0700648 receive_pkt_check(self.dataplane, pkt, of_ports, [], self, config)
Dan Talayco2e77a842010-05-12 15:39:46 -0700649
650class Flood(basic.SimpleDataPlane):
651 """
652 Flood to all ports except ingress
653
654 Generate a packet
655 Generate and install a matching flow
656 Add action to flood the packet
657 Send the packet to ingress dataplane port
658 Verify the packet is received at all other ports
659 """
660 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700661 of_ports = config["port_map"].keys()
Dan Talayco2e77a842010-05-12 15:39:46 -0700662 of_ports.sort()
663 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
664
665 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700666 match = packet_to_flow_match(self, pkt)
Dan Talayco2e77a842010-05-12 15:39:46 -0700667 match.wildcards &= ~ofp.OFPFW_IN_PORT
668 self.assertTrue(match is not None,
669 "Could not generate flow match from pkt")
670 act = action.action_output()
671
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700672 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700673 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700674 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700675
Rich Lane9a003812012-10-04 17:17:59 -0700676 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700677 match.in_port = ingress_port
678
679 request = message.flow_mod()
680 request.match = match
681 request.buffer_id = 0xffffffff
682 act.port = ofp.OFPP_FLOOD
683 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700684 "Could not add flood port action")
Rich Lane9a003812012-10-04 17:17:59 -0700685 logging.info(request.show())
Dan Talayco32fa6542010-05-11 15:54:08 -0700686
Rich Lane9a003812012-10-04 17:17:59 -0700687 logging.info("Inserting flow")
Dan Talayco32fa6542010-05-11 15:54:08 -0700688 rv = self.controller.message_send(request)
689 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700690 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco32fa6542010-05-11 15:54:08 -0700691
Rich Lane9a003812012-10-04 17:17:59 -0700692 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco32fa6542010-05-11 15:54:08 -0700693 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700694 yes_ports = set(of_ports).difference([ingress_port])
695 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane477f4812012-10-04 22:49:00 -0700696 self, config)
Dan Talayco3be5b062010-05-12 15:46:21 -0700697
Dan Talayco3be5b062010-05-12 15:46:21 -0700698class FloodPlusIngress(basic.SimpleDataPlane):
699 """
700 Flood to all ports plus send to ingress port
701
702 Generate a packet
703 Generate and install a matching flow
704 Add action to flood the packet
705 Add action to send to ingress port
706 Send the packet to ingress dataplane port
707 Verify the packet is received at all other ports
708 """
709 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700710 of_ports = config["port_map"].keys()
Dan Talayco3be5b062010-05-12 15:46:21 -0700711 of_ports.sort()
712 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
713
714 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700715 match = packet_to_flow_match(self, pkt)
Dan Talayco3be5b062010-05-12 15:46:21 -0700716 match.wildcards &= ~ofp.OFPFW_IN_PORT
717 self.assertTrue(match is not None,
718 "Could not generate flow match from pkt")
719 act = action.action_output()
720
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700721 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700722 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700723 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700724
Rich Lane9a003812012-10-04 17:17:59 -0700725 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700726 match.in_port = ingress_port
727
728 request = message.flow_mod()
729 request.match = match
730 request.buffer_id = 0xffffffff
731 act.port = ofp.OFPP_FLOOD
732 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700733 "Could not add flood port action")
734 act.port = ofp.OFPP_IN_PORT
735 self.assertTrue(request.actions.add(act),
736 "Could not add ingress port for output")
Rich Lane9a003812012-10-04 17:17:59 -0700737 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700738
Rich Lane9a003812012-10-04 17:17:59 -0700739 logging.info("Inserting flow")
Dan Talayco4aa13122010-05-12 15:54:44 -0700740 rv = self.controller.message_send(request)
741 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700742 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700743
Rich Lane9a003812012-10-04 17:17:59 -0700744 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700745 self.dataplane.send(ingress_port, str(pkt))
Rich Lane477f4812012-10-04 22:49:00 -0700746 receive_pkt_check(self.dataplane, pkt, of_ports, [], self, config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700747
748class All(basic.SimpleDataPlane):
749 """
750 Send to OFPP_ALL port
751
752 Generate a packet
753 Generate and install a matching flow
754 Add action to forward to OFPP_ALL
755 Send the packet to ingress dataplane port
756 Verify the packet is received at all other ports
757 """
758 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700759 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700760 of_ports.sort()
761 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
762
763 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700764 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700765 match.wildcards &= ~ofp.OFPFW_IN_PORT
766 self.assertTrue(match is not None,
767 "Could not generate flow match from pkt")
768 act = action.action_output()
769
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700770 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700771 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700772 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700773
Rich Lane9a003812012-10-04 17:17:59 -0700774 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700775 match.in_port = ingress_port
776
777 request = message.flow_mod()
778 request.match = match
779 request.buffer_id = 0xffffffff
780 act.port = ofp.OFPP_ALL
781 self.assertTrue(request.actions.add(act),
782 "Could not add ALL port action")
Rich Lane9a003812012-10-04 17:17:59 -0700783 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700784
Rich Lane9a003812012-10-04 17:17:59 -0700785 logging.info("Inserting flow")
Dan Talayco4aa13122010-05-12 15:54:44 -0700786 rv = self.controller.message_send(request)
787 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700788 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700789
Rich Lane9a003812012-10-04 17:17:59 -0700790 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700791 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700792 yes_ports = set(of_ports).difference([ingress_port])
793 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane477f4812012-10-04 22:49:00 -0700794 self, config)
Dan Talayco4aa13122010-05-12 15:54:44 -0700795
796class AllPlusIngress(basic.SimpleDataPlane):
797 """
798 Send to OFPP_ALL port and ingress port
799
800 Generate a packet
801 Generate and install a matching flow
802 Add action to forward to OFPP_ALL
803 Add action to forward to ingress port
804 Send the packet to ingress dataplane port
805 Verify the packet is received at all other ports
806 """
807 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700808 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700809 of_ports.sort()
810 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
811
812 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700813 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700814 match.wildcards &= ~ofp.OFPFW_IN_PORT
815 self.assertTrue(match is not None,
816 "Could not generate flow match from pkt")
817 act = action.action_output()
818
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700819 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700820 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700821 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700822
Rich Lane9a003812012-10-04 17:17:59 -0700823 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700824 match.in_port = ingress_port
825
826 request = message.flow_mod()
827 request.match = match
828 request.buffer_id = 0xffffffff
829 act.port = ofp.OFPP_ALL
830 self.assertTrue(request.actions.add(act),
831 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700832 act.port = ofp.OFPP_IN_PORT
833 self.assertTrue(request.actions.add(act),
834 "Could not add ingress port for output")
Rich Lane9a003812012-10-04 17:17:59 -0700835 logging.info(request.show())
Dan Talayco3be5b062010-05-12 15:46:21 -0700836
Rich Lane9a003812012-10-04 17:17:59 -0700837 logging.info("Inserting flow")
Dan Talayco3be5b062010-05-12 15:46:21 -0700838 rv = self.controller.message_send(request)
839 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700840 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco3be5b062010-05-12 15:46:21 -0700841
Rich Lane9a003812012-10-04 17:17:59 -0700842 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco3be5b062010-05-12 15:46:21 -0700843 self.dataplane.send(ingress_port, str(pkt))
Rich Lane477f4812012-10-04 22:49:00 -0700844 receive_pkt_check(self.dataplane, pkt, of_ports, [], self, config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700845
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700846class FloodMinusPort(basic.SimpleDataPlane):
847 """
848 Config port with No_Flood and test Flood action
849
850 Generate a packet
851 Generate a matching flow
852 Add action to forward to OFPP_ALL
853 Set port to no-flood
854 Send the packet to ingress dataplane port
855 Verify the packet is received at all other ports except
856 the ingress port and the no_flood port
857 """
858 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700859 of_ports = config["port_map"].keys()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700860 of_ports.sort()
861 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
862
863 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700864 match = packet_to_flow_match(self, pkt)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700865 match.wildcards &= ~ofp.OFPFW_IN_PORT
866 self.assertTrue(match is not None,
867 "Could not generate flow match from pkt")
868 act = action.action_output()
869
870 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700871 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700872 self.assertEqual(rv, 0, "Failed to delete all flows")
873
874 ingress_port = of_ports[idx]
875 no_flood_idx = (idx + 1) % len(of_ports)
876 no_flood_port = of_ports[no_flood_idx]
877 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700878 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700879 self.assertEqual(rv, 0, "Failed to set port config")
880
881 match.in_port = ingress_port
882
883 request = message.flow_mod()
884 request.match = match
885 request.buffer_id = 0xffffffff
886 act.port = ofp.OFPP_FLOOD
887 self.assertTrue(request.actions.add(act),
888 "Could not add flood port action")
Rich Lane9a003812012-10-04 17:17:59 -0700889 logging.info(request.show())
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700890
Rich Lane9a003812012-10-04 17:17:59 -0700891 logging.info("Inserting flow")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700892 rv = self.controller.message_send(request)
893 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700894 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700895
Rich Lane9a003812012-10-04 17:17:59 -0700896 logging.info("Sending packet to dp port " + str(ingress_port))
897 logging.info("No flood port is " + str(no_flood_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700898 self.dataplane.send(ingress_port, str(pkt))
899 no_ports = set([ingress_port, no_flood_port])
900 yes_ports = set(of_ports).difference(no_ports)
Rich Lane477f4812012-10-04 22:49:00 -0700901 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self, config)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700902
903 # Turn no flood off again
904 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700905 0, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700906 self.assertEqual(rv, 0, "Failed to reset port config")
907
908 #@todo Should check no other packets received
909
Dan Talayco21381562010-07-17 00:34:47 -0700910
911
Dan Talayco551befa2010-07-15 17:05:32 -0700912################################################################
913
914class BaseMatchCase(basic.SimpleDataPlane):
915 def setUp(self):
916 basic.SimpleDataPlane.setUp(self)
Dan Talayco551befa2010-07-15 17:05:32 -0700917 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -0700918 logging.info("BaseMatchCase")
Dan Talayco551befa2010-07-15 17:05:32 -0700919
920class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700921 """
Dan Talayco551befa2010-07-15 17:05:32 -0700922 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700923
924 Generate a packet
925 Generate and install a matching flow without wildcard mask
926 Add action to forward to a port
927 Send the packet to the port
928 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700929 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700930
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700931 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700932 flow_match_test(self, config["port_map"])
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700933
Dan Talayco551befa2010-07-15 17:05:32 -0700934class ExactMatchTagged(BaseMatchCase):
935 """
936 Exact match for all port pairs with tagged pkts
937 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700938
Dan Talayco551befa2010-07-15 17:05:32 -0700939 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700940 vid = test_param_get(config, 'vid', default=TEST_VID_DEFAULT)
941 flow_match_test(self, config["port_map"], dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700942
Dan Talayco551befa2010-07-15 17:05:32 -0700943class ExactMatchTaggedMany(BaseMatchCase):
944 """
945 ExactMatchTagged with many VLANS
946 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700947
Rich Laned1d9c282012-10-04 22:07:10 -0700948 priority = -1
949
Dan Talayco551befa2010-07-15 17:05:32 -0700950 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700951 for vid in range(2,100,10):
Rich Lane477f4812012-10-04 22:49:00 -0700952 flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
Dan Talayco551befa2010-07-15 17:05:32 -0700953 for vid in range(100,4000,389):
Rich Lane477f4812012-10-04 22:49:00 -0700954 flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
955 flow_match_test(self, config["port_map"], dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700956
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700957class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700958 """
959 SingleWildcardMatchPriority
960 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700961
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700962 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700963 self.pkt = simple_tcp_packet()
964 self.flowMsgs = {}
965
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700966 def _ClearTable(self):
Rich Lane9a003812012-10-04 17:17:59 -0700967 rc = delete_all_flows(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700968 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700969 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700970
971 def runTest(self):
972
973 self._Init()
Rich Lane477f4812012-10-04 22:49:00 -0700974 of_ports = config["port_map"].keys()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700975 of_ports.sort()
976
977 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700978 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700979
980 # Run several combinations, each at lower priority settings.
981 # At the end of each call to runPrioFlows(), the table should
982 # be empty. If its not, we'll catch it as the priorities decreases
983 portA = of_ports[0]
984 portB = of_ports[1]
985 portC = of_ports[2]
986
987 # TODO -- these priority numbers should be validated somehow?
988 self.runPrioFlows(portA, portB, portC, 1000, 999)
989 self.runPrioFlows(portB, portC, portA, 998, 997)
990 self.runPrioFlows(portC, portA, portB, 996, 995)
991 self.runPrioFlows(portA, portC, portB, 994, 993)
992
993
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700994
995 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
996 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700997
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700998 if clearTable:
999 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001000
1001 # Sanity check flow at lower priority from pA to pB
Rich Lane9a003812012-10-04 17:17:59 -07001002 logging.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001003 % (portA, portB, portC, prioHigher, prioLower))
1004
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001005 # Sanity check flow at lower priority from pA to pC
1006 self.installFlow(prioLower, portA, portC)
1007 self.verifyFlow(portA, portC)
1008 self.removeFlow(prioLower)
1009
1010 # Install and verify pA->pB @ prioLower
1011 self.installFlow(prioLower, portA, portB)
1012 self.verifyFlow(portA, portB)
1013
1014 # Install and verify pA->pC @ prioHigher, should override pA->pB
1015 self.installFlow(prioHigher, portA, portC)
1016 self.verifyFlow(portA, portC)
1017 # remove pA->pC
1018 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001019 # Old flow pA -> pB @ prioLower should still be active
1020 self.verifyFlow(portA, portB)
1021 self.removeFlow(prioLower)
1022
1023 # Table should be empty at this point, leave it alone as
1024 # an assumption for future test runs
1025
1026
1027
Ed Swierk99a74de2012-08-22 06:40:54 -07001028 def installFlow(self, prio, inp, egp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001029 wildcards=ofp.OFPFW_DL_SRC):
Ed Swierk99a74de2012-08-22 06:40:54 -07001030 wildcards |= required_wildcards(self)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001031 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001032 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001033 egr_ports=egp)
1034 request.priority = prio
Rich Lane9a003812012-10-04 17:17:59 -07001035 logging.debug("Install flow with priority " + str(prio))
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001036 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001037 self.flowMsgs[prio] = request
1038
1039 def removeFlow(self, prio):
1040 if self.flowMsgs.has_key(prio):
1041 msg = self.flowMsgs[prio]
1042 msg.command = ofp.OFPFC_DELETE_STRICT
1043 # This *must* be set for DELETE
1044 msg.out_port = ofp.OFPP_NONE
Rich Lane9a003812012-10-04 17:17:59 -07001045 logging.debug("Remove flow with priority " + str(prio))
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001046 self.controller.message_send(msg)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001047 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001048 else:
1049 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001050
1051
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001052 def verifyFlow(self, inp, egp, pkt=None):
1053 if pkt == None:
1054 pkt = self.pkt
1055
Rich Lane9a003812012-10-04 17:17:59 -07001056 logging.info("Pkt match test: " + str(inp) + " to " + str(egp))
1057 logging.debug("Send packet: " + str(inp) + " to " + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001058 self.dataplane.send(inp, str(pkt))
1059 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001060
1061
1062
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001063class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
1064
1065 def runTest(self):
1066
1067 self._Init()
1068
Rich Lane477f4812012-10-04 22:49:00 -07001069 of_ports = config["port_map"].keys()
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001070 of_ports.sort()
1071
1072 # Install an entry from 0 -> 1 @ prio 1000
1073 self._ClearTable()
1074 self.installFlow(1000, of_ports[0], of_ports[1])
1075 self.verifyFlow(of_ports[0], of_ports[1])
1076 self.installFlow(1000, of_ports[1], of_ports[0])
1077 self.verifyFlow(of_ports[1], of_ports[0])
1078 self.installFlow(1001, of_ports[0], of_ports[1])
1079 self.verifyFlow(of_ports[0], of_ports[1])
1080 self.installFlow(1001, of_ports[1], of_ports[0])
1081 self.verifyFlow(of_ports[1], of_ports[0])
1082 self.removeFlow(1001)
1083 self.verifyFlow(of_ports[0], of_ports[1])
1084 self.removeFlow(1000)
1085
1086
1087
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001088class WildcardPriority(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001089 """
1090 1. Add wildcard flow, verify packet received.
1091 2. Add exact match flow with higher priority, verify packet received
1092 on port specified by this flow.
1093 3. Add wildcard flow with even higher priority, verify packet received
1094 on port specified by this flow.
1095 """
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001096
1097 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001098
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001099 self._Init()
1100
Rich Lane477f4812012-10-04 22:49:00 -07001101 of_ports = config["port_map"].keys()
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001102 of_ports.sort()
1103
1104 self._ClearTable()
Ken Chiang38d7a152012-05-24 15:33:50 -07001105
1106 # Install a flow with wildcards
1107 self.installFlow(999, of_ports[0], of_ports[1],
1108 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001109 self.verifyFlow(of_ports[0], of_ports[1])
Ken Chiang38d7a152012-05-24 15:33:50 -07001110 # Install a flow with no wildcards for our packet
1111 self.installFlow(1000, of_ports[0], of_ports[2], wildcards=0)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001112 self.verifyFlow(of_ports[0], of_ports[2])
Ken Chiang38d7a152012-05-24 15:33:50 -07001113 # Install a flow with wildcards for our packet with higher
1114 # priority
1115 self.installFlow(1001, of_ports[0], of_ports[3])
1116 self.verifyFlow(of_ports[0], of_ports[3])
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001117
1118
Ken Chiang3978f242012-06-13 14:14:09 -07001119class WildcardPriorityWithDelete(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001120 """
1121 1. Add exact match flow, verify packet received.
1122 2. Add wildcard flow with higher priority, verify packet received on port
1123 specified by this flow.
1124 3. Add exact match flow with even higher priority, verify packet received
1125 on port specified by this flow.
1126 4. Delete lowest priority flow, verify packet received on port specified
1127 by highest priority flow.
1128 5. Delete highest priority flow, verify packet received on port specified
1129 by remaining flow.
1130 """
1131
1132 def runTest(self):
1133
1134 self._Init()
1135
Rich Lane477f4812012-10-04 22:49:00 -07001136 of_ports = config["port_map"].keys()
Ken Chiang38d7a152012-05-24 15:33:50 -07001137 of_ports.sort()
1138
1139 self._ClearTable()
1140
1141 # Install an exact match flow
1142 self.installFlow(250, of_ports[0], of_ports[1], wildcards=0)
1143 self.verifyFlow(of_ports[0], of_ports[1])
1144 # Install a flow with wildcards of higher priority
1145 self.installFlow(1250, of_ports[0], of_ports[2],
1146 wildcards=ofp.OFPFW_DL_DST)
1147 self.verifyFlow(of_ports[0], of_ports[2])
1148 # Install an exact match flow with even higher priority
1149 self.installFlow(2001, of_ports[0], of_ports[3], wildcards=0)
1150 self.verifyFlow(of_ports[0], of_ports[3])
1151 # Delete lowest priority flow
1152 self.removeFlow(250)
1153 self.verifyFlow(of_ports[0], of_ports[3])
1154 # Delete highest priority flow
1155 self.removeFlow(2001)
1156 self.verifyFlow(of_ports[0], of_ports[2])
1157
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001158
Dan Talayco551befa2010-07-15 17:05:32 -07001159class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001160 """
1161 Exercise wildcard matching for all ports
1162
1163 Generate a packet
1164 Generate and install a matching flow with wildcard mask
1165 Add action to forward to a port
1166 Send the packet to the port
1167 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001168 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001169 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001170 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001171 vid = test_param_get(config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001172 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001173 wc |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001174 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001175 # Set nonzero VLAN id to avoid sending priority-tagged packet
1176 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001177 else:
1178 dl_vlan = -1
Rich Lane477f4812012-10-04 22:49:00 -07001179 flow_match_test(self, config["port_map"], wildcards=wc,
Dan Talayco4431d542012-03-21 16:42:16 -07001180 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001181
Dan Talayco551befa2010-07-15 17:05:32 -07001182class SingleWildcardMatchTagged(BaseMatchCase):
1183 """
1184 SingleWildcardMatch with tagged packets
1185 """
1186 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001187 vid = test_param_get(config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001188 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001189 wc |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001190 flow_match_test(self, config["port_map"], wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -07001191 max_test=10)
1192
1193class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001194 """
Dan Talayco80b54ed2010-07-13 09:48:35 -07001195 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001196
1197 Generate a packet
1198 Generate and install a matching flow with wildcard all except one filed
1199 Add action to forward to a port
1200 Send the packet to the port
1201 Verify the packet is received at all other ports (one port at a time)
1202 Verify flow_expiration message is correct when command option is set
1203 """
1204 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001205 vid = test_param_get(config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001206 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001207 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001208 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001209 # Set nonzero VLAN id to avoid sending priority-tagged packet
1210 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001211 else:
1212 dl_vlan = -1
Rich Lane477f4812012-10-04 22:49:00 -07001213 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Dan Talayco4431d542012-03-21 16:42:16 -07001214 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001215
Dan Talayco551befa2010-07-15 17:05:32 -07001216class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1217 """
1218 Match one field with tagged packets
1219 """
1220 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001221 vid = test_param_get(config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001222 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001223 all_exp_one_wildcard |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001224 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Dan Talayco21381562010-07-17 00:34:47 -07001225 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001226
1227class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001228 """
1229 Create Wildcard-all flow and exercise for all ports
1230
1231 Generate a packet
1232 Generate and install a matching flow with wildcard-all
1233 Add action to forward to a port
1234 Send the packet to the port
1235 Verify the packet is received at all other ports (one port at a time)
1236 Verify flow_expiration message is correct when command option is set
1237 """
1238 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001239 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001240
Dan Talayco551befa2010-07-15 17:05:32 -07001241class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001242 """
Dan Talayco551befa2010-07-15 17:05:32 -07001243 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001244 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001245 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001246 vid = test_param_get(config, 'vid', default=TEST_VID_DEFAULT)
1247 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL,
Dan Talayco21381562010-07-17 00:34:47 -07001248 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001249
Dan Talaycoba3745c2010-07-21 21:51:08 -07001250
Dan Talayco551befa2010-07-15 17:05:32 -07001251class AddVLANTag(BaseMatchCase):
1252 """
1253 Add a VLAN tag to an untagged packet
1254 """
1255 def runTest(self):
1256 new_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001257 sup_acts = self.supported_actions
Dan Talayco551befa2010-07-15 17:05:32 -07001258 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001259 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001260 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001261
Dan Talayco551befa2010-07-15 17:05:32 -07001262 len = 100
1263 len_w_vid = 104
1264 pkt = simple_tcp_packet(pktlen=len)
1265 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1266 dl_vlan=new_vid)
1267 vid_act = action.action_set_vlan_vid()
1268 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001269
Rich Lane477f4812012-10-04 22:49:00 -07001270 flow_match_test(self, config["port_map"], pkt=pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001271 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001272
Dan Talayco551befa2010-07-15 17:05:32 -07001273class PacketOnly(basic.DataPlaneOnly):
1274 """
1275 Just send a packet thru the switch
1276 """
Rich Laned1d9c282012-10-04 22:07:10 -07001277
1278 priority = -1
1279
Dan Talayco551befa2010-07-15 17:05:32 -07001280 def runTest(self):
1281 pkt = simple_tcp_packet()
Rich Lane477f4812012-10-04 22:49:00 -07001282 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001283 of_ports.sort()
1284 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001285 logging.info("Sending packet to " + str(ing_port))
1286 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001287 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001288
Dan Talayco551befa2010-07-15 17:05:32 -07001289class PacketOnlyTagged(basic.DataPlaneOnly):
1290 """
1291 Just send a packet thru the switch
1292 """
Rich Laned1d9c282012-10-04 22:07:10 -07001293
1294 priority = -1
1295
Dan Talayco551befa2010-07-15 17:05:32 -07001296 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001297 vid = test_param_get(config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001298 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
Rich Lane477f4812012-10-04 22:49:00 -07001299 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001300 of_ports.sort()
1301 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001302 logging.info("Sending packet to " + str(ing_port))
1303 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001304 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001305
Dan Talayco551befa2010-07-15 17:05:32 -07001306class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001307 """
1308 Modify the VLAN ID in the VLAN tag of a tagged packet
1309 """
Dan Talaycoaf669322012-09-12 22:51:22 -07001310 def setUp(self):
1311 BaseMatchCase.setUp(self)
1312 self.ing_port=False
1313
Dan Talayco551befa2010-07-15 17:05:32 -07001314 def runTest(self):
1315 old_vid = 2
1316 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001317 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001318 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001319 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001320 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001321
Dan Talayco551befa2010-07-15 17:05:32 -07001322 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1323 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
1324 vid_act = action.action_set_vlan_vid()
1325 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001326
Rich Lane477f4812012-10-04 22:49:00 -07001327 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoaf669322012-09-12 22:51:22 -07001328 action_list=[vid_act], ing_port=self.ing_port)
1329
1330class ModifyVIDToIngress(ModifyVID):
1331 """
1332 Modify the VLAN ID in the VLAN tag of a tagged packet and send to
1333 ingress port
1334 """
1335 def setUp(self):
1336 BaseMatchCase.setUp(self)
1337 self.ing_port=True
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001338
Ken Chiange9a211d2012-04-20 14:52:11 -07001339class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1340 """
1341 With vlan ID and priority wildcarded, perform SET_VLAN_VID action.
1342 The same flow should match on both untagged and tagged packets.
1343 """
1344 def runTest(self):
1345 old_vid = 2
1346 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001347 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001348 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1349 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1350 return
1351
Rich Lane477f4812012-10-04 22:49:00 -07001352 of_ports = config["port_map"].keys()
Ken Chiange9a211d2012-04-20 14:52:11 -07001353 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1354 ing_port = of_ports[0]
1355 egr_ports = of_ports[1]
1356
Rich Lane9a003812012-10-04 17:17:59 -07001357 rv = delete_all_flows(self.controller)
Ken Chiange9a211d2012-04-20 14:52:11 -07001358 self.assertEqual(rv, 0, "Failed to delete all flows")
1359
1360 len_untagged = 100
1361 len_w_vid = 104
1362 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1363 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
1364 dl_vlan_enable=True, dl_vlan=old_vid)
1365 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1366 dl_vlan=new_vid)
Ed Swierk99a74de2012-08-22 06:40:54 -07001367 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1368 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001369 vid_act = action.action_set_vlan_vid()
1370 vid_act.vlan_vid = new_vid
1371 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
1372 wildcards=wildcards, egr_ports=egr_ports,
1373 action_list=[vid_act])
1374 flow_msg_install(self, request)
1375
Rich Lane9a003812012-10-04 17:17:59 -07001376 logging.debug("Send untagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001377 str(egr_ports))
1378 self.dataplane.send(ing_port, str(untagged_pkt))
1379 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1380
Rich Lane9a003812012-10-04 17:17:59 -07001381 logging.debug("Send tagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001382 str(egr_ports))
1383 self.dataplane.send(ing_port, str(tagged_pkt))
1384 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1385
Howard Pershc1199d52012-04-11 14:21:32 -07001386class ModifyVlanPcp(BaseMatchCase):
1387 """
1388 Modify the priority field of the VLAN tag of a tagged packet
1389 """
1390 def runTest(self):
1391 vid = 123
1392 old_vlan_pcp = 2
1393 new_vlan_pcp = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001394 sup_acts = self.supported_actions
Ed Swierk8c3af7f2012-04-24 14:19:17 -07001395 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_PCP):
1396 skip_message_emit(self, "Modify VLAN priority test")
Howard Pershc1199d52012-04-11 14:21:32 -07001397 return
1398
1399 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1400 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1401 vid_act = action.action_set_vlan_pcp()
1402 vid_act.vlan_pcp = new_vlan_pcp
1403
Rich Lane477f4812012-10-04 22:49:00 -07001404 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Howard Pershc1199d52012-04-11 14:21:32 -07001405 action_list=[vid_act])
1406
Dan Talayco551befa2010-07-15 17:05:32 -07001407class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001408 """
1409 Strip the VLAN tag from a tagged packet
1410 """
Dan Talayco551befa2010-07-15 17:05:32 -07001411 def runTest(self):
1412 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001413 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001414 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001415 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001416 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001417
Dan Talayco551befa2010-07-15 17:05:32 -07001418 len_w_vid = 104
1419 len = 100
1420 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1421 dl_vlan=old_vid)
1422 exp_pkt = simple_tcp_packet(pktlen=len)
1423 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001424
Rich Lane477f4812012-10-04 22:49:00 -07001425 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001426 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001427
Ken Chiange9a211d2012-04-20 14:52:11 -07001428class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1429 """
1430 Strip the VLAN tag from a tagged packet.
1431 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1432 """
1433 def runTest(self):
1434 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001435 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001436 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1437 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1438 return
1439
1440 len_w_vid = 104
1441 len_untagged = 100
1442 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1443 dl_vlan=old_vid)
1444 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
Ed Swierk99a74de2012-08-22 06:40:54 -07001445 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1446 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001447 vid_act = action.action_strip_vlan()
1448
Rich Lane477f4812012-10-04 22:49:00 -07001449 flow_match_test(self, config["port_map"],
Ed Swierk99a74de2012-08-22 06:40:54 -07001450 wildcards=wildcards,
Ken Chiange9a211d2012-04-20 14:52:11 -07001451 pkt=pkt, exp_pkt=exp_pkt,
1452 action_list=[vid_act])
1453
Dan Talayco4b2bee62010-07-20 14:10:05 -07001454def init_pkt_args():
1455 """
1456 Pass back a dictionary with default packet arguments
1457 """
1458 args = {}
1459 args["dl_src"] = '00:23:45:67:89:AB'
1460
1461 dl_vlan_enable=False
1462 dl_vlan=-1
Rich Lane477f4812012-10-04 22:49:00 -07001463 if config["test-params"]["vid"]:
Dan Talayco4b2bee62010-07-20 14:10:05 -07001464 dl_vlan_enable=True
Rich Lane477f4812012-10-04 22:49:00 -07001465 dl_vlan = config["test-params"]["vid"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001466
1467# Unpack operator is ** on a dictionary
1468
1469 return args
1470
Dan Talayco551befa2010-07-15 17:05:32 -07001471class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001472 """
1473 Modify the source MAC address (TP1)
1474 """
Dan Talayco551befa2010-07-15 17:05:32 -07001475 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001476 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001477 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001478 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001479 return
1480
1481 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1482 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001483 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001484 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001485
Dan Talayco551befa2010-07-15 17:05:32 -07001486class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001487 """
1488 Modify the dest MAC address (TP1)
1489 """
Dan Talayco551befa2010-07-15 17:05:32 -07001490 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001491 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001492 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001493 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001494 return
1495
1496 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1497 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001498 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001499 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001500
Dan Talayco551befa2010-07-15 17:05:32 -07001501class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001502 """
1503 Modify the source IP address of an IP packet (TP1)
1504 """
Dan Talayco551befa2010-07-15 17:05:32 -07001505 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001506 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001507 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001508 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001509 return
1510
1511 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1512 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001513 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001514 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001515
Dan Talayco551befa2010-07-15 17:05:32 -07001516class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001517 """
1518 Modify the dest IP address of an IP packet (TP1)
1519 """
Dan Talayco551befa2010-07-15 17:05:32 -07001520 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001521 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001522 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001523 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001524 return
1525
1526 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1527 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001528 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001529 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001530
1531class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001532 """
1533 Modify the source TCP port of a TCP packet (TP1)
1534 """
Dan Talayco551befa2010-07-15 17:05:32 -07001535 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001536 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001537 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001538 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001539 return
1540
1541 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1542 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001543 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001544 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001545
1546class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001547 """
1548 Modify the dest TCP port of a TCP packet (TP1)
1549 """
Dan Talayco551befa2010-07-15 17:05:32 -07001550 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001551 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001552 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001553 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001554 return
1555
1556 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1557 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001558 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001559 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001560
1561class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001562 """
1563 Modify the IP type of service of an IP packet (TP1)
1564 """
Dan Talayco551befa2010-07-15 17:05:32 -07001565 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001566 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001567 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001568 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001569 return
Dan Talayco551befa2010-07-15 17:05:32 -07001570
Dan Talayco4b2bee62010-07-20 14:10:05 -07001571 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1572 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001573 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001574 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001575
Dan Talaycof6e76c02012-03-23 10:56:12 -07001576class ModifyL2DstMC(BaseMatchCase):
1577 """
1578 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001579 """
1580 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001581 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001582 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001583 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001584 return
1585
Dan Talaycof6e76c02012-03-23 10:56:12 -07001586 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1587 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001588 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001589 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001590
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001591class ModifyL2DstIngress(BaseMatchCase):
1592 """
1593 Modify the L2 dest and send to the ingress port
1594 """
1595 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001596 sup_acts = self.supported_actions
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001597 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001598 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001599 return
1600
1601 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1602 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001603 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001604 action_list=acts, max_test=2, egr_count=0,
1605 ing_port=True)
1606
Dan Talaycod8ae7582012-03-23 12:24:56 -07001607class ModifyL2DstIngressMC(BaseMatchCase):
1608 """
1609 Modify the L2 dest and send to the ingress port
1610 """
1611 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001612 sup_acts = self.supported_actions
Dan Talaycod8ae7582012-03-23 12:24:56 -07001613 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1614 skip_message_emit(self, "ModifyL2dstMC test")
1615 return
1616
1617 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1618 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001619 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001620 action_list=acts, max_test=2, egr_count=-1,
1621 ing_port=True)
1622
Dan Talaycof6e76c02012-03-23 10:56:12 -07001623class ModifyL2SrcMC(BaseMatchCase):
1624 """
1625 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001626 """
1627 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001628 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001629 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001630 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001631 return
1632
Dan Talaycof6e76c02012-03-23 10:56:12 -07001633 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1634 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001635 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001636 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001637
1638class ModifyL2SrcDstMC(BaseMatchCase):
1639 """
1640 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001641 """
1642 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001643 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001644 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1645 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1646 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001647 return
1648
Dan Talaycof6e76c02012-03-23 10:56:12 -07001649 mod_fields = ['dl_dst', 'dl_src']
1650 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1651 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001652 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001653 action_list=acts, max_test=2, egr_count=-1)
1654
1655class ModifyL2DstVIDMC(BaseMatchCase):
1656 """
1657 Modify the L2 dest and send to 2 ports
1658 """
1659 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001660 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001661 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1662 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1663 skip_message_emit(self, "ModifyL2DstVIDMC test")
1664 return
1665
1666 mod_fields = ['dl_dst', 'dl_vlan']
1667 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1668 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1669 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001670 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001671 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001672
Dan Talaycofa6454f2012-04-05 10:04:13 -07001673class FlowToggle(BaseMatchCase):
1674 """
1675 Add flows to the table and modify them repeatedly
Dan Talaycof7c41312012-07-23 12:53:19 -07001676
1677 This is done by using only "add" flow messages. Since the check overlap
1678 flag is not set, the switch is supposed to modify the existing flow if
1679 the match already exists.
1680
1681 Would probably be better to exercise more of the flow modify commands
1682 (add, modify, delete +/- strict).
Dan Talaycofa6454f2012-04-05 10:04:13 -07001683 """
1684 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001685 flow_count = test_param_get(config, 'ft_flow_count', default=20)
1686 iter_count = test_param_get(config, 'ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001687
Rich Lane9a003812012-10-04 17:17:59 -07001688 logging.info("Running flow toggle with %d flows, %d iterations" %
Dan Talaycofa6454f2012-04-05 10:04:13 -07001689 (flow_count, iter_count))
1690 acts = []
1691 acts.append(action.action_output())
1692 acts.append(action.action_output())
1693
Rich Lane477f4812012-10-04 22:49:00 -07001694 of_ports = config["port_map"].keys()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001695 if len(of_ports) < 3:
1696 self.assertTrue(False, "Too few ports for test")
1697
1698 for idx in range(2):
1699 acts[idx].port = of_ports[idx]
1700
1701 flows = []
1702 flows.append([])
1703 flows.append([])
1704
Ed Swierk99a74de2012-08-22 06:40:54 -07001705 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_SRC |
1706 ofp.OFPFW_DL_DST)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001707 # Create up the flows in an array
1708 for toggle in range(2):
1709 for f_idx in range(flow_count):
1710 pkt = simple_tcp_packet(tcp_sport=f_idx)
1711 msg = message.flow_mod()
Ed Swierk99a74de2012-08-22 06:40:54 -07001712 match = packet_to_flow_match(self, pkt)
Shudong Zhou031373c2012-07-19 17:37:42 -07001713 match.in_port = of_ports[2]
Dan Talayco50be7672012-04-05 11:38:08 -07001714 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001715 msg.match = match
1716 msg.buffer_id = 0xffffffff
Dan Talaycof7c41312012-07-23 12:53:19 -07001717 msg.command = ofp.OFPFC_ADD
Dan Talaycofa6454f2012-04-05 10:04:13 -07001718 msg.actions.add(acts[toggle])
1719 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001720
1721 # Show two sample flows
Rich Lane9a003812012-10-04 17:17:59 -07001722 logging.debug(flows[0][0].show())
1723 logging.debug(flows[1][0].show())
Dan Talayco50be7672012-04-05 11:38:08 -07001724
Dan Talaycofa6454f2012-04-05 10:04:13 -07001725 # Install the first set of flows
1726 for f_idx in range(flow_count):
1727 rv = self.controller.message_send(flows[0][f_idx])
1728 self.assertTrue(rv != -1, "Error installing flow %d" % f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001729 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycofa6454f2012-04-05 10:04:13 -07001730
Rich Lane9a003812012-10-04 17:17:59 -07001731 logging.info("Installed %d flows" % flow_count)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001732
1733 # Repeatedly modify all the flows back and forth
1734 updates = 0
1735 # Report status about 5 times
1736 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001737 start = time.time()
1738 for iter_idx in range(iter_count):
1739 if not iter_idx % mod_val:
Rich Lane9a003812012-10-04 17:17:59 -07001740 logging.info("Flow Toggle: iter %d of %d. " %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001741 (iter_idx, iter_count) +
1742 "%d updates in %d secs" %
1743 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001744 for toggle in range(2):
1745 t_idx = 1 - toggle
1746 for f_idx in range(flow_count):
1747 rv = self.controller.message_send(flows[t_idx][f_idx])
1748 updates += 1
1749 self.assertTrue(rv != -1, "Error modifying flow %d" %
1750 f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001751 self.assertEqual(do_barrier(self.controller), 0,
1752 "Barrier failed")
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001753
1754 end = time.time()
1755 divisor = end - start or (end - start + 1)
Rich Lane9a003812012-10-04 17:17:59 -07001756 logging.info("Flow toggle: %d iterations" % iter_count)
1757 logging.info(" %d flow mods in %d secs, %d mods/sec" %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001758 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001759
1760
Dan Talayco8a64e332012-03-28 14:53:20 -07001761# You can pick and choose these by commenting tests in or out
1762iter_classes = [
1763 basic.PacketIn,
1764 basic.PacketOut,
1765 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001766 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001767 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001768 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001769 AllWildcardMatch,
1770 AllWildcardMatchTagged,
1771 SingleWildcardMatch,
1772 SingleWildcardMatchTagged,
1773 ExactMatch,
1774 ExactMatchTagged,
1775 SingleWildcardMatch,
1776 ModifyL2Src,
1777 ModifyL2Dst,
1778 ModifyL2SrcMC,
1779 ModifyL2DstMC,
1780 ModifyL2SrcDstMC
1781 ]
1782
1783class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001784 """
1785 Iterate over a bunch of test cases
1786
1787 The cases come from the list above
1788 """
1789
Rich Laned1d9c282012-10-04 22:07:10 -07001790 priority = -1
1791
Dan Talayco8a64e332012-03-28 14:53:20 -07001792 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001793 count = test_param_get(config, 'iter_count', default=10)
Dan Talayco8a64e332012-03-28 14:53:20 -07001794 tests_done = 0
Rich Lane9a003812012-10-04 17:17:59 -07001795 logging.info("Running iteration test " + str(count) + " times")
Dan Talayco8a64e332012-03-28 14:53:20 -07001796 start = time.time()
1797 last = start
1798 for idx in range(count):
Rich Lane9a003812012-10-04 17:17:59 -07001799 logging.info("Iteration " + str(idx + 1))
Dan Talayco8a64e332012-03-28 14:53:20 -07001800 for cls in iter_classes:
1801 test = cls()
1802 test.inheritSetup(self)
1803 test.runTest()
1804 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001805 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001806 if time.time() - last > 60:
1807 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001808 logging.info(
Dan Talaycofa6454f2012-04-05 10:04:13 -07001809 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1810 (idx, count, tests_done, last - start) +
1811 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001812 stats = all_stats_get(self)
1813 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001814 logging.info("\nIterCases ran %d tests in %d seconds." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001815 (tests_done, last - start))
Rich Lane9a003812012-10-04 17:17:59 -07001816 logging.info(" flows: %d. packets: %d. bytes: %d" %
Dan Talayco8a64e332012-03-28 14:53:20 -07001817 (stats["flows"], stats["packets"], stats["bytes"]))
Rich Lane9a003812012-10-04 17:17:59 -07001818 logging.info(" active: %d. lookups: %d. matched %d." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001819 (stats["active"], stats["lookups"], stats["matched"]))
1820
Dan Talayco4b2bee62010-07-20 14:10:05 -07001821#@todo Need to implement tagged versions of the above tests
1822#
1823#@todo Implement a test case that strips tag 2, adds tag 3
1824# and modifies tag 4 to tag 5. Then verify (in addition) that
1825# tag 6 does not get modified.
1826
1827class MixedVLAN(BaseMatchCase):
1828 """
1829 Test mixture of VLAN tag actions
1830
1831 Strip tag 2 on port 1, send to port 2
1832 Add tag 3 on port 1, send to port 2
1833 Modify tag 4 to 5 on port 1, send to port 2
1834 All other traffic from port 1, send to port 3
1835 All traffic from port 2 sent to port 4
1836 Use exact matches with different packets for all mods
1837 Verify the following: (port, vid)
1838 (port 1, vid 2) => VLAN tag stripped, out port 2
1839 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1840 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1841 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1842 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1843 (port 2, no tag) => untagged packet out port 4
1844 (port 2, vid 2-6) => unmodified packet out port 4
1845
1846 Variation: Might try sending VID 5 to port 3 and check.
1847 If only VID 5 distinguishes pkt, this will fail on some platforms
1848 """
1849
Rich Laned1d9c282012-10-04 22:07:10 -07001850 priority = -1
Rich Lane8d6ab272012-09-23 18:06:20 -07001851
1852class MatchEach(basic.SimpleDataPlane):
1853 """
1854 Check that each match field is actually matched on.
1855 Installs two flows that differ in one field. The flow that should not
1856 match has a higher priority, so if that field is ignored during matching
1857 the packet will be sent out the wrong port.
1858
1859 TODO test UDP, ARP, ICMP, etc.
1860 """
1861 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001862 of_ports = config["port_map"].keys()
Rich Lane8d6ab272012-09-23 18:06:20 -07001863 of_ports.sort()
1864 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1865
Rich Lane9a003812012-10-04 17:17:59 -07001866 delete_all_flows(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001867
1868 pkt = simple_tcp_packet()
1869 ingress_port = of_ports[0]
1870 egress_port = of_ports[1]
1871
1872 def testField(field, mask):
Rich Lane9a003812012-10-04 17:17:59 -07001873 logging.info("Testing field %s" % field)
Rich Lane8d6ab272012-09-23 18:06:20 -07001874
1875 def addFlow(matching, priority, output_port):
1876 match = packet_to_flow_match(self, pkt)
1877 self.assertTrue(match is not None, "Could not generate flow match from pkt")
1878 match.wildcards &= ~ofp.OFPFW_IN_PORT
1879 match.in_port = ingress_port
1880 if not matching:
1881 # Make sure flow doesn't match
1882 orig = getattr(match, field)
1883 if isinstance(orig, list):
1884 new = map(lambda a: ~a[0] & a[1], zip(orig, mask))
1885 else:
1886 new = ~orig & mask
1887 setattr(match, field, new)
1888 request = message.flow_mod()
1889 request.match = match
1890 request.buffer_id = 0xffffffff
1891 request.priority = priority
1892 act = action.action_output()
1893 act.port = output_port
1894 self.assertTrue(request.actions.add(act), "Could not add action")
Rich Lane9a003812012-10-04 17:17:59 -07001895 logging.info("Inserting flow")
Rich Lane8d6ab272012-09-23 18:06:20 -07001896 self.controller.message_send(request)
1897
1898 # This flow should match.
1899 addFlow(matching=True, priority=0, output_port=egress_port)
1900 # This flow should not match, but it has a higher priority.
1901 addFlow(matching=False, priority=1, output_port=ofp.OFPP_IN_PORT)
1902
1903 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
1904
Rich Lane9a003812012-10-04 17:17:59 -07001905 logging.info("Sending packet to dp port " + str(ingress_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001906 self.dataplane.send(ingress_port, str(pkt))
1907
1908 exp_pkt_arg = None
1909 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -07001910 if config["relax"]:
Rich Lane8d6ab272012-09-23 18:06:20 -07001911 exp_pkt_arg = pkt
1912 exp_port = egress_port
1913
1914 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
1915 exp_pkt=exp_pkt_arg)
1916 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -07001917 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001918 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
1919 self.assertEqual(str(pkt), str(rcv_pkt), 'Response packet does not match send packet')
1920
1921 # TODO in_port
1922 testField("dl_src", [0xff]*6)
1923 testField("dl_dst", [0xff]*6)
1924 testField("dl_type", 0xffff)
1925 testField("dl_vlan", 0xfff)
1926 # TODO dl_vlan_pcp
1927 testField("nw_src", 0xffffffff)
1928 testField("nw_dst", 0xffffffff)
1929 testField("nw_tos", 0x3f)
1930 testField("nw_proto", 0xff)
1931 testField("tp_src", 0xffff)
1932 testField("tp_dst", 0xffff)
1933
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001934if __name__ == "__main__":
1935 print "Please run through oft script: ./oft --test_spec=basic"