blob: 67aa9bbfd8fddf50897c5c7c3857cabfa7dbe870 [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
Dan Talayco5eba8442010-03-10 13:58:43 -080016import logging
Rich Laneb90a1c42012-10-05 09:16:05 -070017import time
Dan Talayco5eba8442010-03-10 13:58:43 -080018import unittest
Christian Dickmann8b59b4b2012-09-23 16:48:30 -070019import random
Dan Talayco5eba8442010-03-10 13:58:43 -080020
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
Rich Laneb90a1c42012-10-05 09:16:05 -070028import oftest.base_tests as base_tests
29import basic # for IterCases
Dan Talayco5eba8442010-03-10 13:58:43 -080030
Christian Dickmann8b59b4b2012-09-23 16:48:30 -070031from oftest.parse import parse_mac, parse_ip
32
Rich Laneda3b5ad2012-10-03 09:05:32 -070033from oftest.testutils import *
Dan Talayco5eba8442010-03-10 13:58:43 -080034
Dan Talayco551befa2010-07-15 17:05:32 -070035WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
Dan Talayco488fbc52012-04-09 16:30:41 -070036 ofp.OFPFW_DL_VLAN | ofp.OFPFW_DL_VLAN_PCP,
Dan Talayco551befa2010-07-15 17:05:32 -070037 ofp.OFPFW_DL_SRC,
38 ofp.OFPFW_DL_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070039 (ofp.OFPFW_DL_TYPE | ofp.OFPFW_NW_SRC_ALL |
40 ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS | ofp.OFPFW_NW_PROTO |
41 ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
42 (ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
Dan Talayco551befa2010-07-15 17:05:32 -070043 ofp.OFPFW_TP_SRC,
44 ofp.OFPFW_TP_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070045 ofp.OFPFW_NW_SRC_MASK,
46 ofp.OFPFW_NW_DST_MASK,
Dan Talayco551befa2010-07-15 17:05:32 -070047 ofp.OFPFW_DL_VLAN_PCP,
48 ofp.OFPFW_NW_TOS]
49
Dan Talayco488fbc52012-04-09 16:30:41 -070050NO_WILDCARD_VALUES = [(ofp.OFPFW_ALL ^ ofp.OFPFW_IN_PORT),
51 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN),
52 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_SRC),
53 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_DST),
54 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE),
55 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO),
56 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
57 ofp.OFPFW_TP_SRC),
58 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
59 ofp.OFPFW_TP_DST),
60 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
61 ofp.OFPFW_NW_SRC_MASK),
62 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
63 ofp.OFPFW_NW_DST_MASK),
64 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN ^ ofp.OFPFW_DL_VLAN_PCP),
65 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
66 ofp.OFPFW_NW_TOS)]
67
Dan Talayco551befa2010-07-15 17:05:32 -070068MODIFY_ACTION_VALUES = [ofp.OFPAT_SET_VLAN_VID,
69 ofp.OFPAT_SET_VLAN_PCP,
70 ofp.OFPAT_STRIP_VLAN,
71 ofp.OFPAT_SET_DL_SRC,
72 ofp.OFPAT_SET_DL_DST,
73 ofp.OFPAT_SET_NW_SRC,
74 ofp.OFPAT_SET_NW_DST,
75 ofp.OFPAT_SET_NW_TOS,
76 ofp.OFPAT_SET_TP_SRC,
77 ofp.OFPAT_SET_TP_DST]
78
Dan Talayco21381562010-07-17 00:34:47 -070079TEST_VID_DEFAULT = 2
80
Rich Laneb90a1c42012-10-05 09:16:05 -070081class DirectPacket(base_tests.SimpleDataPlane):
Dan Talayco5eba8442010-03-10 13:58:43 -080082 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -070083 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -080084
85 Generate a packet
86 Generate and install a matching flow
87 Add action to direct the packet to an egress port
88 Send the packet to ingress dataplane port
89 Verify the packet is received at the egress port only
90 """
91 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -070092 self.handleFlow()
93
94 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -070095 of_ports = config["port_map"].keys()
Dan Talayco5eba8442010-03-10 13:58:43 -080096 of_ports.sort()
97 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
98
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -070099 if (pkttype == 'ICMP'):
100 pkt = simple_icmp_packet()
101 else:
102 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700103 match = packet_to_flow_match(self, pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700104 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800105 self.assertTrue(match is not None,
106 "Could not generate flow match from pkt")
107 act = action.action_output()
108
109 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700110 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700111 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700112
Dan Talayco5eba8442010-03-10 13:58:43 -0800113 ingress_port = of_ports[idx]
114 egress_port = of_ports[(idx + 1) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700115 logging.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700116 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800117
118 match.in_port = ingress_port
119
120 request = message.flow_mod()
121 request.match = match
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700122
Dan Talayco5eba8442010-03-10 13:58:43 -0800123 request.buffer_id = 0xffffffff
124 act.port = egress_port
125 self.assertTrue(request.actions.add(act), "Could not add action")
126
Rich Lane9a003812012-10-04 17:17:59 -0700127 logging.info("Inserting flow")
Dan Talayco5eba8442010-03-10 13:58:43 -0800128 rv = self.controller.message_send(request)
129 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700130 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco5eba8442010-03-10 13:58:43 -0800131
Rich Lane9a003812012-10-04 17:17:59 -0700132 logging.info("Sending packet to dp port " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800133 str(ingress_port))
134 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700135
136 exp_pkt_arg = None
137 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700138 if config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700139 exp_pkt_arg = pkt
140 exp_port = egress_port
141
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700142 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700143 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800144 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700145 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800146 str(rcv_port))
147 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
148 self.assertEqual(str(pkt), str(rcv_pkt),
149 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700150
Rich Laneb90a1c42012-10-05 09:16:05 -0700151class DirectPacketController(base_tests.SimpleDataPlane):
Rich Lane51c23b32012-07-27 16:37:25 -0700152 """
153 Send packet to the controller port
154
155 Generate a packet
156 Generate and install a matching flow
157 Add action to direct the packet to the controller port
158 Send the packet to ingress dataplane port
159 Verify the packet is received at the controller port
160 """
161 def runTest(self):
162 self.handleFlow()
163
164 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700165 of_ports = config["port_map"].keys()
Rich Lane51c23b32012-07-27 16:37:25 -0700166 of_ports.sort()
167 self.assertTrue(len(of_ports) > 0, "Not enough ports for test")
168
169 if (pkttype == 'ICMP'):
170 pkt = simple_icmp_packet()
171 else:
172 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700173 match = packet_to_flow_match(self, pkt)
Rich Lane51c23b32012-07-27 16:37:25 -0700174 match.wildcards &= ~ofp.OFPFW_IN_PORT
175 self.assertTrue(match is not None,
176 "Could not generate flow match from pkt")
177 act = action.action_output()
178
Rich Lane9a003812012-10-04 17:17:59 -0700179 rv = delete_all_flows(self.controller)
Rich Lane51c23b32012-07-27 16:37:25 -0700180 self.assertEqual(rv, 0, "Failed to delete all flows")
181
182 ingress_port = of_ports[0]
183 match.in_port = ingress_port
184
185 request = message.flow_mod()
186 request.match = match
187
188 request.buffer_id = 0xffffffff
189 act.port = ofp.OFPP_CONTROLLER
190 act.max_len = 65535
191 self.assertTrue(request.actions.add(act), "Could not add action")
192
Rich Lane9a003812012-10-04 17:17:59 -0700193 logging.info("Inserting flow")
Rich Lane51c23b32012-07-27 16:37:25 -0700194 rv = self.controller.message_send(request)
195 self.assertTrue(rv != -1, "Error installing flow mod")
196 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
197
Rich Lane9a003812012-10-04 17:17:59 -0700198 logging.info("Sending packet to dp port " +
Rich Lane51c23b32012-07-27 16:37:25 -0700199 str(ingress_port))
200 self.dataplane.send(ingress_port, str(pkt))
201
202 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
203
204 self.assertTrue(response is not None,
205 'Packet in message not received by controller')
206 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700207 logging.debug("Sent %s" % format_packet(pkt))
208 logging.debug("Resp %s" % format_packet(response.data))
Rich Lane51c23b32012-07-27 16:37:25 -0700209 self.assertTrue(False,
210 'Response packet does not match send packet' +
211 ' for controller port')
212
Howard Pershf97840f2012-04-10 16:30:42 -0700213
Rich Laneb90a1c42012-10-05 09:16:05 -0700214class DirectPacketQueue(base_tests.SimpleDataPlane):
Howard Pershf97840f2012-04-10 16:30:42 -0700215 """
216 Send packet to single queue on single egress port
217
218 Generate a packet
219 Generate and install a matching flow
220 Add action to direct the packet to an egress port and queue
221 Send the packet to ingress dataplane port
222 Verify the packet is received at the egress port only
223 """
224 def runTest(self):
225 self.handleFlow()
226
Howard Persh670b5672012-04-13 09:08:29 -0700227 def portQueuesGet(self, queue_stats, port_num):
228 result = []
229 for qs in queue_stats.stats:
230 if qs.port_no != port_num:
231 continue
232 result.append(qs.queue_id)
233 return result
234
Howard Pershf97840f2012-04-10 16:30:42 -0700235 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700236 of_ports = config["port_map"].keys()
Howard Pershf97840f2012-04-10 16:30:42 -0700237 of_ports.sort()
238 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
239
240 if (pkttype == 'ICMP'):
241 pkt = simple_icmp_packet()
242 else:
243 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700244 match = packet_to_flow_match(self, pkt)
Howard Pershf97840f2012-04-10 16:30:42 -0700245 match.wildcards &= ~ofp.OFPFW_IN_PORT
246 self.assertTrue(match is not None,
247 "Could not generate flow match from pkt")
248
Howard Persh670b5672012-04-13 09:08:29 -0700249 # Get queue stats from switch
250
251 request = message.queue_stats_request()
252 request.port_no = ofp.OFPP_ALL
253 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700254 (queue_stats, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700255 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
256
257 act = action.action_enqueue()
Howard Pershf97840f2012-04-10 16:30:42 -0700258
259 for idx in range(len(of_ports)):
Howard Pershf97840f2012-04-10 16:30:42 -0700260 ingress_port = of_ports[idx]
261 egress_port = of_ports[(idx + 1) % len(of_ports)]
Howard Pershf97840f2012-04-10 16:30:42 -0700262
Howard Persh670b5672012-04-13 09:08:29 -0700263 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700264 logging.info("Ingress " + str(ingress_port)
Howard Persh670b5672012-04-13 09:08:29 -0700265 + " to egress " + str(egress_port)
266 + " queue " + str(egress_queue_id)
267 )
Howard Pershf97840f2012-04-10 16:30:42 -0700268
Rich Lane9a003812012-10-04 17:17:59 -0700269 rv = delete_all_flows(self.controller)
Howard Persh670b5672012-04-13 09:08:29 -0700270 self.assertEqual(rv, 0, "Failed to delete all flows")
Howard Pershf97840f2012-04-10 16:30:42 -0700271
Howard Persh670b5672012-04-13 09:08:29 -0700272 match.in_port = ingress_port
273
274 request = message.flow_mod()
275 request.match = match
Howard Pershf97840f2012-04-10 16:30:42 -0700276
Howard Persh670b5672012-04-13 09:08:29 -0700277 request.buffer_id = 0xffffffff
278 act.port = egress_port
279 act.queue_id = egress_queue_id
280 self.assertTrue(request.actions.add(act), "Could not add action")
Howard Pershf97840f2012-04-10 16:30:42 -0700281
Rich Lane9a003812012-10-04 17:17:59 -0700282 logging.info("Inserting flow")
Howard Persh670b5672012-04-13 09:08:29 -0700283 rv = self.controller.message_send(request)
284 self.assertTrue(rv != -1, "Error installing flow mod")
285 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Howard Pershf97840f2012-04-10 16:30:42 -0700286
Howard Persh670b5672012-04-13 09:08:29 -0700287 # Get current stats for selected egress queue
Howard Pershf97840f2012-04-10 16:30:42 -0700288
Howard Persh670b5672012-04-13 09:08:29 -0700289 request = message.queue_stats_request()
290 request.port_no = egress_port
291 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700292 (qs_before, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700293 self.assertNotEqual(qs_before, None, "Queue stats request failed")
294
Rich Lane9a003812012-10-04 17:17:59 -0700295 logging.info("Sending packet to dp port " +
Howard Persh670b5672012-04-13 09:08:29 -0700296 str(ingress_port))
297 self.dataplane.send(ingress_port, str(pkt))
298
299 exp_pkt_arg = None
300 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700301 if config["relax"]:
Howard Persh670b5672012-04-13 09:08:29 -0700302 exp_pkt_arg = pkt
303 exp_port = egress_port
304
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700305 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Howard Persh670b5672012-04-13 09:08:29 -0700306 exp_pkt=exp_pkt_arg)
307 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700308 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Howard Persh670b5672012-04-13 09:08:29 -0700309 str(rcv_port))
310 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
311 self.assertEqual(str(pkt), str(rcv_pkt),
312 'Response packet does not match send packet')
313
Ed Swierkb8a86512012-04-18 18:45:58 -0700314 # FIXME: instead of sleeping, keep requesting queue stats until
315 # the expected queue counter increases or some large timeout is
316 # reached
317 time.sleep(2)
318
Howard Persh670b5672012-04-13 09:08:29 -0700319 # Get current stats for selected egress queue again
320
321 request = message.queue_stats_request()
322 request.port_no = egress_port
323 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700324 (qs_after, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700325 self.assertNotEqual(qs_after, None, "Queue stats request failed")
326
327 # Make sure that tx packet counter for selected egress queue was
328 # incremented
329
Ed Swierk22f59152012-04-17 16:36:47 -0700330 self.assertEqual(qs_after.stats[0].tx_packets, \
331 qs_before.stats[0].tx_packets + 1, \
Howard Persh670b5672012-04-13 09:08:29 -0700332 "Verification of egress queue tx packet count failed"
333 )
334
335
Rich Laneb90a1c42012-10-05 09:16:05 -0700336class DirectPacketControllerQueue(base_tests.SimpleDataPlane):
Ken Chiang899ff8e2012-05-23 18:26:12 -0700337 """
338 Send a packet from each of the openflow ports
339 to each of the queues configured on the controller port.
340 If no queues have been configured, no packets are sent.
Howard Pershf97840f2012-04-10 16:30:42 -0700341
Ken Chiang899ff8e2012-05-23 18:26:12 -0700342 Generate a packet
343 Generate and install a matching flow
344 Add action to direct the packet to one of the controller port queues
345 Send the packet to ingress dataplane port
346 Verify the packet is received on the controller port queue
347 """
348 def runTest(self):
349 self.handleFlow()
350
351 def portQueuesGet(self, queue_stats, port_num):
352 result = []
353 for qs in queue_stats.stats:
354 if qs.port_no != port_num:
355 continue
356 result.append(qs.queue_id)
357 return result
358
359 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700360 of_ports = config["port_map"].keys()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700361 of_ports.sort()
362 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
363
364 if (pkttype == 'ICMP'):
365 pkt = simple_icmp_packet()
366 else:
367 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700368 match = packet_to_flow_match(self, pkt)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700369 match.wildcards &= ~ofp.OFPFW_IN_PORT
370 self.assertTrue(match is not None,
371 "Could not generate flow match from pkt")
372
373 # Get queue stats from switch
374
375 request = message.queue_stats_request()
376 request.port_no = ofp.OFPP_CONTROLLER
377 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700378 (queue_stats, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700379 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
380
381 act = action.action_enqueue()
382
383 for idx in range(len(of_ports)):
384 ingress_port = of_ports[idx]
385 egress_port = ofp.OFPP_CONTROLLER
386
Rich Lane9a003812012-10-04 17:17:59 -0700387 logging.info("Ingress port " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700388 + ", controller port queues "
389 + str(self.portQueuesGet(queue_stats, egress_port)))
390
391 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700392 logging.info("Ingress " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700393 + " to egress " + str(egress_port)
394 + " queue " + str(egress_queue_id)
395 )
396
Rich Lane9a003812012-10-04 17:17:59 -0700397 rv = delete_all_flows(self.controller)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700398 self.assertEqual(rv, 0, "Failed to delete all flows")
399
400 match.in_port = ingress_port
401
402 request = message.flow_mod()
403 request.match = match
404
405 request.buffer_id = 0xffffffff
406 act.port = egress_port
407 act.queue_id = egress_queue_id
408 self.assertTrue(request.actions.add(act), "Could not add action")
409
Rich Lane9a003812012-10-04 17:17:59 -0700410 logging.info("Inserting flow")
Ken Chiang899ff8e2012-05-23 18:26:12 -0700411 rv = self.controller.message_send(request)
412 self.assertTrue(rv != -1, "Error installing flow mod")
413 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
414
415 # Get current stats for selected egress queue
416
417 request = message.queue_stats_request()
418 request.port_no = egress_port
419 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700420 (qs_before, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700421 self.assertNotEqual(qs_before, None, "Queue stats request failed")
422
Rich Lane9a003812012-10-04 17:17:59 -0700423 logging.info("Sending packet to dp port " +
Ken Chiang899ff8e2012-05-23 18:26:12 -0700424 str(ingress_port))
425 self.dataplane.send(ingress_port, str(pkt))
426
427 exp_pkt_arg = None
428 exp_port = None
429
Rich Lanee5779d32012-10-05 17:56:04 -0700430 count = 0
Ken Chiang899ff8e2012-05-23 18:26:12 -0700431 while True:
Dan Talaycoc689a792012-09-28 14:22:53 -0700432 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700433 if not response: # Timeout
434 break
435 if dataplane.match_exp_pkt(pkt, response.data): # Got match
436 break
Rich Lane477f4812012-10-04 22:49:00 -0700437 if not config["relax"]: # Only one attempt to match
Ken Chiang899ff8e2012-05-23 18:26:12 -0700438 break
439 count += 1
440 if count > 10: # Too many tries
441 break
442
443 self.assertTrue(response is not None,
444 'Packet in message not received by controller')
445 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700446 logging.debug("Sent %s" % format_packet(pkt))
447 logging.debug("Resp %s" % format_packet(response.data))
Ken Chiang899ff8e2012-05-23 18:26:12 -0700448 self.assertTrue(False,
449 'Response packet does not match send packet' +
450 ' for controller port')
451
452 # FIXME: instead of sleeping, keep requesting queue stats until
453 # the expected queue counter increases or some large timeout is
454 # reached
455 time.sleep(2)
456
457 # Get current stats for selected egress queue again
458
459 request = message.queue_stats_request()
460 request.port_no = egress_port
461 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700462 (qs_after, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700463 self.assertNotEqual(qs_after, None, "Queue stats request failed")
464
465 # Make sure that tx packet counter for selected egress queue was
466 # incremented
467
468 self.assertEqual(qs_after.stats[0].tx_packets, \
469 qs_before.stats[0].tx_packets + 1, \
470 "Verification of egress queue tx packet count failed"
471 )
472
Howard Pershf97840f2012-04-10 16:30:42 -0700473
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700474class DirectPacketICMP(DirectPacket):
475 """
476 Send ICMP packet to single egress port
477
478 Generate a ICMP packet
479 Generate and install a matching flow
480 Add action to direct the packet to an egress port
481 Send the packet to ingress dataplane port
482 Verify the packet is received at the egress port only
483 Difference from DirectPacket test is that sent packet is ICMP
484 """
485 def runTest(self):
486 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700487
Rich Laneb90a1c42012-10-05 09:16:05 -0700488class DirectTwoPorts(base_tests.SimpleDataPlane):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700489 """
490 Send packet to two egress ports
491
492 Generate a packet
493 Generate and install a matching flow
494 Add action to direct the packet to two egress ports
495 Send the packet to ingress dataplane port
496 Verify the packet is received at the two egress ports
497 """
498 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700499 of_ports = config["port_map"].keys()
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700500 of_ports.sort()
501 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
502
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700503 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700504 match = packet_to_flow_match(self, pkt)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700505 match.wildcards &= ~ofp.OFPFW_IN_PORT
506 self.assertTrue(match is not None,
507 "Could not generate flow match from pkt")
508 act = action.action_output()
509
510 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700511 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700512 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700513
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700514 ingress_port = of_ports[idx]
515 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
516 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700517 logging.info("Ingress " + str(ingress_port) +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700518 " to egress " + str(egress_port1) + " and " +
519 str(egress_port2))
520
521 match.in_port = ingress_port
522
523 request = message.flow_mod()
524 request.match = match
525 request.buffer_id = 0xffffffff
526 act.port = egress_port1
527 self.assertTrue(request.actions.add(act), "Could not add action1")
528 act.port = egress_port2
529 self.assertTrue(request.actions.add(act), "Could not add action2")
Rich Lane9a003812012-10-04 17:17:59 -0700530 # logging.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700531
Rich Lane9a003812012-10-04 17:17:59 -0700532 logging.info("Inserting flow")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700533 rv = self.controller.message_send(request)
534 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700535 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700536
Rich Lane9a003812012-10-04 17:17:59 -0700537 logging.info("Sending packet to dp port " +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700538 str(ingress_port))
539 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700540 yes_ports = set([egress_port1, egress_port2])
541 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700542
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700543 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Rich Lane2014f9b2012-10-05 15:29:40 -0700544 self)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700545
Rich Laneb90a1c42012-10-05 09:16:05 -0700546class DirectMCNonIngress(base_tests.SimpleDataPlane):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700547 """
548 Multicast to all non-ingress ports
549
550 Generate a packet
551 Generate and install a matching flow
552 Add action to direct the packet to all non-ingress ports
553 Send the packet to ingress dataplane port
554 Verify the packet is received at all non-ingress ports
555
556 Does not use the flood action
557 """
558 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700559 of_ports = config["port_map"].keys()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700560 of_ports.sort()
561 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
562
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700563 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700564 match = packet_to_flow_match(self, pkt)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700565 match.wildcards &= ~ofp.OFPFW_IN_PORT
566 self.assertTrue(match is not None,
567 "Could not generate flow match from pkt")
568 act = action.action_output()
569
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700570 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700571 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700572 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700573
Rich Lane9a003812012-10-04 17:17:59 -0700574 logging.info("Ingress " + str(ingress_port) +
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700575 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700576 match.in_port = ingress_port
577
578 request = message.flow_mod()
579 request.match = match
580 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700581 for egress_port in of_ports:
582 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700583 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700584 act.port = egress_port
585 self.assertTrue(request.actions.add(act),
586 "Could not add output to " + str(egress_port))
Rich Lane9a003812012-10-04 17:17:59 -0700587 logging.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700588
Rich Lane9a003812012-10-04 17:17:59 -0700589 logging.info("Inserting flow")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700590 rv = self.controller.message_send(request)
591 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700592 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700593
Rich Lane9a003812012-10-04 17:17:59 -0700594 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700595 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700596 yes_ports = set(of_ports).difference([ingress_port])
597 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700598 self)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700599
Dan Talayco32fa6542010-05-11 15:54:08 -0700600
Rich Laneb90a1c42012-10-05 09:16:05 -0700601class DirectMC(base_tests.SimpleDataPlane):
Dan Talayco32fa6542010-05-11 15:54:08 -0700602 """
603 Multicast to all ports including ingress
604
605 Generate a packet
606 Generate and install a matching flow
607 Add action to direct the packet to all non-ingress ports
608 Send the packet to ingress dataplane port
609 Verify the packet is received at all ports
610
611 Does not use the flood action
612 """
613 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700614 of_ports = config["port_map"].keys()
Dan Talayco32fa6542010-05-11 15:54:08 -0700615 of_ports.sort()
616 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
617
Dan Talayco32fa6542010-05-11 15:54:08 -0700618 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700619 match = packet_to_flow_match(self, pkt)
Dan Talayco32fa6542010-05-11 15:54:08 -0700620 match.wildcards &= ~ofp.OFPFW_IN_PORT
621 self.assertTrue(match is not None,
622 "Could not generate flow match from pkt")
623 act = action.action_output()
624
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700625 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700626 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700627 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700628
Rich Lane9a003812012-10-04 17:17:59 -0700629 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700630 match.in_port = ingress_port
631
632 request = message.flow_mod()
633 request.match = match
634 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700635 for egress_port in of_ports:
636 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700637 act.port = ofp.OFPP_IN_PORT
638 else:
639 act.port = egress_port
640 self.assertTrue(request.actions.add(act),
641 "Could not add output to " + str(egress_port))
Rich Lane9a003812012-10-04 17:17:59 -0700642 # logging.info(request.show())
Dan Talayco2e77a842010-05-12 15:39:46 -0700643
Rich Lane9a003812012-10-04 17:17:59 -0700644 logging.info("Inserting flow")
Dan Talayco2e77a842010-05-12 15:39:46 -0700645 rv = self.controller.message_send(request)
646 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700647 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2e77a842010-05-12 15:39:46 -0700648
Rich Lane9a003812012-10-04 17:17:59 -0700649 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700650 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700651 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco2e77a842010-05-12 15:39:46 -0700652
Rich Laneb90a1c42012-10-05 09:16:05 -0700653class Flood(base_tests.SimpleDataPlane):
Dan Talayco2e77a842010-05-12 15:39:46 -0700654 """
655 Flood to all ports except ingress
656
657 Generate a packet
658 Generate and install a matching flow
659 Add action to flood the packet
660 Send the packet to ingress dataplane port
661 Verify the packet is received at all other ports
662 """
663 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700664 of_ports = config["port_map"].keys()
Dan Talayco2e77a842010-05-12 15:39:46 -0700665 of_ports.sort()
666 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
667
668 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700669 match = packet_to_flow_match(self, pkt)
Dan Talayco2e77a842010-05-12 15:39:46 -0700670 match.wildcards &= ~ofp.OFPFW_IN_PORT
671 self.assertTrue(match is not None,
672 "Could not generate flow match from pkt")
673 act = action.action_output()
674
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700675 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700676 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700677 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700678
Rich Lane9a003812012-10-04 17:17:59 -0700679 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700680 match.in_port = ingress_port
681
682 request = message.flow_mod()
683 request.match = match
684 request.buffer_id = 0xffffffff
685 act.port = ofp.OFPP_FLOOD
686 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700687 "Could not add flood port action")
Rich Lane9a003812012-10-04 17:17:59 -0700688 logging.info(request.show())
Dan Talayco32fa6542010-05-11 15:54:08 -0700689
Rich Lane9a003812012-10-04 17:17:59 -0700690 logging.info("Inserting flow")
Dan Talayco32fa6542010-05-11 15:54:08 -0700691 rv = self.controller.message_send(request)
692 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700693 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco32fa6542010-05-11 15:54:08 -0700694
Rich Lane9a003812012-10-04 17:17:59 -0700695 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco32fa6542010-05-11 15:54:08 -0700696 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700697 yes_ports = set(of_ports).difference([ingress_port])
698 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700699 self)
Dan Talayco3be5b062010-05-12 15:46:21 -0700700
Rich Laneb90a1c42012-10-05 09:16:05 -0700701class FloodPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco3be5b062010-05-12 15:46:21 -0700702 """
703 Flood to all ports plus send to ingress port
704
705 Generate a packet
706 Generate and install a matching flow
707 Add action to flood the packet
708 Add action to send to ingress port
709 Send the packet to ingress dataplane port
710 Verify the packet is received at all other ports
711 """
712 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700713 of_ports = config["port_map"].keys()
Dan Talayco3be5b062010-05-12 15:46:21 -0700714 of_ports.sort()
715 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
716
717 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700718 match = packet_to_flow_match(self, pkt)
Dan Talayco3be5b062010-05-12 15:46:21 -0700719 match.wildcards &= ~ofp.OFPFW_IN_PORT
720 self.assertTrue(match is not None,
721 "Could not generate flow match from pkt")
722 act = action.action_output()
723
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700724 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700725 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700726 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700727
Rich Lane9a003812012-10-04 17:17:59 -0700728 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700729 match.in_port = ingress_port
730
731 request = message.flow_mod()
732 request.match = match
733 request.buffer_id = 0xffffffff
734 act.port = ofp.OFPP_FLOOD
735 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700736 "Could not add flood port action")
737 act.port = ofp.OFPP_IN_PORT
738 self.assertTrue(request.actions.add(act),
739 "Could not add ingress port for output")
Rich Lane9a003812012-10-04 17:17:59 -0700740 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700741
Rich Lane9a003812012-10-04 17:17:59 -0700742 logging.info("Inserting flow")
Dan Talayco4aa13122010-05-12 15:54:44 -0700743 rv = self.controller.message_send(request)
744 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700745 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700746
Rich Lane9a003812012-10-04 17:17:59 -0700747 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700748 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700749 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco4aa13122010-05-12 15:54:44 -0700750
Rich Laneb90a1c42012-10-05 09:16:05 -0700751class All(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700752 """
753 Send to OFPP_ALL port
754
755 Generate a packet
756 Generate and install a matching flow
757 Add action to forward to OFPP_ALL
758 Send the packet to ingress dataplane port
759 Verify the packet is received at all other ports
760 """
761 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700762 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700763 of_ports.sort()
764 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
765
766 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700767 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700768 match.wildcards &= ~ofp.OFPFW_IN_PORT
769 self.assertTrue(match is not None,
770 "Could not generate flow match from pkt")
771 act = action.action_output()
772
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700773 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700774 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700775 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700776
Rich Lane9a003812012-10-04 17:17:59 -0700777 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700778 match.in_port = ingress_port
779
780 request = message.flow_mod()
781 request.match = match
782 request.buffer_id = 0xffffffff
783 act.port = ofp.OFPP_ALL
784 self.assertTrue(request.actions.add(act),
785 "Could not add ALL port action")
Rich Lane9a003812012-10-04 17:17:59 -0700786 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700787
Rich Lane9a003812012-10-04 17:17:59 -0700788 logging.info("Inserting flow")
Dan Talayco4aa13122010-05-12 15:54:44 -0700789 rv = self.controller.message_send(request)
790 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700791 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700792
Rich Lane9a003812012-10-04 17:17:59 -0700793 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700794 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700795 yes_ports = set(of_ports).difference([ingress_port])
796 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700797 self)
Dan Talayco4aa13122010-05-12 15:54:44 -0700798
Rich Laneb90a1c42012-10-05 09:16:05 -0700799class AllPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700800 """
801 Send to OFPP_ALL port and ingress port
802
803 Generate a packet
804 Generate and install a matching flow
805 Add action to forward to OFPP_ALL
806 Add action to forward to ingress port
807 Send the packet to ingress dataplane port
808 Verify the packet is received at all other ports
809 """
810 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700811 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700812 of_ports.sort()
813 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
814
815 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700816 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700817 match.wildcards &= ~ofp.OFPFW_IN_PORT
818 self.assertTrue(match is not None,
819 "Could not generate flow match from pkt")
820 act = action.action_output()
821
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700822 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700823 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700824 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700825
Rich Lane9a003812012-10-04 17:17:59 -0700826 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700827 match.in_port = ingress_port
828
829 request = message.flow_mod()
830 request.match = match
831 request.buffer_id = 0xffffffff
832 act.port = ofp.OFPP_ALL
833 self.assertTrue(request.actions.add(act),
834 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700835 act.port = ofp.OFPP_IN_PORT
836 self.assertTrue(request.actions.add(act),
837 "Could not add ingress port for output")
Rich Lane9a003812012-10-04 17:17:59 -0700838 logging.info(request.show())
Dan Talayco3be5b062010-05-12 15:46:21 -0700839
Rich Lane9a003812012-10-04 17:17:59 -0700840 logging.info("Inserting flow")
Dan Talayco3be5b062010-05-12 15:46:21 -0700841 rv = self.controller.message_send(request)
842 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700843 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco3be5b062010-05-12 15:46:21 -0700844
Rich Lane9a003812012-10-04 17:17:59 -0700845 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco3be5b062010-05-12 15:46:21 -0700846 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700847 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700848
Rich Laneb90a1c42012-10-05 09:16:05 -0700849class FloodMinusPort(base_tests.SimpleDataPlane):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700850 """
851 Config port with No_Flood and test Flood action
852
853 Generate a packet
854 Generate a matching flow
855 Add action to forward to OFPP_ALL
856 Set port to no-flood
857 Send the packet to ingress dataplane port
858 Verify the packet is received at all other ports except
859 the ingress port and the no_flood port
860 """
861 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700862 of_ports = config["port_map"].keys()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700863 of_ports.sort()
864 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
865
866 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700867 match = packet_to_flow_match(self, pkt)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700868 match.wildcards &= ~ofp.OFPFW_IN_PORT
869 self.assertTrue(match is not None,
870 "Could not generate flow match from pkt")
871 act = action.action_output()
872
Rich Lane4b9e38c2012-12-06 16:33:20 -0800873 # Clear OFPPC_NO_FLOOD on each port
874 for of_port in of_ports:
875 rv = port_config_set(self.controller, of_port,
876 0, ofp.OFPPC_NO_FLOOD)
877 self.assertEqual(rv, 0, "Failed to set port config")
878
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700879 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700880 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700881 self.assertEqual(rv, 0, "Failed to delete all flows")
882
883 ingress_port = of_ports[idx]
884 no_flood_idx = (idx + 1) % len(of_ports)
885 no_flood_port = of_ports[no_flood_idx]
886 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700887 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700888 self.assertEqual(rv, 0, "Failed to set port config")
889
890 match.in_port = ingress_port
891
892 request = message.flow_mod()
893 request.match = match
894 request.buffer_id = 0xffffffff
895 act.port = ofp.OFPP_FLOOD
896 self.assertTrue(request.actions.add(act),
897 "Could not add flood port action")
Rich Lane9a003812012-10-04 17:17:59 -0700898 logging.info(request.show())
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700899
Rich Lane9a003812012-10-04 17:17:59 -0700900 logging.info("Inserting flow")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700901 rv = self.controller.message_send(request)
902 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700903 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700904
Rich Lane9a003812012-10-04 17:17:59 -0700905 logging.info("Sending packet to dp port " + str(ingress_port))
906 logging.info("No flood port is " + str(no_flood_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700907 self.dataplane.send(ingress_port, str(pkt))
908 no_ports = set([ingress_port, no_flood_port])
909 yes_ports = set(of_ports).difference(no_ports)
Rich Lane2014f9b2012-10-05 15:29:40 -0700910 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700911
912 # Turn no flood off again
913 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700914 0, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700915 self.assertEqual(rv, 0, "Failed to reset port config")
Rich Lane4ecc1f42012-12-06 16:35:24 -0800916 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
917
918 # Check that packets are now flooded to no_flood_port
919 logging.info("Sending packet to dp port " + str(ingress_port))
920 self.dataplane.send(ingress_port, str(pkt))
921 no_ports = set([ingress_port])
922 yes_ports = set(of_ports).difference(no_ports)
923 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700924
925 #@todo Should check no other packets received
926
Dan Talayco21381562010-07-17 00:34:47 -0700927
928
Dan Talayco551befa2010-07-15 17:05:32 -0700929################################################################
930
Rich Laneb90a1c42012-10-05 09:16:05 -0700931class BaseMatchCase(base_tests.SimpleDataPlane):
Dan Talayco551befa2010-07-15 17:05:32 -0700932 def setUp(self):
Rich Laneb90a1c42012-10-05 09:16:05 -0700933 base_tests.SimpleDataPlane.setUp(self)
Dan Talayco551befa2010-07-15 17:05:32 -0700934 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -0700935 logging.info("BaseMatchCase")
Dan Talayco551befa2010-07-15 17:05:32 -0700936
937class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700938 """
Dan Talayco551befa2010-07-15 17:05:32 -0700939 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700940
941 Generate a packet
942 Generate and install a matching flow without wildcard mask
943 Add action to forward to a port
944 Send the packet to the port
945 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700946 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700947
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700948 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700949 flow_match_test(self, config["port_map"])
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700950
Dan Talayco551befa2010-07-15 17:05:32 -0700951class ExactMatchTagged(BaseMatchCase):
952 """
953 Exact match for all port pairs with tagged pkts
954 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700955
Dan Talayco551befa2010-07-15 17:05:32 -0700956 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -0700957 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Lane477f4812012-10-04 22:49:00 -0700958 flow_match_test(self, config["port_map"], dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700959
Dan Talayco551befa2010-07-15 17:05:32 -0700960class ExactMatchTaggedMany(BaseMatchCase):
961 """
962 ExactMatchTagged with many VLANS
963 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700964
Rich Laned1d9c282012-10-04 22:07:10 -0700965 priority = -1
966
Dan Talayco551befa2010-07-15 17:05:32 -0700967 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700968 for vid in range(2,100,10):
Rich Lane477f4812012-10-04 22:49:00 -0700969 flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
Dan Talayco551befa2010-07-15 17:05:32 -0700970 for vid in range(100,4000,389):
Rich Lane477f4812012-10-04 22:49:00 -0700971 flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
972 flow_match_test(self, config["port_map"], dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700973
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700974class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700975 """
976 SingleWildcardMatchPriority
977 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700978
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700979 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700980 self.pkt = simple_tcp_packet()
981 self.flowMsgs = {}
982
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700983 def _ClearTable(self):
Rich Lane9a003812012-10-04 17:17:59 -0700984 rc = delete_all_flows(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700985 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700986 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700987
988 def runTest(self):
989
990 self._Init()
Rich Lane477f4812012-10-04 22:49:00 -0700991 of_ports = config["port_map"].keys()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700992 of_ports.sort()
993
994 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700995 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700996
997 # Run several combinations, each at lower priority settings.
998 # At the end of each call to runPrioFlows(), the table should
999 # be empty. If its not, we'll catch it as the priorities decreases
1000 portA = of_ports[0]
1001 portB = of_ports[1]
1002 portC = of_ports[2]
1003
1004 # TODO -- these priority numbers should be validated somehow?
1005 self.runPrioFlows(portA, portB, portC, 1000, 999)
1006 self.runPrioFlows(portB, portC, portA, 998, 997)
1007 self.runPrioFlows(portC, portA, portB, 996, 995)
1008 self.runPrioFlows(portA, portC, portB, 994, 993)
1009
1010
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001011
1012 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
1013 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001014
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001015 if clearTable:
1016 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001017
1018 # Sanity check flow at lower priority from pA to pB
Rich Lane9a003812012-10-04 17:17:59 -07001019 logging.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001020 % (portA, portB, portC, prioHigher, prioLower))
1021
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001022 # Sanity check flow at lower priority from pA to pC
1023 self.installFlow(prioLower, portA, portC)
1024 self.verifyFlow(portA, portC)
1025 self.removeFlow(prioLower)
1026
1027 # Install and verify pA->pB @ prioLower
1028 self.installFlow(prioLower, portA, portB)
1029 self.verifyFlow(portA, portB)
1030
1031 # Install and verify pA->pC @ prioHigher, should override pA->pB
1032 self.installFlow(prioHigher, portA, portC)
1033 self.verifyFlow(portA, portC)
1034 # remove pA->pC
1035 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001036 # Old flow pA -> pB @ prioLower should still be active
1037 self.verifyFlow(portA, portB)
1038 self.removeFlow(prioLower)
1039
1040 # Table should be empty at this point, leave it alone as
1041 # an assumption for future test runs
1042
1043
1044
Ed Swierk99a74de2012-08-22 06:40:54 -07001045 def installFlow(self, prio, inp, egp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001046 wildcards=ofp.OFPFW_DL_SRC):
Ed Swierk99a74de2012-08-22 06:40:54 -07001047 wildcards |= required_wildcards(self)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001048 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001049 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001050 egr_ports=egp)
1051 request.priority = prio
Rich Lane9a003812012-10-04 17:17:59 -07001052 logging.debug("Install flow with priority " + str(prio))
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001053 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001054 self.flowMsgs[prio] = request
1055
1056 def removeFlow(self, prio):
1057 if self.flowMsgs.has_key(prio):
1058 msg = self.flowMsgs[prio]
1059 msg.command = ofp.OFPFC_DELETE_STRICT
1060 # This *must* be set for DELETE
1061 msg.out_port = ofp.OFPP_NONE
Rich Lane9a003812012-10-04 17:17:59 -07001062 logging.debug("Remove flow with priority " + str(prio))
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001063 self.controller.message_send(msg)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001064 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001065 else:
1066 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001067
1068
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001069 def verifyFlow(self, inp, egp, pkt=None):
1070 if pkt == None:
1071 pkt = self.pkt
1072
Rich Lane9a003812012-10-04 17:17:59 -07001073 logging.info("Pkt match test: " + str(inp) + " to " + str(egp))
1074 logging.debug("Send packet: " + str(inp) + " to " + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001075 self.dataplane.send(inp, str(pkt))
1076 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001077
1078
1079
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001080class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
1081
1082 def runTest(self):
1083
1084 self._Init()
1085
Rich Lane477f4812012-10-04 22:49:00 -07001086 of_ports = config["port_map"].keys()
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001087 of_ports.sort()
1088
1089 # Install an entry from 0 -> 1 @ prio 1000
1090 self._ClearTable()
1091 self.installFlow(1000, of_ports[0], of_ports[1])
1092 self.verifyFlow(of_ports[0], of_ports[1])
1093 self.installFlow(1000, of_ports[1], of_ports[0])
1094 self.verifyFlow(of_ports[1], of_ports[0])
1095 self.installFlow(1001, of_ports[0], of_ports[1])
1096 self.verifyFlow(of_ports[0], of_ports[1])
1097 self.installFlow(1001, of_ports[1], of_ports[0])
1098 self.verifyFlow(of_ports[1], of_ports[0])
1099 self.removeFlow(1001)
1100 self.verifyFlow(of_ports[0], of_ports[1])
1101 self.removeFlow(1000)
1102
1103
1104
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001105class WildcardPriority(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001106 """
1107 1. Add wildcard flow, verify packet received.
1108 2. Add exact match flow with higher priority, verify packet received
1109 on port specified by this flow.
1110 3. Add wildcard flow with even higher priority, verify packet received
1111 on port specified by this flow.
Rich Laneb8392082012-11-21 15:52:54 -08001112 4. Add wildcard flow with lower priority, verify packet received
1113 on port specified by the highest priority flow.
Ken Chiang38d7a152012-05-24 15:33:50 -07001114 """
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001115
1116 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001117
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001118 self._Init()
1119
Rich Lane477f4812012-10-04 22:49:00 -07001120 of_ports = config["port_map"].keys()
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001121 of_ports.sort()
1122
1123 self._ClearTable()
Ken Chiang38d7a152012-05-24 15:33:50 -07001124
1125 # Install a flow with wildcards
1126 self.installFlow(999, of_ports[0], of_ports[1],
1127 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001128 self.verifyFlow(of_ports[0], of_ports[1])
Ken Chiang38d7a152012-05-24 15:33:50 -07001129 # Install a flow with no wildcards for our packet
1130 self.installFlow(1000, of_ports[0], of_ports[2], wildcards=0)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001131 self.verifyFlow(of_ports[0], of_ports[2])
Ken Chiang38d7a152012-05-24 15:33:50 -07001132 # Install a flow with wildcards for our packet with higher
1133 # priority
1134 self.installFlow(1001, of_ports[0], of_ports[3])
1135 self.verifyFlow(of_ports[0], of_ports[3])
Rich Laneb8392082012-11-21 15:52:54 -08001136 # Install a flow with wildcards for our packet with lower
1137 # priority
1138 self.installFlow(999, of_ports[0], of_ports[1],
1139 wildcards=ofp.OFPFW_DL_SRC)
1140 self.verifyFlow(of_ports[0], of_ports[3])
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001141
1142
Ken Chiang3978f242012-06-13 14:14:09 -07001143class WildcardPriorityWithDelete(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001144 """
1145 1. Add exact match flow, verify packet received.
1146 2. Add wildcard flow with higher priority, verify packet received on port
1147 specified by this flow.
1148 3. Add exact match flow with even higher priority, verify packet received
1149 on port specified by this flow.
1150 4. Delete lowest priority flow, verify packet received on port specified
1151 by highest priority flow.
1152 5. Delete highest priority flow, verify packet received on port specified
1153 by remaining flow.
1154 """
1155
1156 def runTest(self):
1157
1158 self._Init()
1159
Rich Lane477f4812012-10-04 22:49:00 -07001160 of_ports = config["port_map"].keys()
Ken Chiang38d7a152012-05-24 15:33:50 -07001161 of_ports.sort()
1162
1163 self._ClearTable()
1164
1165 # Install an exact match flow
1166 self.installFlow(250, of_ports[0], of_ports[1], wildcards=0)
1167 self.verifyFlow(of_ports[0], of_ports[1])
1168 # Install a flow with wildcards of higher priority
1169 self.installFlow(1250, of_ports[0], of_ports[2],
1170 wildcards=ofp.OFPFW_DL_DST)
1171 self.verifyFlow(of_ports[0], of_ports[2])
1172 # Install an exact match flow with even higher priority
1173 self.installFlow(2001, of_ports[0], of_ports[3], wildcards=0)
1174 self.verifyFlow(of_ports[0], of_ports[3])
1175 # Delete lowest priority flow
1176 self.removeFlow(250)
1177 self.verifyFlow(of_ports[0], of_ports[3])
1178 # Delete highest priority flow
1179 self.removeFlow(2001)
1180 self.verifyFlow(of_ports[0], of_ports[2])
1181
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001182
Dan Talayco551befa2010-07-15 17:05:32 -07001183class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001184 """
1185 Exercise wildcard matching for all ports
1186
1187 Generate a packet
1188 Generate and install a matching flow with wildcard mask
1189 Add action to forward to a port
1190 Send the packet to the port
1191 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001192 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001193 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001194 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001195 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001196 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001197 wc |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001198 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001199 # Set nonzero VLAN id to avoid sending priority-tagged packet
1200 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001201 else:
1202 dl_vlan = -1
Rich Lane477f4812012-10-04 22:49:00 -07001203 flow_match_test(self, config["port_map"], wildcards=wc,
Dan Talayco4431d542012-03-21 16:42:16 -07001204 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001205
Dan Talayco551befa2010-07-15 17:05:32 -07001206class SingleWildcardMatchTagged(BaseMatchCase):
1207 """
1208 SingleWildcardMatch with tagged packets
1209 """
1210 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001211 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001212 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001213 wc |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001214 flow_match_test(self, config["port_map"], wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -07001215 max_test=10)
1216
1217class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001218 """
Dan Talayco80b54ed2010-07-13 09:48:35 -07001219 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001220
1221 Generate a packet
1222 Generate and install a matching flow with wildcard all except one filed
1223 Add action to forward to a port
1224 Send the packet to the port
1225 Verify the packet is received at all other ports (one port at a time)
1226 Verify flow_expiration message is correct when command option is set
1227 """
1228 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001229 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001230 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001231 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001232 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001233 # Set nonzero VLAN id to avoid sending priority-tagged packet
1234 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001235 else:
1236 dl_vlan = -1
Rich Lane477f4812012-10-04 22:49:00 -07001237 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Dan Talayco4431d542012-03-21 16:42:16 -07001238 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001239
Dan Talayco551befa2010-07-15 17:05:32 -07001240class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1241 """
1242 Match one field with tagged packets
1243 """
1244 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001245 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001246 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001247 all_exp_one_wildcard |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001248 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Dan Talayco21381562010-07-17 00:34:47 -07001249 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001250
1251class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001252 """
1253 Create Wildcard-all flow and exercise for all ports
1254
1255 Generate a packet
1256 Generate and install a matching flow with wildcard-all
1257 Add action to forward to a port
1258 Send the packet to the port
1259 Verify the packet is received at all other ports (one port at a time)
1260 Verify flow_expiration message is correct when command option is set
1261 """
1262 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001263 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001264
Dan Talayco551befa2010-07-15 17:05:32 -07001265class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001266 """
Dan Talayco551befa2010-07-15 17:05:32 -07001267 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001268 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001269 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001270 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Lane477f4812012-10-04 22:49:00 -07001271 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL,
Dan Talayco21381562010-07-17 00:34:47 -07001272 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001273
Dan Talaycoba3745c2010-07-21 21:51:08 -07001274
Dan Talayco551befa2010-07-15 17:05:32 -07001275class AddVLANTag(BaseMatchCase):
1276 """
1277 Add a VLAN tag to an untagged packet
1278 """
1279 def runTest(self):
1280 new_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001281 sup_acts = self.supported_actions
Dan Talayco551befa2010-07-15 17:05:32 -07001282 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001283 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001284 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001285
Dan Talayco551befa2010-07-15 17:05:32 -07001286 len = 100
1287 len_w_vid = 104
1288 pkt = simple_tcp_packet(pktlen=len)
1289 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1290 dl_vlan=new_vid)
1291 vid_act = action.action_set_vlan_vid()
1292 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001293
Rich Lane477f4812012-10-04 22:49:00 -07001294 flow_match_test(self, config["port_map"], pkt=pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001295 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001296
Rich Laneb90a1c42012-10-05 09:16:05 -07001297class PacketOnly(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001298 """
1299 Just send a packet thru the switch
1300 """
Rich Laned1d9c282012-10-04 22:07:10 -07001301
1302 priority = -1
1303
Dan Talayco551befa2010-07-15 17:05:32 -07001304 def runTest(self):
1305 pkt = simple_tcp_packet()
Rich Lane477f4812012-10-04 22:49:00 -07001306 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001307 of_ports.sort()
1308 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001309 logging.info("Sending packet to " + str(ing_port))
1310 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001311 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001312
Rich Laneb90a1c42012-10-05 09:16:05 -07001313class PacketOnlyTagged(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001314 """
1315 Just send a packet thru the switch
1316 """
Rich Laned1d9c282012-10-04 22:07:10 -07001317
1318 priority = -1
1319
Dan Talayco551befa2010-07-15 17:05:32 -07001320 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001321 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001322 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
Rich Lane477f4812012-10-04 22:49:00 -07001323 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001324 of_ports.sort()
1325 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001326 logging.info("Sending packet to " + str(ing_port))
1327 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001328 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001329
Dan Talayco551befa2010-07-15 17:05:32 -07001330class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001331 """
1332 Modify the VLAN ID in the VLAN tag of a tagged packet
1333 """
Dan Talaycoaf669322012-09-12 22:51:22 -07001334 def setUp(self):
1335 BaseMatchCase.setUp(self)
1336 self.ing_port=False
1337
Dan Talayco551befa2010-07-15 17:05:32 -07001338 def runTest(self):
1339 old_vid = 2
1340 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001341 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001342 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001343 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001344 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001345
Dan Talayco551befa2010-07-15 17:05:32 -07001346 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1347 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
1348 vid_act = action.action_set_vlan_vid()
1349 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001350
Rich Lane477f4812012-10-04 22:49:00 -07001351 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoaf669322012-09-12 22:51:22 -07001352 action_list=[vid_act], ing_port=self.ing_port)
1353
1354class ModifyVIDToIngress(ModifyVID):
1355 """
1356 Modify the VLAN ID in the VLAN tag of a tagged packet and send to
1357 ingress port
1358 """
1359 def setUp(self):
1360 BaseMatchCase.setUp(self)
1361 self.ing_port=True
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001362
Ken Chiange9a211d2012-04-20 14:52:11 -07001363class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1364 """
1365 With vlan ID and priority wildcarded, perform SET_VLAN_VID action.
1366 The same flow should match on both untagged and tagged packets.
1367 """
1368 def runTest(self):
1369 old_vid = 2
1370 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001371 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001372 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1373 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1374 return
1375
Rich Lane477f4812012-10-04 22:49:00 -07001376 of_ports = config["port_map"].keys()
Ken Chiange9a211d2012-04-20 14:52:11 -07001377 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1378 ing_port = of_ports[0]
1379 egr_ports = of_ports[1]
1380
Rich Lane9a003812012-10-04 17:17:59 -07001381 rv = delete_all_flows(self.controller)
Ken Chiange9a211d2012-04-20 14:52:11 -07001382 self.assertEqual(rv, 0, "Failed to delete all flows")
1383
1384 len_untagged = 100
1385 len_w_vid = 104
1386 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1387 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
1388 dl_vlan_enable=True, dl_vlan=old_vid)
1389 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1390 dl_vlan=new_vid)
Ed Swierk99a74de2012-08-22 06:40:54 -07001391 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1392 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001393 vid_act = action.action_set_vlan_vid()
1394 vid_act.vlan_vid = new_vid
1395 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
1396 wildcards=wildcards, egr_ports=egr_ports,
1397 action_list=[vid_act])
1398 flow_msg_install(self, request)
1399
Rich Lane9a003812012-10-04 17:17:59 -07001400 logging.debug("Send untagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001401 str(egr_ports))
1402 self.dataplane.send(ing_port, str(untagged_pkt))
1403 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1404
Rich Lane9a003812012-10-04 17:17:59 -07001405 logging.debug("Send tagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001406 str(egr_ports))
1407 self.dataplane.send(ing_port, str(tagged_pkt))
1408 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1409
Howard Pershc1199d52012-04-11 14:21:32 -07001410class ModifyVlanPcp(BaseMatchCase):
1411 """
1412 Modify the priority field of the VLAN tag of a tagged packet
1413 """
1414 def runTest(self):
1415 vid = 123
1416 old_vlan_pcp = 2
1417 new_vlan_pcp = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001418 sup_acts = self.supported_actions
Ed Swierk8c3af7f2012-04-24 14:19:17 -07001419 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_PCP):
1420 skip_message_emit(self, "Modify VLAN priority test")
Howard Pershc1199d52012-04-11 14:21:32 -07001421 return
1422
1423 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1424 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1425 vid_act = action.action_set_vlan_pcp()
1426 vid_act.vlan_pcp = new_vlan_pcp
1427
Rich Lane477f4812012-10-04 22:49:00 -07001428 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Howard Pershc1199d52012-04-11 14:21:32 -07001429 action_list=[vid_act])
1430
Dan Talayco551befa2010-07-15 17:05:32 -07001431class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001432 """
1433 Strip the VLAN tag from a tagged packet
1434 """
Dan Talayco551befa2010-07-15 17:05:32 -07001435 def runTest(self):
1436 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001437 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001438 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001439 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001440 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001441
Dan Talayco551befa2010-07-15 17:05:32 -07001442 len_w_vid = 104
1443 len = 100
1444 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1445 dl_vlan=old_vid)
1446 exp_pkt = simple_tcp_packet(pktlen=len)
1447 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001448
Rich Lane477f4812012-10-04 22:49:00 -07001449 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001450 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001451
Ken Chiange9a211d2012-04-20 14:52:11 -07001452class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1453 """
1454 Strip the VLAN tag from a tagged packet.
1455 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1456 """
1457 def runTest(self):
1458 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001459 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001460 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1461 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1462 return
1463
1464 len_w_vid = 104
1465 len_untagged = 100
1466 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1467 dl_vlan=old_vid)
1468 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
Ed Swierk99a74de2012-08-22 06:40:54 -07001469 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1470 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001471 vid_act = action.action_strip_vlan()
1472
Rich Lane477f4812012-10-04 22:49:00 -07001473 flow_match_test(self, config["port_map"],
Ed Swierk99a74de2012-08-22 06:40:54 -07001474 wildcards=wildcards,
Ken Chiange9a211d2012-04-20 14:52:11 -07001475 pkt=pkt, exp_pkt=exp_pkt,
1476 action_list=[vid_act])
1477
Dan Talayco4b2bee62010-07-20 14:10:05 -07001478def init_pkt_args():
1479 """
1480 Pass back a dictionary with default packet arguments
1481 """
1482 args = {}
1483 args["dl_src"] = '00:23:45:67:89:AB'
1484
1485 dl_vlan_enable=False
1486 dl_vlan=-1
Rich Lane477f4812012-10-04 22:49:00 -07001487 if config["test-params"]["vid"]:
Dan Talayco4b2bee62010-07-20 14:10:05 -07001488 dl_vlan_enable=True
Rich Lane477f4812012-10-04 22:49:00 -07001489 dl_vlan = config["test-params"]["vid"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001490
1491# Unpack operator is ** on a dictionary
1492
1493 return args
1494
Dan Talayco551befa2010-07-15 17:05:32 -07001495class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001496 """
1497 Modify the source MAC address (TP1)
1498 """
Dan Talayco551befa2010-07-15 17:05:32 -07001499 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001500 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001501 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001502 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001503 return
1504
1505 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1506 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001507 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001508 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001509
Dan Talayco551befa2010-07-15 17:05:32 -07001510class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001511 """
1512 Modify the dest MAC address (TP1)
1513 """
Dan Talayco551befa2010-07-15 17:05:32 -07001514 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001515 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001516 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001517 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001518 return
1519
1520 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1521 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001522 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001523 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001524
Dan Talayco551befa2010-07-15 17:05:32 -07001525class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001526 """
1527 Modify the source IP address of an IP packet (TP1)
1528 """
Dan Talayco551befa2010-07-15 17:05:32 -07001529 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001530 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001531 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001532 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001533 return
1534
1535 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1536 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001537 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001538 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001539
Dan Talayco551befa2010-07-15 17:05:32 -07001540class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001541 """
1542 Modify the dest IP address of an IP packet (TP1)
1543 """
Dan Talayco551befa2010-07-15 17:05:32 -07001544 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001545 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001546 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001547 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001548 return
1549
1550 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1551 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001552 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001553 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001554
1555class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001556 """
1557 Modify the source TCP port of a TCP packet (TP1)
1558 """
Dan Talayco551befa2010-07-15 17:05:32 -07001559 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001560 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001561 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001562 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001563 return
1564
1565 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1566 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001567 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001568 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001569
Rich Lane01c2b862012-10-26 16:26:25 -07001570class ModifyL4SrcUdp(BaseMatchCase):
1571 """
1572 Modify the source UDP port of a UDP packet
1573 """
1574 def runTest(self):
1575 sup_acts = self.supported_actions
1576 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1577 skip_message_emit(self, "ModifyL4SrcUdp test")
1578 return
1579
1580 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_sport'],
1581 check_test_params=True, tp="udp")
1582 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1583 action_list=acts, max_test=2)
1584
Dan Talayco551befa2010-07-15 17:05:32 -07001585class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001586 """
1587 Modify the dest TCP port of a TCP packet (TP1)
1588 """
Dan Talayco551befa2010-07-15 17:05:32 -07001589 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001590 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001591 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001592 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001593 return
1594
1595 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1596 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001597 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001598 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001599
Rich Lane01c2b862012-10-26 16:26:25 -07001600class ModifyL4DstUdp(BaseMatchCase):
1601 """
1602 Modify the dest UDP port of a UDP packet
1603 """
1604 def runTest(self):
1605 sup_acts = self.supported_actions
1606 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1607 skip_message_emit(self, "ModifyL4DstUdp test")
1608 return
1609
1610 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_dport'],
1611 check_test_params=True, tp="udp")
1612 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1613 action_list=acts, max_test=2)
1614
Dan Talayco551befa2010-07-15 17:05:32 -07001615class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001616 """
1617 Modify the IP type of service of an IP packet (TP1)
1618 """
Dan Talayco551befa2010-07-15 17:05:32 -07001619 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001620 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001621 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001622 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001623 return
Dan Talayco551befa2010-07-15 17:05:32 -07001624
Dan Talayco4b2bee62010-07-20 14:10:05 -07001625 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1626 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001627 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001628 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001629
Dan Talaycof6e76c02012-03-23 10:56:12 -07001630class ModifyL2DstMC(BaseMatchCase):
1631 """
1632 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001633 """
1634 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001635 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001636 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001637 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001638 return
1639
Dan Talaycof6e76c02012-03-23 10:56:12 -07001640 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1641 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001642 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001643 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001644
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001645class ModifyL2DstIngress(BaseMatchCase):
1646 """
1647 Modify the L2 dest and send to the ingress port
1648 """
1649 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001650 sup_acts = self.supported_actions
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001651 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001652 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001653 return
1654
1655 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1656 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001657 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001658 action_list=acts, max_test=2, egr_count=0,
1659 ing_port=True)
1660
Dan Talaycod8ae7582012-03-23 12:24:56 -07001661class ModifyL2DstIngressMC(BaseMatchCase):
1662 """
1663 Modify the L2 dest and send to the ingress port
1664 """
1665 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001666 sup_acts = self.supported_actions
Dan Talaycod8ae7582012-03-23 12:24:56 -07001667 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1668 skip_message_emit(self, "ModifyL2dstMC test")
1669 return
1670
1671 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1672 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001673 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001674 action_list=acts, max_test=2, egr_count=-1,
1675 ing_port=True)
1676
Dan Talaycof6e76c02012-03-23 10:56:12 -07001677class ModifyL2SrcMC(BaseMatchCase):
1678 """
1679 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001680 """
1681 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001682 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001683 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001684 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001685 return
1686
Dan Talaycof6e76c02012-03-23 10:56:12 -07001687 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1688 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001689 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001690 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001691
1692class ModifyL2SrcDstMC(BaseMatchCase):
1693 """
1694 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001695 """
1696 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001697 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001698 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1699 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1700 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001701 return
1702
Dan Talaycof6e76c02012-03-23 10:56:12 -07001703 mod_fields = ['dl_dst', 'dl_src']
1704 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1705 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001706 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001707 action_list=acts, max_test=2, egr_count=-1)
1708
1709class ModifyL2DstVIDMC(BaseMatchCase):
1710 """
1711 Modify the L2 dest and send to 2 ports
1712 """
1713 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001714 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001715 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1716 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1717 skip_message_emit(self, "ModifyL2DstVIDMC test")
1718 return
1719
1720 mod_fields = ['dl_dst', 'dl_vlan']
1721 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1722 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1723 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001724 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001725 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001726
Rich Lane22e74c12012-11-12 15:06:06 -08001727class ModifyAll(BaseMatchCase):
1728 """
1729 Modify all supported fields and output to a port
1730 """
1731 def runTest(self):
1732 sup_acts = self.supported_actions
1733
1734 sup_map = {
1735 "dl_dst" : ofp.OFPAT_SET_DL_DST,
1736 "dl_src" : ofp.OFPAT_SET_DL_SRC,
1737 "dl_vlan_enable" : ofp.OFPAT_SET_VLAN_VID,
1738 "dl_vlan" : ofp.OFPAT_SET_VLAN_VID,
1739 "dl_vlan_pcp" : ofp.OFPAT_SET_VLAN_PCP,
1740 "ip_src" : ofp.OFPAT_SET_NW_SRC,
1741 "ip_dst" : ofp.OFPAT_SET_NW_DST,
1742 "ip_tos" : ofp.OFPAT_SET_NW_TOS,
1743 "tcp_sport" : ofp.OFPAT_SET_TP_SRC,
1744 "tcp_dport" : ofp.OFPAT_SET_TP_DST,
1745 }
1746
1747 mod_fields = [field for (field, bit) in sup_map.items() if (sup_acts & 1 << bit)]
1748 random.shuffle(mod_fields)
1749 start_field_vals = { "dl_vlan_enable" : True }
1750 mod_field_vals = { "dl_vlan_enable" : True }
1751 logging.info("modifying fields: %s" % repr(mod_fields))
1752
1753 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1754 mod_fields=mod_fields,
1755 start_field_vals=start_field_vals,
1756 mod_field_vals=mod_field_vals,
1757 check_test_params=True)
1758 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1759 action_list=acts, max_test=2)
1760
Dan Talaycofa6454f2012-04-05 10:04:13 -07001761class FlowToggle(BaseMatchCase):
1762 """
1763 Add flows to the table and modify them repeatedly
Dan Talaycof7c41312012-07-23 12:53:19 -07001764
1765 This is done by using only "add" flow messages. Since the check overlap
1766 flag is not set, the switch is supposed to modify the existing flow if
1767 the match already exists.
1768
1769 Would probably be better to exercise more of the flow modify commands
1770 (add, modify, delete +/- strict).
Dan Talaycofa6454f2012-04-05 10:04:13 -07001771 """
1772 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001773 flow_count = test_param_get('ft_flow_count', default=20)
1774 iter_count = test_param_get('ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001775
Rich Lane9a003812012-10-04 17:17:59 -07001776 logging.info("Running flow toggle with %d flows, %d iterations" %
Dan Talaycofa6454f2012-04-05 10:04:13 -07001777 (flow_count, iter_count))
1778 acts = []
1779 acts.append(action.action_output())
1780 acts.append(action.action_output())
1781
Rich Lane477f4812012-10-04 22:49:00 -07001782 of_ports = config["port_map"].keys()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001783 if len(of_ports) < 3:
1784 self.assertTrue(False, "Too few ports for test")
1785
1786 for idx in range(2):
1787 acts[idx].port = of_ports[idx]
1788
1789 flows = []
1790 flows.append([])
1791 flows.append([])
1792
Ed Swierk99a74de2012-08-22 06:40:54 -07001793 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_SRC |
1794 ofp.OFPFW_DL_DST)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001795 # Create up the flows in an array
1796 for toggle in range(2):
1797 for f_idx in range(flow_count):
1798 pkt = simple_tcp_packet(tcp_sport=f_idx)
1799 msg = message.flow_mod()
Ed Swierk99a74de2012-08-22 06:40:54 -07001800 match = packet_to_flow_match(self, pkt)
Shudong Zhou031373c2012-07-19 17:37:42 -07001801 match.in_port = of_ports[2]
Dan Talayco50be7672012-04-05 11:38:08 -07001802 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001803 msg.match = match
1804 msg.buffer_id = 0xffffffff
Dan Talaycof7c41312012-07-23 12:53:19 -07001805 msg.command = ofp.OFPFC_ADD
Dan Talaycofa6454f2012-04-05 10:04:13 -07001806 msg.actions.add(acts[toggle])
1807 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001808
1809 # Show two sample flows
Rich Lane9a003812012-10-04 17:17:59 -07001810 logging.debug(flows[0][0].show())
1811 logging.debug(flows[1][0].show())
Dan Talayco50be7672012-04-05 11:38:08 -07001812
Dan Talaycofa6454f2012-04-05 10:04:13 -07001813 # Install the first set of flows
1814 for f_idx in range(flow_count):
1815 rv = self.controller.message_send(flows[0][f_idx])
1816 self.assertTrue(rv != -1, "Error installing flow %d" % f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001817 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycofa6454f2012-04-05 10:04:13 -07001818
Rich Lane9a003812012-10-04 17:17:59 -07001819 logging.info("Installed %d flows" % flow_count)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001820
1821 # Repeatedly modify all the flows back and forth
1822 updates = 0
1823 # Report status about 5 times
1824 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001825 start = time.time()
1826 for iter_idx in range(iter_count):
1827 if not iter_idx % mod_val:
Rich Lane9a003812012-10-04 17:17:59 -07001828 logging.info("Flow Toggle: iter %d of %d. " %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001829 (iter_idx, iter_count) +
1830 "%d updates in %d secs" %
1831 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001832 for toggle in range(2):
1833 t_idx = 1 - toggle
1834 for f_idx in range(flow_count):
1835 rv = self.controller.message_send(flows[t_idx][f_idx])
1836 updates += 1
1837 self.assertTrue(rv != -1, "Error modifying flow %d" %
1838 f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001839 self.assertEqual(do_barrier(self.controller), 0,
1840 "Barrier failed")
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001841
1842 end = time.time()
1843 divisor = end - start or (end - start + 1)
Rich Lane9a003812012-10-04 17:17:59 -07001844 logging.info("Flow toggle: %d iterations" % iter_count)
1845 logging.info(" %d flow mods in %d secs, %d mods/sec" %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001846 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001847
1848
Dan Talayco8a64e332012-03-28 14:53:20 -07001849# You can pick and choose these by commenting tests in or out
1850iter_classes = [
1851 basic.PacketIn,
1852 basic.PacketOut,
1853 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001854 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001855 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001856 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001857 AllWildcardMatch,
1858 AllWildcardMatchTagged,
1859 SingleWildcardMatch,
1860 SingleWildcardMatchTagged,
1861 ExactMatch,
1862 ExactMatchTagged,
1863 SingleWildcardMatch,
1864 ModifyL2Src,
1865 ModifyL2Dst,
1866 ModifyL2SrcMC,
1867 ModifyL2DstMC,
1868 ModifyL2SrcDstMC
1869 ]
1870
1871class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001872 """
1873 Iterate over a bunch of test cases
1874
1875 The cases come from the list above
1876 """
1877
Rich Laned1d9c282012-10-04 22:07:10 -07001878 priority = -1
1879
Dan Talayco8a64e332012-03-28 14:53:20 -07001880 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001881 count = test_param_get('iter_count', default=10)
Dan Talayco8a64e332012-03-28 14:53:20 -07001882 tests_done = 0
Rich Lane9a003812012-10-04 17:17:59 -07001883 logging.info("Running iteration test " + str(count) + " times")
Dan Talayco8a64e332012-03-28 14:53:20 -07001884 start = time.time()
1885 last = start
1886 for idx in range(count):
Rich Lane9a003812012-10-04 17:17:59 -07001887 logging.info("Iteration " + str(idx + 1))
Dan Talayco8a64e332012-03-28 14:53:20 -07001888 for cls in iter_classes:
1889 test = cls()
1890 test.inheritSetup(self)
1891 test.runTest()
1892 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001893 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001894 if time.time() - last > 60:
1895 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001896 logging.info(
Dan Talaycofa6454f2012-04-05 10:04:13 -07001897 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1898 (idx, count, tests_done, last - start) +
1899 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001900 stats = all_stats_get(self)
1901 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001902 logging.info("\nIterCases ran %d tests in %d seconds." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001903 (tests_done, last - start))
Rich Lane9a003812012-10-04 17:17:59 -07001904 logging.info(" flows: %d. packets: %d. bytes: %d" %
Dan Talayco8a64e332012-03-28 14:53:20 -07001905 (stats["flows"], stats["packets"], stats["bytes"]))
Rich Lane9a003812012-10-04 17:17:59 -07001906 logging.info(" active: %d. lookups: %d. matched %d." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001907 (stats["active"], stats["lookups"], stats["matched"]))
1908
Dan Talayco4b2bee62010-07-20 14:10:05 -07001909#@todo Need to implement tagged versions of the above tests
1910#
1911#@todo Implement a test case that strips tag 2, adds tag 3
1912# and modifies tag 4 to tag 5. Then verify (in addition) that
1913# tag 6 does not get modified.
1914
1915class MixedVLAN(BaseMatchCase):
1916 """
1917 Test mixture of VLAN tag actions
1918
1919 Strip tag 2 on port 1, send to port 2
1920 Add tag 3 on port 1, send to port 2
1921 Modify tag 4 to 5 on port 1, send to port 2
1922 All other traffic from port 1, send to port 3
1923 All traffic from port 2 sent to port 4
1924 Use exact matches with different packets for all mods
1925 Verify the following: (port, vid)
1926 (port 1, vid 2) => VLAN tag stripped, out port 2
1927 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1928 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1929 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1930 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1931 (port 2, no tag) => untagged packet out port 4
1932 (port 2, vid 2-6) => unmodified packet out port 4
1933
1934 Variation: Might try sending VID 5 to port 3 and check.
1935 If only VID 5 distinguishes pkt, this will fail on some platforms
1936 """
1937
Rich Laned1d9c282012-10-04 22:07:10 -07001938 priority = -1
Rich Lane8d6ab272012-09-23 18:06:20 -07001939
Rich Laneb90a1c42012-10-05 09:16:05 -07001940class MatchEach(base_tests.SimpleDataPlane):
Rich Lane8d6ab272012-09-23 18:06:20 -07001941 """
1942 Check that each match field is actually matched on.
1943 Installs two flows that differ in one field. The flow that should not
1944 match has a higher priority, so if that field is ignored during matching
1945 the packet will be sent out the wrong port.
1946
1947 TODO test UDP, ARP, ICMP, etc.
1948 """
1949 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001950 of_ports = config["port_map"].keys()
Rich Lane8d6ab272012-09-23 18:06:20 -07001951 of_ports.sort()
1952 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1953
Rich Lane9a003812012-10-04 17:17:59 -07001954 delete_all_flows(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001955
Ed Swierk7040a8d2012-12-11 16:30:13 -08001956 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=2)
Rich Lane8d6ab272012-09-23 18:06:20 -07001957 ingress_port = of_ports[0]
1958 egress_port = of_ports[1]
1959
1960 def testField(field, mask):
Rich Lane9a003812012-10-04 17:17:59 -07001961 logging.info("Testing field %s" % field)
Rich Lane8d6ab272012-09-23 18:06:20 -07001962
1963 def addFlow(matching, priority, output_port):
1964 match = packet_to_flow_match(self, pkt)
1965 self.assertTrue(match is not None, "Could not generate flow match from pkt")
1966 match.wildcards &= ~ofp.OFPFW_IN_PORT
1967 match.in_port = ingress_port
1968 if not matching:
1969 # Make sure flow doesn't match
1970 orig = getattr(match, field)
1971 if isinstance(orig, list):
1972 new = map(lambda a: ~a[0] & a[1], zip(orig, mask))
1973 else:
1974 new = ~orig & mask
1975 setattr(match, field, new)
1976 request = message.flow_mod()
1977 request.match = match
1978 request.buffer_id = 0xffffffff
1979 request.priority = priority
1980 act = action.action_output()
1981 act.port = output_port
1982 self.assertTrue(request.actions.add(act), "Could not add action")
Rich Lane9a003812012-10-04 17:17:59 -07001983 logging.info("Inserting flow")
Rich Lane8d6ab272012-09-23 18:06:20 -07001984 self.controller.message_send(request)
1985
1986 # This flow should match.
1987 addFlow(matching=True, priority=0, output_port=egress_port)
1988 # This flow should not match, but it has a higher priority.
1989 addFlow(matching=False, priority=1, output_port=ofp.OFPP_IN_PORT)
1990
1991 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
1992
Rich Lane9a003812012-10-04 17:17:59 -07001993 logging.info("Sending packet to dp port " + str(ingress_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001994 self.dataplane.send(ingress_port, str(pkt))
1995
1996 exp_pkt_arg = None
1997 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -07001998 if config["relax"]:
Rich Lane8d6ab272012-09-23 18:06:20 -07001999 exp_pkt_arg = pkt
2000 exp_port = egress_port
2001
2002 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
2003 exp_pkt=exp_pkt_arg)
2004 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -07002005 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07002006 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
2007 self.assertEqual(str(pkt), str(rcv_pkt), 'Response packet does not match send packet')
2008
Ed Swierkb603b192012-12-12 15:38:49 -08002009 wildcards = required_wildcards(self)
Rich Lane8d6ab272012-09-23 18:06:20 -07002010 # TODO in_port
Ed Swierkb603b192012-12-12 15:38:49 -08002011 if not (wildcards & ofp.OFPFW_DL_SRC):
2012 testField("dl_src", [0xff]*6)
2013 if not (wildcards & ofp.OFPFW_DL_DST):
2014 testField("dl_dst", [0xff]*6)
2015 if not (wildcards & ofp.OFPFW_DL_TYPE):
2016 testField("dl_type", 0xffff)
2017 if not (wildcards & ofp.OFPFW_DL_VLAN):
2018 testField("dl_vlan", 0xfff)
Rich Lane8d6ab272012-09-23 18:06:20 -07002019 # TODO dl_vlan_pcp
Ed Swierkb603b192012-12-12 15:38:49 -08002020 if not (wildcards & ofp.OFPFW_NW_SRC_ALL):
2021 testField("nw_src", 0xffffffff)
2022 if not (wildcards & ofp.OFPFW_NW_DST_ALL):
2023 testField("nw_dst", 0xffffffff)
2024 if not (wildcards & ofp.OFPFW_NW_TOS):
2025 testField("nw_tos", 0x3f)
2026 if not (wildcards & ofp.OFPFW_NW_PROTO):
2027 testField("nw_proto", 0xff)
2028 if not (wildcards & ofp.OFPFW_TP_SRC):
2029 testField("tp_src", 0xffff)
2030 if not (wildcards & ofp.OFPFW_TP_DST):
2031 testField("tp_dst", 0xffff)
Rich Lane8d6ab272012-09-23 18:06:20 -07002032
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002033class DirectBadPacketBase(base_tests.SimpleDataPlane):
2034 """
2035 Base class for sending single packets with single flow table entries.
2036 Used to verify matching of unusual packets and parsing/matching of
2037 corrupted packets.
2038
2039 The idea is to generate packets that may either be totally malformed or
2040 malformed just enough to trick the flow matcher into making mistakes.
2041
2042 Generate a 'bad' packet
2043 Generate and install a matching flow
2044 Add action to direct the packet to an egress port
2045 Send the packet to ingress dataplane port
2046 Verify the packet is received at the egress port only
2047 """
2048
Rich Lane5d0e13c2012-12-24 15:05:07 -08002049 priority = -1 # no-op base class
2050
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002051 RESULT_MATCH = "MATCH"
2052 RESULT_NOMATCH = "NO MATCH"
2053 RESULT_ANY = "ANY MATCH"
2054
2055 def runTest(self):
2056 pass
2057 # TODO:
2058 # - ICMP?
2059 # - VLAN?
2060 # - action
2061
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002062 def createMatch(self, **kwargs):
2063 match = ofp.ofp_match()
2064 match.wildcards = ofp.OFPFW_ALL
2065 fields = {
2066 'dl_dst': ofp.OFPFW_DL_DST,
2067 'dl_src': ofp.OFPFW_DL_SRC,
2068 'dl_type': ofp.OFPFW_DL_TYPE,
2069 'dl_vlan': ofp.OFPFW_DL_VLAN,
2070 'nw_src': ofp.OFPFW_NW_SRC_MASK,
2071 'nw_dst': ofp.OFPFW_NW_DST_MASK,
2072 'nw_tos': ofp.OFPFW_NW_TOS,
2073 'nw_proto': ofp.OFPFW_NW_PROTO,
2074 'tp_src': ofp.OFPFW_TP_SRC,
2075 'tp_dst': ofp.OFPFW_TP_DST,
2076 }
2077 for key in kwargs:
2078 setattr(match, key, kwargs[key])
2079 match.wildcards &= ~fields[key]
2080 return match
2081
2082 def testPktsAgainstFlow(self, pkts, acts, match):
2083 if type(acts) != list:
2084 acts = [acts]
2085 for info in pkts:
2086 title, pkt, expected_result = info
2087 self.testPktAgainstFlow(title, pkt, acts, match, expected_result)
2088
2089 def testPktAgainstFlow(self, title, pkt, acts, match, expected_result):
2090 of_ports = config["port_map"].keys()
2091 of_ports.sort()
2092 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
2093
2094 rv = delete_all_flows(self.controller)
2095 self.assertEqual(rv, 0, "Failed to delete all flows")
2096
2097 ingress_port = of_ports[0]
2098 egress_port = of_ports[1]
2099
2100 logging.info("Testing packet '%s', expect result %s" %
2101 (title, expected_result))
2102 logging.info("Ingress %s to egress %s" %
2103 (str(ingress_port), str(egress_port)))
2104 logging.info("Packet:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002105 logging.info(inspect_packet(pkt))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002106
2107 match.in_port = ingress_port
2108
2109 request = message.flow_mod()
2110 request.match = match
Rich Lane44cf12d2012-10-15 11:10:45 -07002111 request.priority = 1
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002112
2113 request.buffer_id = 0xffffffff
2114 for act in acts:
2115 act.port = egress_port
2116 rv = request.actions.add(act)
2117 self.assertTrue(rv, "Could not add action")
2118
2119 logging.info("Inserting flow")
2120 rv = self.controller.message_send(request)
2121 self.assertTrue(rv != -1, "Error installing flow mod")
Rich Lane44cf12d2012-10-15 11:10:45 -07002122
2123 # This flow speeds up negative tests
2124 logging.info("Inserting catch-all flow")
2125 request2 = message.flow_mod()
2126 request2.match = self.createMatch()
2127 request2.priority = 0
2128 act = action.action_output()
2129 act.port = ofp.OFPP_IN_PORT
2130 request2.actions.add(act)
2131 rv = self.controller.message_send(request2)
2132 self.assertTrue(rv != -1, "Error installing flow mod")
2133
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002134 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
2135
2136 logging.info("Sending packet to dp port " +
2137 str(ingress_port))
2138 self.dataplane.send(ingress_port, str(pkt))
2139
2140 exp_pkt_arg = None
2141 exp_port = None
2142 if config["relax"]:
2143 exp_pkt_arg = pkt
2144 exp_port = egress_port
2145
Rich Lane44cf12d2012-10-15 11:10:45 -07002146 if expected_result == self.RESULT_MATCH:
2147 timeout = -1 # default timeout
2148 else:
2149 timeout = 1 # short timeout for negative tests
2150
2151 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(exp_pkt=exp_pkt_arg,
2152 timeout=timeout)
2153 if rcv_port == ingress_port:
2154 logging.debug("Packet matched catch-all flow")
2155 rcv_pkt = None
2156
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002157 if expected_result == self.RESULT_MATCH:
2158 self.assertTrue(rcv_pkt is not None,
2159 "Did not receive packet, expected a match")
2160 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
2161 str(rcv_port))
2162 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
2163 str_pkt = str(pkt)
2164 str_rcv_pkt = str(rcv_pkt)
2165 str_rcv_pkt = str_rcv_pkt[0:len(str_pkt)]
2166 if str_pkt != str_rcv_pkt:
2167 logging.error("Response packet does not match send packet")
2168 logging.info("Response:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002169 logging.info(inspect_packet(scapy.Ether(rcv_pkt)))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002170 self.assertEqual(str_pkt, str_rcv_pkt,
2171 'Response packet does not match send packet')
2172 elif expected_result == self.RESULT_NOMATCH:
2173 self.assertTrue(rcv_pkt is None, "Received packet, expected drop")
2174 else:
2175 logging.debug("Match or drop accepted. Result = %s" %
2176 ("match" if rcv_pkt is not None else "drop"))
2177
2178
2179class DirectBadIpTcpPacketsBase(DirectBadPacketBase):
2180 """
2181 Base class for TCP and UDP parsing/matching verification under corruptions
2182 """
2183 def runTest(self):
2184 pass
2185
2186 def runTestWithProto(self, protoName = 'TCP'):
2187 dl_dst='00:01:02:03:04:05'
2188 dl_src='00:06:07:08:09:0a'
2189 ip_src='192.168.0.1'
2190 ip_dst='192.168.0.2'
2191 ip_tos=0
2192 tcp_sport=1234
2193 tcp_dport=80
2194
2195 # Generate a proper packet for constructing a match
2196 tp = None
2197 if protoName == 'TCP':
2198 tp = scapy.TCP
2199 proto = 6
2200 elif protoName == 'UDP':
2201 tp = scapy.UDP
2202 proto = 17
2203 else:
2204 raise Exception("Passed in unknown proto name")
2205
2206 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
2207 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2208 tp(sport=tcp_sport, dport=tcp_dport)
2209 match = packet_to_flow_match(self, match_pkt)
2210 self.assertTrue(match is not None,
2211 "Could not generate flow match from pkt")
2212 match.wildcards &= ~ofp.OFPFW_IN_PORT
2213
2214 def testPacket(title, pkt, result):
2215 act = action.action_output()
2216 pkts = [
2217 [title, pkt, result]
2218 ]
2219 self.testPktsAgainstFlow(pkts, act, match)
2220
2221 # Try incomplete IP headers
2222 testPacket("Incomplete IP header (1 bytes)",
2223 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2224 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:1],
2225 self.RESULT_NOMATCH,
2226 )
2227 testPacket("Incomplete IP header (2 bytes)",
2228 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2229 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:2],
2230 self.RESULT_NOMATCH,
2231 )
2232 testPacket("Incomplete IP header (3 bytes)",
2233 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2234 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:3],
2235 self.RESULT_NOMATCH,
2236 )
2237 testPacket("Incomplete IP header (12 bytes)",
2238 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2239 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:12],
2240 self.RESULT_NOMATCH,
2241 )
2242 testPacket("Incomplete IP header (16 bytes)",
2243 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2244 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:16],
2245 self.RESULT_NOMATCH,
2246 )
2247 testPacket("Incomplete IP header (19 bytes)",
2248 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2249 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:19],
2250 self.RESULT_NOMATCH,
2251 )
2252
2253 # Try variations where the TCP header is missing or incomplete. As we
2254 # saw bugs before where buffers were reused and lengths weren't honored,
2255 # we initiatlize once with a non-matching full packet and once with a
2256 # matching full packet.
2257 testPacket("Non-Matching TCP packet, warming buffer",
2258 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2259 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2260 tp(sport=tcp_sport, dport=tcp_dport + 1),
2261 self.RESULT_NOMATCH,
2262 )
2263 testPacket("Missing TCP header, buffer warmed with non-match",
2264 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2265 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2266 self.RESULT_NOMATCH,
2267 )
2268 testPacket("Matching TCP packet, warming buffer",
2269 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2270 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2271 tp(sport=tcp_sport, dport=tcp_dport),
2272 self.RESULT_MATCH,
2273 )
2274 testPacket("Missing TCP header, buffer warmed with match",
2275 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2276 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2277 self.RESULT_NOMATCH,
2278 )
2279 testPacket("Truncated TCP header: 2 bytes",
2280 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2281 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2282 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:2]),
2283 self.RESULT_NOMATCH,
2284 )
2285
2286 # Play with IP header length values that put the start of TCP either
2287 # inside the generated TCP header or beyond. In some cases it may even
2288 # be beyond the packet boundary. Also play with IP options and more
2289 # importantly IP total length corruptions.
2290 testPacket("TCP packet, corrupt ihl (0x6)",
2291 simple_tcp_packet(ip_ihl=6),
2292 self.RESULT_NOMATCH,
2293 )
2294 testPacket("TCP packet, corrupt ihl (0xf)",
2295 simple_tcp_packet(ip_ihl=0xf), # ihl = 15 * 4 = 60
2296 self.RESULT_NOMATCH,
2297 )
2298 testPacket("TCP packet, corrupt ihl and total length",
2299 simple_tcp_packet(ip_ihl=0xf, pktlen=56), # ihl = 15 * 4 = 60,
2300 self.RESULT_NOMATCH,
2301 )
2302 testPacket("Corrupt IPoption: First 4 bytes of matching TCP header",
2303 simple_tcp_packet(
2304 ip_options=scapy.IPOption('\x04\xd2\x00\x50'),
2305 tcp_dport=2, tcp_sport=2
2306 ),
2307 self.RESULT_NOMATCH,
2308 )
2309 testPacket("Missing TCP header, corrupt ihl",
2310 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2311 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto),
2312 self.RESULT_NOMATCH,
2313 )
2314 testPacket("Missing TCP header, corrupt total length",
2315 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2316 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, len= 100),
2317 self.RESULT_NOMATCH,
2318 )
2319 testPacket("Missing TCP header, corrupt ihl and total length",
2320 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2321 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto, len=43),
2322 self.RESULT_NOMATCH,
2323 )
2324 testPacket("Incomplete IP header (12 bytes), corrupt ihl and total length",
2325 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2326 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:12],
2327 self.RESULT_NOMATCH,
2328 )
2329 testPacket("Incomplete IP header (16 bytes), corrupt ihl and total length",
2330 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2331 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:16],
2332 self.RESULT_NOMATCH,
2333 )
2334
2335 # Try an incomplete TCP header that has enough bytes to carry source and
2336 # destination ports. As that is all we care about during matching, some
2337 # implementations may match and some may drop the packet
2338 testPacket("Incomplete TCP header: src/dst port present",
2339 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2340 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2341 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:4]),
2342 self.RESULT_ANY,
2343 )
2344
2345 for i in range(1):
2346 for length in range(40 / 4): # IPv4 options are a maximum of 40 in length
2347 bytes = "".join([("%c" % random.randint(0, 255)) for x in range(length * 4)])
2348 eth = scapy.Ether(dst=dl_dst, src=dl_src)
2349 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2350 tcp = tp(sport=tcp_sport, dport=tcp_dport+1)
2351 pkt = eth / ip
2352 pkt = pkt / bytes
2353 pkt = pkt / str(tcp)
2354 testPacket("Random IP options len = %d - TP match must fail" % length * 4,
2355 pkt,
2356 self.RESULT_NOMATCH
2357 )
2358
2359 eth = scapy.Ether(dst=dl_dst, src=dl_src)
2360 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2361 tcp = tp(sport=tcp_sport, dport=tcp_dport)
2362 pkt = eth / ip
2363 pkt = pkt / bytes
2364 pkt = pkt / str(tcp)
2365
2366 testPacket("Random IP options len = %d - May match",
2367 pkt,
2368 self.RESULT_ANY
2369 )
2370
2371
2372class DirectBadIpTcpPackets(DirectBadIpTcpPacketsBase):
2373 """
2374 Verify IP/TCP parsing and matching. Focus on packet corruptions
2375 """
2376 def runTest(self):
2377 self.runTestWithProto(protoName = 'TCP')
2378
2379class DirectBadIpUdpPackets(DirectBadIpTcpPacketsBase):
2380 """
2381 Verify IP/UDP parsing and matching. Focus on packet corruptions
2382 """
2383 def runTest(self):
2384 self.runTestWithProto(protoName = 'UDP')
2385
2386class DirectBadLlcPackets(DirectBadPacketBase):
2387 """
2388 Verify LLC/SNAP parsing and matching. Focus on packet corruptions
2389 """
2390 def runTest(self):
2391 dl_dst='00:01:02:03:04:05'
2392 dl_src='00:06:07:08:09:0a'
2393 ip_src='192.168.0.1'
2394 ip_dst='192.168.0.2'
2395 ip_tos=0
2396 tcp_sport=1234
2397 tcp_dport=80
2398
2399 IS_SNAP_IP = 1
2400 IS_SNAP_IP_CORRUPT = 2
2401 IS_NOT_SNAP_IP = 3
2402
2403 def testPacketTcpMatch(title, llc):
2404 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
2405 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2406 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
2407 match = packet_to_flow_match(self, match_pkt)
2408 self.assertTrue(match is not None,
2409 "Could not generate flow match from pkt")
2410 match.wildcards &= ~ofp.OFPFW_IN_PORT
2411 act = action.action_output()
2412
2413 self.testPktsAgainstFlow(
2414 [[
2415 "TCP match - LLC frame correct length - %s" % title,
2416 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2417 self.RESULT_ANY,
2418 ]],
2419 act, match
2420 )
2421
2422 # Corrupt length field
2423 ethLen = random.randint(0, 1535)
2424 self.testPktsAgainstFlow(
2425 [[
2426 "TCP match - LLC frame corrupted length - %s" % title,
2427 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
2428 self.RESULT_ANY,
2429 ]],
2430 act, match
2431 )
2432
2433 def testPacketEthSrcDstMatch(title, llc):
2434 # Matching based on Ethernet source and destination
2435 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)
2436 match = packet_to_flow_match(self, match_pkt)
2437 self.assertTrue(match is not None,
2438 "Could not generate flow match from pkt")
2439 match.wildcards &= ~ofp.OFPFW_IN_PORT
2440 match.wildcards |= ofp.OFPFW_DL_TYPE
2441 self.testPktsAgainstFlow(
2442 [[
2443 "Eth addr match - LLC frame correct length- %s" % title,
2444 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2445 self.RESULT_MATCH,
2446 ]],
2447 action.action_output(), match
2448 )
2449
2450 # Corrupt length field
2451 ethLen = random.randint(0, 1535)
2452 self.testPktsAgainstFlow(
2453 [[
2454 "Eth addr match - LLC frame corrupted length- %s" % title,
2455 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
2456 self.RESULT_ANY,
2457 ]],
2458 action.action_output(), match
2459 )
2460
2461 def testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip):
2462 # Matching based on Ethernet source, destination and type
2463 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src, type=0x800)
2464 match = packet_to_flow_match(self, match_pkt)
2465 self.assertTrue(match is not None,
2466 "Could not generate flow match from pkt")
2467 match.wildcards &= ~ofp.OFPFW_IN_PORT
2468 if is_snap_ip == IS_SNAP_IP:
2469 is_match = self.RESULT_MATCH
2470 elif is_snap_ip == IS_SNAP_IP_CORRUPT:
2471 is_match = self.RESULT_ANY
2472 else:
2473 is_match = self.RESULT_NOMATCH
2474 self.testPktsAgainstFlow(
2475 [[
2476 "Eth addr+type match - LLC frame correct length - %s" % title,
2477 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2478 is_match,
2479 ]],
2480 action.action_output(), match
2481 )
2482
2483 # Corrupt length field
2484 ethLen = random.randint(0, 1535)
2485 self.testPktsAgainstFlow(
2486 [[
2487 "Eth addr+type match - LLC frame corrupted length - %s" % title,
2488 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
Christian Dickmanne9b6d252012-10-08 22:56:50 -07002489 self.RESULT_ANY,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002490 ]],
2491 action.action_output(), match
2492 )
2493
2494 def testPacket(title, llc, is_snap_ip):
2495 testPacketTcpMatch(title, llc)
2496 testPacketEthSrcDstMatch(title, llc)
2497 testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip)
2498
2499 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002500 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002501 IS_NOT_SNAP_IP,
2502 )
2503 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002504 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002505 IS_NOT_SNAP_IP,
2506 )
2507 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002508 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002509 IS_NOT_SNAP_IP,
2510 )
2511 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002512 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002513 IS_NOT_SNAP_IP,
2514 )
2515 testPacket("LLC - SNAP - Small bogus payload",
2516 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2517 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2518 IS_SNAP_IP_CORRUPT,
2519 )
2520 testPacket("LLC - SNAP - Max -1 bogus payload",
2521 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2522 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2523 IS_NOT_SNAP_IP,
2524 )
2525 testPacket("LLC - SNAP - Max bogus payload",
2526 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2527 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2528 IS_NOT_SNAP_IP,
2529 )
2530 testPacket("LLC - SNAP - IP - TCP",
2531 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2532 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2533 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2534 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2535 IS_SNAP_IP,
2536 )
2537
2538
2539class DirectLlcPackets(DirectBadPacketBase):
2540 """
2541 Verify LLC/SNAP parsing (valid and corrupted packets) and matching
2542 """
2543 def runTest(self):
2544 dl_dst='00:01:02:03:04:05'
2545 dl_src='00:06:07:08:09:0a'
2546 ip_src='192.168.0.1'
2547 ip_dst='192.168.0.2'
2548 ip_tos=0
2549 tcp_sport=1234
2550 tcp_dport=80
2551
2552 # Test ethertype in face of LLC/SNAP and OFP_DL_TYPE_NOT_ETH_TYPE
2553 IS_SNAP_NOT_IP = 1
2554 IS_SNAP_AND_IP = 2
2555 IS_NOT_SNAP = 3
2556
2557 def testPacketEthTypeIP(title, llc, is_snap):
2558 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src, type=0x800)
2559 match = packet_to_flow_match(self, match_pkt)
2560 self.assertTrue(match is not None,
2561 "Could not generate flow match from pkt")
2562 match.wildcards &= ~ofp.OFPFW_IN_PORT
2563 pkts = []
2564 if is_snap == IS_NOT_SNAP or is_snap == IS_SNAP_NOT_IP:
2565 result = self.RESULT_NOMATCH
2566 else:
2567 result = self.RESULT_MATCH
2568 pkts.append([
2569 "Ether type 0x800 match - %s" % title,
2570 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2571 result,
2572 ])
2573 act = action.action_output()
2574 self.testPktsAgainstFlow(pkts, act, match)
2575
2576 def testPacketEthTypeNotEth(title, llc, is_snap):
2577 match_pkt = scapy.Ether(dst = dl_dst, src = dl_src,
2578 type = ofp.OFP_DL_TYPE_NOT_ETH_TYPE)
2579 match = packet_to_flow_match(self, match_pkt)
2580 self.assertTrue(match is not None,
2581 "Could not generate flow match from pkt")
2582 match.wildcards &= ~ofp.OFPFW_IN_PORT
2583 pkts = []
2584 if is_snap == IS_NOT_SNAP:
2585 result = self.RESULT_MATCH
2586 else:
2587 result = self.RESULT_NOMATCH
2588 pkts.append([
2589 "Ether type OFP_DL_TYPE_NOT_ETH_TYPE match - %s" % title,
2590 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2591 result,
2592 ])
2593 act = action.action_output()
2594 self.testPktsAgainstFlow(pkts, act, match)
2595
2596 def testPacket(title, llc, is_snap):
2597 testPacketEthTypeIP(title, llc, is_snap)
2598 testPacketEthTypeNotEth(title, llc, is_snap)
2599
2600 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002601 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
2602 IS_NOT_SNAP,
2603 )
2604 testPacket("LLC (with information field) - No SNAP - No Payload",
2605 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x12) / "S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002606 IS_NOT_SNAP,
2607 )
2608 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002609 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002610 IS_NOT_SNAP,
2611 )
2612 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002613 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002614 IS_NOT_SNAP,
2615 )
2616 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002617 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002618 IS_NOT_SNAP,
2619 )
2620 testPacket("LLC - SNAP - Non-default OUI",
2621 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2622 scapy.SNAP(OUI=0x000001, code=0x800) / ("S" * 10),
2623 IS_NOT_SNAP,
2624 )
2625 testPacket("LLC - SNAP - Default OUI",
2626 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2627 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2628 IS_SNAP_AND_IP,
2629 )
2630 testPacket("LLC - SNAP - Max -1 bogus payload",
2631 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2632 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2633 IS_SNAP_NOT_IP,
2634 )
2635 testPacket("LLC - SNAP - Max bogus payload",
2636 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2637 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2638 IS_SNAP_NOT_IP,
2639 )
2640 testPacket("LLC - SNAP - IP - TCP",
2641 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2642 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2643 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2644 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2645 IS_SNAP_AND_IP,
2646 )
2647
2648
2649class DirectArpPackets(DirectBadPacketBase):
2650 """
2651 Verify ARP parsing (valid and corrupted packets) and ARP matching
2652 """
2653 def runTest(self):
2654 self.testArpHandling()
2655
2656 def testArpHandling(self):
2657 dl_dst='00:01:02:03:04:05'
2658 dl_src='00:06:07:08:09:0a'
2659 ip_src='192.168.0.1'
2660 ip_dst='192.168.0.2'
2661 ip_src2='192.168.1.1'
2662 ip_dst2='192.168.1.2'
2663 ip_tos=0
2664 tcp_sport=1234
2665 tcp_dport=80
2666
2667 def testPacket(title, arp_match, arp_pkt, result):
2668 pkts = []
2669
2670 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src) / arp_match
2671 match = packet_to_flow_match(self, match_pkt)
2672 self.assertTrue(match is not None,
2673 "Could not generate flow match from pkt")
2674 match.wildcards &= ~ofp.OFPFW_IN_PORT
2675
2676 pkts.append([
2677 title,
2678 scapy.Ether(dst=dl_dst, src=dl_src) / arp_pkt,
2679 result,
2680 ])
2681
2682 act = action.action_output()
2683 self.testPktsAgainstFlow(pkts, act, match)
2684
2685 testPacket("Basic ARP",
2686 scapy.ARP(psrc=ip_src, pdst=ip_dst, op = 1),
2687 scapy.ARP(hwdst = '00:00:00:00:00:00', hwsrc = dl_src,
2688 psrc = ip_src, pdst = ip_dst, hwlen = 6, plen = 4,
2689 ptype = 0x800, hwtype = 1, op = 1),
2690 self.RESULT_MATCH
2691 )
2692 # More stuff:
2693 # - Non matches on any property
2694 # - Corrupted hwlen and plen
2695 # - Other hwtype, ptype
2696 # - Truncated ARP pkt
2697
2698
2699class DirectVlanPackets(DirectBadPacketBase):
2700 """
2701 Verify VLAN parsing (valid and corrupted packets) and ARP matching
2702 """
2703 def runTest(self):
2704 dl_dst='00:01:02:03:04:05'
2705 dl_src='00:06:07:08:09:0a'
2706 ip_src='192.168.0.1'
2707 ip_dst='192.168.0.2'
2708 ip_src2='192.168.1.1'
2709 ip_dst2='192.168.1.2'
2710 ip_tos=0
2711 tcp_sport=1234
2712 tcp_dport=80
2713
2714 def testPacket(title, match, pkt, result):
2715 pkts = []
2716
2717 self.assertTrue(match is not None,
2718 "Could not generate flow match from pkt")
2719 match.wildcards &= ~ofp.OFPFW_IN_PORT
2720
2721 pkts.append([
2722 "%s" % title,
2723 pkt,
2724 result,
2725 ])
2726
2727 act = action.action_output()
2728 self.testPktsAgainstFlow(pkts, act, match)
2729
2730 testPacket("Basic MAC matching - IPv4 payload",
2731 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2732 scapy.Ether(dst=dl_dst, src=dl_src, type=0x800) / scapy.IP(),
2733 self.RESULT_MATCH
2734 )
2735 testPacket("Basic MAC matching - VMware beacon - no payload",
2736 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2737 scapy.Ether(dst=dl_dst, src=dl_src, type=0x8922),
2738 self.RESULT_MATCH
2739 )
2740 testPacket("Basic MAC matching - VMware beacon - with payload",
2741 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2742 scapy.Ether(dst=dl_dst, src=dl_src, type=0x8922)/ ("X" * 1),
2743 self.RESULT_MATCH
2744 )
2745 testPacket("Basic MAC matching - IPv6 payload",
2746 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2747 scapy.Ether(dst=dl_dst, src=dl_src) / scapy.IPv6(),
2748 self.RESULT_MATCH
2749 )
2750 testPacket("Basic MAC matching with VLAN tag present",
2751 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2752 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002753 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002754 scapy.IP(),
2755 self.RESULT_MATCH
2756 )
2757 testPacket("Basic MAC matching with VLAN tag present",
2758 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2759 dl_type=0x800),
2760 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002761 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002762 scapy.IP(),
2763 self.RESULT_MATCH
2764 )
2765 testPacket("Ether matching with VLAN tag present - No type match",
2766 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2767 dl_type=0x801),
2768 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002769 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002770 scapy.IP(),
2771 self.RESULT_NOMATCH
2772 )
2773 testPacket("Ether matching with VLAN tag present - No type match 0x8100",
2774 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2775 dl_type=0x8100),
2776 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002777 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002778 scapy.IP(),
2779 self.RESULT_NOMATCH
2780 )
2781 testPacket("Ether matching with double VLAN tag - Wrong type match",
2782 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2783 dl_type=0x800),
2784 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002785 scapy.Dot1Q(prio=5, vlan=1000)/ \
2786 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002787 scapy.IP(),
2788 self.RESULT_NOMATCH
2789 )
2790 testPacket("Ether matching with double VLAN tag - Type match",
2791 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2792 dl_type=0x8100),
2793 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002794 scapy.Dot1Q(prio=5, vlan=1000)/ \
2795 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002796 scapy.IP(),
2797 self.RESULT_MATCH
2798 )
2799 testPacket("IP matching - VLAN tag",
2800 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2801 dl_type=0x0800,
2802 nw_src=parse_ip(ip_src), nw_dst=parse_ip(ip_dst)),
2803 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002804 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002805 scapy.IP(src=ip_src, dst=ip_dst),
2806 self.RESULT_MATCH
2807 )
2808 # XXX:
2809 # - Matching on VLAN ID and Prio
2810 # - Actions
2811
2812
2813
Dan Talayco9f47f4d2010-06-03 13:54:37 -07002814if __name__ == "__main__":
2815 print "Please run through oft script: ./oft --test_spec=basic"