blob: cceb13e51772f9117d48127a2251b9df8d24fcb5 [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
Rich Lanea68176f2013-08-09 17:41:05 -070020import oftest.packet as scapy
Dan Talayco5eba8442010-03-10 13:58:43 -080021
Rich Lane477f4812012-10-04 22:49:00 -070022from oftest import config
Dan Talayco5eba8442010-03-10 13:58:43 -080023import oftest.controller as controller
Rich Laned7b0ffa2013-03-08 15:53:42 -080024import ofp
Dan Talayco5eba8442010-03-10 13:58:43 -080025import oftest.dataplane as dataplane
Dan Talayco5eba8442010-03-10 13:58:43 -080026import oftest.parse as parse
Rich Laneb90a1c42012-10-05 09:16:05 -070027import oftest.base_tests as base_tests
28import basic # for IterCases
Dan Talayco5eba8442010-03-10 13:58:43 -080029
Christian Dickmann8b59b4b2012-09-23 16:48:30 -070030from oftest.parse import parse_mac, parse_ip
31
Rich Laneda3b5ad2012-10-03 09:05:32 -070032from oftest.testutils import *
Dan Talayco5eba8442010-03-10 13:58:43 -080033
Dan Talayco551befa2010-07-15 17:05:32 -070034WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
Dan Talayco488fbc52012-04-09 16:30:41 -070035 ofp.OFPFW_DL_VLAN | ofp.OFPFW_DL_VLAN_PCP,
Dan Talayco551befa2010-07-15 17:05:32 -070036 ofp.OFPFW_DL_SRC,
37 ofp.OFPFW_DL_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070038 (ofp.OFPFW_DL_TYPE | ofp.OFPFW_NW_SRC_ALL |
39 ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS | ofp.OFPFW_NW_PROTO |
40 ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
41 (ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
Dan Talayco551befa2010-07-15 17:05:32 -070042 ofp.OFPFW_TP_SRC,
43 ofp.OFPFW_TP_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070044 ofp.OFPFW_NW_SRC_MASK,
45 ofp.OFPFW_NW_DST_MASK,
Dan Talayco551befa2010-07-15 17:05:32 -070046 ofp.OFPFW_DL_VLAN_PCP,
47 ofp.OFPFW_NW_TOS]
48
Dan Talayco488fbc52012-04-09 16:30:41 -070049NO_WILDCARD_VALUES = [(ofp.OFPFW_ALL ^ ofp.OFPFW_IN_PORT),
50 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN),
51 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_SRC),
52 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_DST),
53 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE),
54 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO),
55 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
56 ofp.OFPFW_TP_SRC),
57 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
58 ofp.OFPFW_TP_DST),
59 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
60 ofp.OFPFW_NW_SRC_MASK),
61 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
62 ofp.OFPFW_NW_DST_MASK),
63 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN ^ ofp.OFPFW_DL_VLAN_PCP),
64 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
65 ofp.OFPFW_NW_TOS)]
66
Dan Talayco551befa2010-07-15 17:05:32 -070067MODIFY_ACTION_VALUES = [ofp.OFPAT_SET_VLAN_VID,
68 ofp.OFPAT_SET_VLAN_PCP,
69 ofp.OFPAT_STRIP_VLAN,
70 ofp.OFPAT_SET_DL_SRC,
71 ofp.OFPAT_SET_DL_DST,
72 ofp.OFPAT_SET_NW_SRC,
73 ofp.OFPAT_SET_NW_DST,
74 ofp.OFPAT_SET_NW_TOS,
75 ofp.OFPAT_SET_TP_SRC,
76 ofp.OFPAT_SET_TP_DST]
77
Dan Talayco21381562010-07-17 00:34:47 -070078TEST_VID_DEFAULT = 2
79
Rich Lane97e99652013-01-02 17:23:20 -080080@group('smoke')
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")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800107 act = ofp.action.output()
Dan Talayco5eba8442010-03-10 13:58:43 -0800108
109 for idx in range(len(of_ports)):
Rich Lane32bf9482013-01-03 17:26:30 -0800110 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700111
Dan Talayco5eba8442010-03-10 13:58:43 -0800112 ingress_port = of_ports[idx]
113 egress_port = of_ports[(idx + 1) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700114 logging.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700115 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800116
117 match.in_port = ingress_port
118
Rich Laneba3f0e22013-03-11 16:43:57 -0700119 request = ofp.message.flow_add()
Dan Talayco5eba8442010-03-10 13:58:43 -0800120 request.match = match
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700121
Dan Talayco5eba8442010-03-10 13:58:43 -0800122 request.buffer_id = 0xffffffff
123 act.port = egress_port
Rich Lanec495d9e2013-03-08 17:43:36 -0800124 request.actions.append(act)
Dan Talayco5eba8442010-03-10 13:58:43 -0800125
Rich Lane9a003812012-10-04 17:17:59 -0700126 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800127 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800128 do_barrier(self.controller)
Dan Talayco5eba8442010-03-10 13:58:43 -0800129
Rich Lane9a003812012-10-04 17:17:59 -0700130 logging.info("Sending packet to dp port " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800131 str(ingress_port))
132 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700133
134 exp_pkt_arg = None
135 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700136 if config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700137 exp_pkt_arg = pkt
138 exp_port = egress_port
139
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700140 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700141 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800142 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700143 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800144 str(rcv_port))
145 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
146 self.assertEqual(str(pkt), str(rcv_pkt),
147 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700148
Rich Lane97e99652013-01-02 17:23:20 -0800149@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -0700150class DirectPacketController(base_tests.SimpleDataPlane):
Rich Lane51c23b32012-07-27 16:37:25 -0700151 """
152 Send packet to the controller port
153
154 Generate a packet
155 Generate and install a matching flow
156 Add action to direct the packet to the controller port
157 Send the packet to ingress dataplane port
158 Verify the packet is received at the controller port
159 """
160 def runTest(self):
161 self.handleFlow()
162
163 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700164 of_ports = config["port_map"].keys()
Rich Lane51c23b32012-07-27 16:37:25 -0700165 of_ports.sort()
166 self.assertTrue(len(of_ports) > 0, "Not enough ports for test")
167
168 if (pkttype == 'ICMP'):
169 pkt = simple_icmp_packet()
170 else:
171 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700172 match = packet_to_flow_match(self, pkt)
Rich Lane51c23b32012-07-27 16:37:25 -0700173 match.wildcards &= ~ofp.OFPFW_IN_PORT
174 self.assertTrue(match is not None,
175 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800176 act = ofp.action.output()
Rich Lane51c23b32012-07-27 16:37:25 -0700177
Rich Lane32bf9482013-01-03 17:26:30 -0800178 delete_all_flows(self.controller)
Rich Lane51c23b32012-07-27 16:37:25 -0700179
180 ingress_port = of_ports[0]
181 match.in_port = ingress_port
182
Rich Laneba3f0e22013-03-11 16:43:57 -0700183 request = ofp.message.flow_add()
Rich Lane51c23b32012-07-27 16:37:25 -0700184 request.match = match
185
186 request.buffer_id = 0xffffffff
187 act.port = ofp.OFPP_CONTROLLER
188 act.max_len = 65535
Rich Lanec495d9e2013-03-08 17:43:36 -0800189 request.actions.append(act)
Rich Lane51c23b32012-07-27 16:37:25 -0700190
Rich Lane9a003812012-10-04 17:17:59 -0700191 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800192 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800193 do_barrier(self.controller)
Rich Lane51c23b32012-07-27 16:37:25 -0700194
Rich Lane9a003812012-10-04 17:17:59 -0700195 logging.info("Sending packet to dp port " +
Rich Lane51c23b32012-07-27 16:37:25 -0700196 str(ingress_port))
197 self.dataplane.send(ingress_port, str(pkt))
198
Rich Lane4c504f32013-06-07 17:24:14 -0700199 verify_packet_in(self, str(pkt), ingress_port, ofp.OFPR_ACTION)
Howard Pershf97840f2012-04-10 16:30:42 -0700200
Rich Laneb90a1c42012-10-05 09:16:05 -0700201class DirectPacketQueue(base_tests.SimpleDataPlane):
Howard Pershf97840f2012-04-10 16:30:42 -0700202 """
203 Send packet to single queue on single egress port
204
205 Generate a packet
206 Generate and install a matching flow
207 Add action to direct the packet to an egress port and queue
208 Send the packet to ingress dataplane port
209 Verify the packet is received at the egress port only
210 """
211 def runTest(self):
212 self.handleFlow()
213
Howard Persh670b5672012-04-13 09:08:29 -0700214 def portQueuesGet(self, queue_stats, port_num):
215 result = []
Rich Lane5fd6faf2013-03-11 13:30:20 -0700216 for qs in queue_stats.entries:
Howard Persh670b5672012-04-13 09:08:29 -0700217 if qs.port_no != port_num:
218 continue
219 result.append(qs.queue_id)
220 return result
221
Howard Pershf97840f2012-04-10 16:30:42 -0700222 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700223 of_ports = config["port_map"].keys()
Howard Pershf97840f2012-04-10 16:30:42 -0700224 of_ports.sort()
225 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
226
227 if (pkttype == 'ICMP'):
228 pkt = simple_icmp_packet()
229 else:
230 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700231 match = packet_to_flow_match(self, pkt)
Howard Pershf97840f2012-04-10 16:30:42 -0700232 match.wildcards &= ~ofp.OFPFW_IN_PORT
233 self.assertTrue(match is not None,
234 "Could not generate flow match from pkt")
235
Howard Persh670b5672012-04-13 09:08:29 -0700236 # Get queue stats from switch
237
Rich Lane28fa9272013-03-08 16:00:25 -0800238 request = ofp.message.queue_stats_request()
Howard Persh670b5672012-04-13 09:08:29 -0700239 request.port_no = ofp.OFPP_ALL
240 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700241 (queue_stats, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700242 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
243
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800244 act = ofp.action.enqueue()
Howard Pershf97840f2012-04-10 16:30:42 -0700245
246 for idx in range(len(of_ports)):
Howard Pershf97840f2012-04-10 16:30:42 -0700247 ingress_port = of_ports[idx]
248 egress_port = of_ports[(idx + 1) % len(of_ports)]
Howard Pershf97840f2012-04-10 16:30:42 -0700249
Howard Persh670b5672012-04-13 09:08:29 -0700250 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700251 logging.info("Ingress " + str(ingress_port)
Howard Persh670b5672012-04-13 09:08:29 -0700252 + " to egress " + str(egress_port)
253 + " queue " + str(egress_queue_id)
254 )
Howard Pershf97840f2012-04-10 16:30:42 -0700255
Rich Lane32bf9482013-01-03 17:26:30 -0800256 delete_all_flows(self.controller)
Howard Pershf97840f2012-04-10 16:30:42 -0700257
Howard Persh670b5672012-04-13 09:08:29 -0700258 match.in_port = ingress_port
259
Rich Laneba3f0e22013-03-11 16:43:57 -0700260 request = ofp.message.flow_add()
Howard Persh670b5672012-04-13 09:08:29 -0700261 request.match = match
Howard Pershf97840f2012-04-10 16:30:42 -0700262
Howard Persh670b5672012-04-13 09:08:29 -0700263 request.buffer_id = 0xffffffff
264 act.port = egress_port
265 act.queue_id = egress_queue_id
Rich Lanec495d9e2013-03-08 17:43:36 -0800266 request.actions.append(act)
Howard Pershf97840f2012-04-10 16:30:42 -0700267
Rich Lane9a003812012-10-04 17:17:59 -0700268 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800269 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800270 do_barrier(self.controller)
Howard Pershf97840f2012-04-10 16:30:42 -0700271
Howard Persh670b5672012-04-13 09:08:29 -0700272 # Get current stats for selected egress queue
Howard Pershf97840f2012-04-10 16:30:42 -0700273
Rich Lane28fa9272013-03-08 16:00:25 -0800274 request = ofp.message.queue_stats_request()
Howard Persh670b5672012-04-13 09:08:29 -0700275 request.port_no = egress_port
276 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700277 (qs_before, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700278 self.assertNotEqual(qs_before, None, "Queue stats request failed")
279
Rich Lane9a003812012-10-04 17:17:59 -0700280 logging.info("Sending packet to dp port " +
Howard Persh670b5672012-04-13 09:08:29 -0700281 str(ingress_port))
282 self.dataplane.send(ingress_port, str(pkt))
283
284 exp_pkt_arg = None
285 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700286 if config["relax"]:
Howard Persh670b5672012-04-13 09:08:29 -0700287 exp_pkt_arg = pkt
288 exp_port = egress_port
289
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700290 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Howard Persh670b5672012-04-13 09:08:29 -0700291 exp_pkt=exp_pkt_arg)
292 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700293 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Howard Persh670b5672012-04-13 09:08:29 -0700294 str(rcv_port))
295 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
296 self.assertEqual(str(pkt), str(rcv_pkt),
297 'Response packet does not match send packet')
298
Ed Swierkb8a86512012-04-18 18:45:58 -0700299 # FIXME: instead of sleeping, keep requesting queue stats until
300 # the expected queue counter increases or some large timeout is
301 # reached
302 time.sleep(2)
303
Howard Persh670b5672012-04-13 09:08:29 -0700304 # Get current stats for selected egress queue again
305
Rich Lane28fa9272013-03-08 16:00:25 -0800306 request = ofp.message.queue_stats_request()
Howard Persh670b5672012-04-13 09:08:29 -0700307 request.port_no = egress_port
308 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700309 (qs_after, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700310 self.assertNotEqual(qs_after, None, "Queue stats request failed")
311
312 # Make sure that tx packet counter for selected egress queue was
313 # incremented
314
Rich Lane5fd6faf2013-03-11 13:30:20 -0700315 self.assertEqual(qs_after.entries[0].tx_packets, \
316 qs_before.entries[0].tx_packets + 1, \
Howard Persh670b5672012-04-13 09:08:29 -0700317 "Verification of egress queue tx packet count failed"
318 )
319
320
Rich Laneb90a1c42012-10-05 09:16:05 -0700321class DirectPacketControllerQueue(base_tests.SimpleDataPlane):
Ken Chiang899ff8e2012-05-23 18:26:12 -0700322 """
323 Send a packet from each of the openflow ports
324 to each of the queues configured on the controller port.
325 If no queues have been configured, no packets are sent.
Howard Pershf97840f2012-04-10 16:30:42 -0700326
Ken Chiang899ff8e2012-05-23 18:26:12 -0700327 Generate a packet
328 Generate and install a matching flow
329 Add action to direct the packet to one of the controller port queues
330 Send the packet to ingress dataplane port
331 Verify the packet is received on the controller port queue
332 """
333 def runTest(self):
334 self.handleFlow()
335
336 def portQueuesGet(self, queue_stats, port_num):
337 result = []
Rich Lane5fd6faf2013-03-11 13:30:20 -0700338 for qs in queue_stats.entries:
Ken Chiang899ff8e2012-05-23 18:26:12 -0700339 if qs.port_no != port_num:
340 continue
341 result.append(qs.queue_id)
342 return result
343
344 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700345 of_ports = config["port_map"].keys()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700346 of_ports.sort()
347 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
348
349 if (pkttype == 'ICMP'):
350 pkt = simple_icmp_packet()
351 else:
352 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700353 match = packet_to_flow_match(self, pkt)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700354 match.wildcards &= ~ofp.OFPFW_IN_PORT
355 self.assertTrue(match is not None,
356 "Could not generate flow match from pkt")
357
358 # Get queue stats from switch
359
Rich Lane28fa9272013-03-08 16:00:25 -0800360 request = ofp.message.queue_stats_request()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700361 request.port_no = ofp.OFPP_CONTROLLER
362 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700363 (queue_stats, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700364 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
Rich Laneb73808c2013-03-11 15:22:23 -0700365 if queue_stats.type == ofp.OFPT_ERROR:
Rich Laneb8c845a2012-12-31 17:23:51 -0800366 skip_message_emit(self, "Enqueue packet to controller")
367 return
Ken Chiang899ff8e2012-05-23 18:26:12 -0700368
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800369 act = ofp.action.enqueue()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700370
371 for idx in range(len(of_ports)):
372 ingress_port = of_ports[idx]
373 egress_port = ofp.OFPP_CONTROLLER
374
Rich Lane9a003812012-10-04 17:17:59 -0700375 logging.info("Ingress port " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700376 + ", controller port queues "
377 + str(self.portQueuesGet(queue_stats, egress_port)))
378
379 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700380 logging.info("Ingress " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700381 + " to egress " + str(egress_port)
382 + " queue " + str(egress_queue_id)
383 )
384
Rich Lane32bf9482013-01-03 17:26:30 -0800385 delete_all_flows(self.controller)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700386
387 match.in_port = ingress_port
388
Rich Laneba3f0e22013-03-11 16:43:57 -0700389 request = ofp.message.flow_add()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700390 request.match = match
391
392 request.buffer_id = 0xffffffff
393 act.port = egress_port
394 act.queue_id = egress_queue_id
Rich Lanec495d9e2013-03-08 17:43:36 -0800395 request.actions.append(act)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700396
Rich Lane9a003812012-10-04 17:17:59 -0700397 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800398 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800399 do_barrier(self.controller)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700400
401 # Get current stats for selected egress queue
402
Rich Lane28fa9272013-03-08 16:00:25 -0800403 request = ofp.message.queue_stats_request()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700404 request.port_no = egress_port
405 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700406 (qs_before, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700407 self.assertNotEqual(qs_before, None, "Queue stats request failed")
408
Rich Lane9a003812012-10-04 17:17:59 -0700409 logging.info("Sending packet to dp port " +
Ken Chiang899ff8e2012-05-23 18:26:12 -0700410 str(ingress_port))
411 self.dataplane.send(ingress_port, str(pkt))
Ken Chiang899ff8e2012-05-23 18:26:12 -0700412
Rich Lane4c504f32013-06-07 17:24:14 -0700413 verify_packet_in(self, str(pkt), ingress_port, ofp.OFPR_ACTION)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700414
415 # FIXME: instead of sleeping, keep requesting queue stats until
416 # the expected queue counter increases or some large timeout is
417 # reached
418 time.sleep(2)
419
420 # Get current stats for selected egress queue again
421
Rich Lane28fa9272013-03-08 16:00:25 -0800422 request = ofp.message.queue_stats_request()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700423 request.port_no = egress_port
424 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700425 (qs_after, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700426 self.assertNotEqual(qs_after, None, "Queue stats request failed")
427
428 # Make sure that tx packet counter for selected egress queue was
429 # incremented
430
Rich Lane5fd6faf2013-03-11 13:30:20 -0700431 self.assertEqual(qs_after.entries[0].tx_packets, \
432 qs_before.entries[0].tx_packets + 1, \
Ken Chiang899ff8e2012-05-23 18:26:12 -0700433 "Verification of egress queue tx packet count failed"
434 )
435
Howard Pershf97840f2012-04-10 16:30:42 -0700436
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700437class DirectPacketICMP(DirectPacket):
438 """
439 Send ICMP packet to single egress port
440
441 Generate a ICMP packet
442 Generate and install a matching flow
443 Add action to direct the packet to an egress port
444 Send the packet to ingress dataplane port
445 Verify the packet is received at the egress port only
446 Difference from DirectPacket test is that sent packet is ICMP
447 """
448 def runTest(self):
449 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700450
Rich Laneb90a1c42012-10-05 09:16:05 -0700451class DirectTwoPorts(base_tests.SimpleDataPlane):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700452 """
453 Send packet to two egress ports
454
455 Generate a packet
456 Generate and install a matching flow
457 Add action to direct the packet to two egress ports
458 Send the packet to ingress dataplane port
459 Verify the packet is received at the two egress ports
460 """
461 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700462 of_ports = config["port_map"].keys()
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700463 of_ports.sort()
464 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
465
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700466 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700467 match = packet_to_flow_match(self, pkt)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700468 match.wildcards &= ~ofp.OFPFW_IN_PORT
469 self.assertTrue(match is not None,
470 "Could not generate flow match from pkt")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700471
472 for idx in range(len(of_ports)):
Rich Lane32bf9482013-01-03 17:26:30 -0800473 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700474
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700475 ingress_port = of_ports[idx]
476 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
477 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700478 logging.info("Ingress " + str(ingress_port) +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700479 " to egress " + str(egress_port1) + " and " +
480 str(egress_port2))
481
482 match.in_port = ingress_port
483
Rich Laneba3f0e22013-03-11 16:43:57 -0700484 request = ofp.message.flow_add()
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700485 request.match = match
486 request.buffer_id = 0xffffffff
Rich Lane62e96852013-03-11 12:04:45 -0700487 request.actions.append(ofp.action.output(port=egress_port1))
488 request.actions.append(ofp.action.output(port=egress_port2))
Rich Lane9a003812012-10-04 17:17:59 -0700489 # logging.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700490
Rich Lane9a003812012-10-04 17:17:59 -0700491 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800492 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800493 do_barrier(self.controller)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700494
Rich Lane9a003812012-10-04 17:17:59 -0700495 logging.info("Sending packet to dp port " +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700496 str(ingress_port))
497 self.dataplane.send(ingress_port, str(pkt))
Rich Lanee4b384d2013-09-13 14:33:40 -0700498 verify_packets(self, pkt, [egress_port1, egress_port2])
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700499
Rich Laneb90a1c42012-10-05 09:16:05 -0700500class DirectMCNonIngress(base_tests.SimpleDataPlane):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700501 """
502 Multicast to all non-ingress ports
503
504 Generate a packet
505 Generate and install a matching flow
506 Add action to direct the packet to all non-ingress ports
507 Send the packet to ingress dataplane port
508 Verify the packet is received at all non-ingress ports
509
510 Does not use the flood action
511 """
512 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700513 of_ports = config["port_map"].keys()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700514 of_ports.sort()
515 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
516
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700517 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700518 match = packet_to_flow_match(self, pkt)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700519 match.wildcards &= ~ofp.OFPFW_IN_PORT
520 self.assertTrue(match is not None,
521 "Could not generate flow match from pkt")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700522
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700523 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800524 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700525
Rich Lane9a003812012-10-04 17:17:59 -0700526 logging.info("Ingress " + str(ingress_port) +
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700527 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700528 match.in_port = ingress_port
529
Rich Laneba3f0e22013-03-11 16:43:57 -0700530 request = ofp.message.flow_add()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700531 request.match = match
532 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700533 for egress_port in of_ports:
534 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700535 continue
Rich Lane62e96852013-03-11 12:04:45 -0700536 request.actions.append(ofp.action.output(port=egress_port))
Rich Lane9a003812012-10-04 17:17:59 -0700537 logging.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700538
Rich Lane9a003812012-10-04 17:17:59 -0700539 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800540 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800541 do_barrier(self.controller)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700542
Rich Lane9a003812012-10-04 17:17:59 -0700543 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700544 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700545 yes_ports = set(of_ports).difference([ingress_port])
Rich Lanee4b384d2013-09-13 14:33:40 -0700546 verify_packets(self, pkt, yes_ports)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700547
Dan Talayco32fa6542010-05-11 15:54:08 -0700548
Rich Laneb90a1c42012-10-05 09:16:05 -0700549class DirectMC(base_tests.SimpleDataPlane):
Dan Talayco32fa6542010-05-11 15:54:08 -0700550 """
551 Multicast to all ports including ingress
552
553 Generate a packet
554 Generate and install a matching flow
555 Add action to direct the packet to all non-ingress ports
556 Send the packet to ingress dataplane port
557 Verify the packet is received at all ports
558
559 Does not use the flood action
560 """
561 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700562 of_ports = config["port_map"].keys()
Dan Talayco32fa6542010-05-11 15:54:08 -0700563 of_ports.sort()
564 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
565
Dan Talayco32fa6542010-05-11 15:54:08 -0700566 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700567 match = packet_to_flow_match(self, pkt)
Dan Talayco32fa6542010-05-11 15:54:08 -0700568 match.wildcards &= ~ofp.OFPFW_IN_PORT
569 self.assertTrue(match is not None,
570 "Could not generate flow match from pkt")
Dan Talayco32fa6542010-05-11 15:54:08 -0700571
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700572 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800573 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700574
Rich Lane9a003812012-10-04 17:17:59 -0700575 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700576 match.in_port = ingress_port
577
Rich Laneba3f0e22013-03-11 16:43:57 -0700578 request = ofp.message.flow_add()
Dan Talayco32fa6542010-05-11 15:54:08 -0700579 request.match = match
580 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700581 for egress_port in of_ports:
Rich Lane62e96852013-03-11 12:04:45 -0700582 act = ofp.action.output()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700583 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700584 act.port = ofp.OFPP_IN_PORT
585 else:
586 act.port = egress_port
Rich Lanec495d9e2013-03-08 17:43:36 -0800587 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -0700588 # logging.info(request.show())
Dan Talayco2e77a842010-05-12 15:39:46 -0700589
Rich Lane9a003812012-10-04 17:17:59 -0700590 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800591 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800592 do_barrier(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700593
Rich Lane9a003812012-10-04 17:17:59 -0700594 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700595 self.dataplane.send(ingress_port, str(pkt))
Rich Lanee4b384d2013-09-13 14:33:40 -0700596 verify_packets(self, pkt, of_ports)
Dan Talayco2e77a842010-05-12 15:39:46 -0700597
Rich Laneb90a1c42012-10-05 09:16:05 -0700598class Flood(base_tests.SimpleDataPlane):
Dan Talayco2e77a842010-05-12 15:39:46 -0700599 """
600 Flood to all ports except ingress
601
Dan Talaycofcc09912013-02-08 23:46:08 -0800602 Make sure noflood bit is off on all ports
Dan Talayco2e77a842010-05-12 15:39:46 -0700603 Generate a packet
604 Generate and install a matching flow
605 Add action to flood the packet
606 Send the packet to ingress dataplane port
607 Verify the packet is received at all other ports
608 """
609 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700610 of_ports = config["port_map"].keys()
Dan Talayco2e77a842010-05-12 15:39:46 -0700611 of_ports.sort()
612 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
613
614 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700615 match = packet_to_flow_match(self, pkt)
Dan Talayco2e77a842010-05-12 15:39:46 -0700616 match.wildcards &= ~ofp.OFPFW_IN_PORT
617 self.assertTrue(match is not None,
618 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800619 act = ofp.action.output()
Dan Talayco2e77a842010-05-12 15:39:46 -0700620
Dan Talaycofcc09912013-02-08 23:46:08 -0800621 for of_port in of_ports:
622 # Clear relevant bits that might block ports
623 rv = port_config_set(self.controller, of_port, 0,
624 ofp.OFPPC_NO_FLOOD | ofp.OFPPC_NO_FWD |
625 ofp.OFPPC_PORT_DOWN)
626 self.assertTrue(rv == 0, "Did not set port config")
627 logging.debug("Enabled and cleared no-flood for port " + str(of_port))
628
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700629 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800630 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700631
Rich Lane9a003812012-10-04 17:17:59 -0700632 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700633 match.in_port = ingress_port
634
Rich Laneba3f0e22013-03-11 16:43:57 -0700635 request = ofp.message.flow_add()
Dan Talayco2e77a842010-05-12 15:39:46 -0700636 request.match = match
637 request.buffer_id = 0xffffffff
638 act.port = ofp.OFPP_FLOOD
Rich Lanec495d9e2013-03-08 17:43:36 -0800639 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -0700640 logging.info(request.show())
Dan Talayco32fa6542010-05-11 15:54:08 -0700641
Rich Lane9a003812012-10-04 17:17:59 -0700642 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800643 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800644 do_barrier(self.controller)
Dan Talayco32fa6542010-05-11 15:54:08 -0700645
Rich Lane9a003812012-10-04 17:17:59 -0700646 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco32fa6542010-05-11 15:54:08 -0700647 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700648 yes_ports = set(of_ports).difference([ingress_port])
Rich Lanee4b384d2013-09-13 14:33:40 -0700649 verify_packets(self, pkt, yes_ports)
Dan Talayco3be5b062010-05-12 15:46:21 -0700650
Rich Laneb90a1c42012-10-05 09:16:05 -0700651class FloodPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco3be5b062010-05-12 15:46:21 -0700652 """
653 Flood to all ports plus send to ingress port
654
655 Generate a packet
656 Generate and install a matching flow
657 Add action to flood the packet
658 Add action to send to ingress port
659 Send the packet to ingress dataplane port
660 Verify the packet is received at all other ports
661 """
662 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700663 of_ports = config["port_map"].keys()
Dan Talayco3be5b062010-05-12 15:46:21 -0700664 of_ports.sort()
665 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
666
667 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700668 match = packet_to_flow_match(self, pkt)
Dan Talayco3be5b062010-05-12 15:46:21 -0700669 match.wildcards &= ~ofp.OFPFW_IN_PORT
670 self.assertTrue(match is not None,
671 "Could not generate flow match from pkt")
Dan Talayco3be5b062010-05-12 15:46:21 -0700672
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700673 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800674 delete_all_flows(self.controller)
Dan Talayco3be5b062010-05-12 15:46:21 -0700675
Rich Lane9a003812012-10-04 17:17:59 -0700676 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700677 match.in_port = ingress_port
678
Rich Laneba3f0e22013-03-11 16:43:57 -0700679 request = ofp.message.flow_add()
Dan Talayco3be5b062010-05-12 15:46:21 -0700680 request.match = match
681 request.buffer_id = 0xffffffff
Rich Lane62e96852013-03-11 12:04:45 -0700682 request.actions.append(ofp.action.output(port=ofp.OFPP_FLOOD))
683 request.actions.append(ofp.action.output(port=ofp.OFPP_IN_PORT))
Rich Lane9a003812012-10-04 17:17:59 -0700684 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700685
Rich Lane9a003812012-10-04 17:17:59 -0700686 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800687 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800688 do_barrier(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700689
Rich Lane9a003812012-10-04 17:17:59 -0700690 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700691 self.dataplane.send(ingress_port, str(pkt))
Rich Lanee4b384d2013-09-13 14:33:40 -0700692 verify_packets(self, pkt, of_ports)
Dan Talayco4aa13122010-05-12 15:54:44 -0700693
Rich Laneb90a1c42012-10-05 09:16:05 -0700694class All(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700695 """
696 Send to OFPP_ALL port
697
698 Generate a packet
699 Generate and install a matching flow
700 Add action to forward to OFPP_ALL
701 Send the packet to ingress dataplane port
702 Verify the packet is received at all other ports
703 """
704 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700705 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700706 of_ports.sort()
707 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
708
709 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700710 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700711 match.wildcards &= ~ofp.OFPFW_IN_PORT
712 self.assertTrue(match is not None,
713 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800714 act = ofp.action.output()
Dan Talayco4aa13122010-05-12 15:54:44 -0700715
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700716 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800717 delete_all_flows(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700718
Rich Lane9a003812012-10-04 17:17:59 -0700719 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700720 match.in_port = ingress_port
721
Rich Laneba3f0e22013-03-11 16:43:57 -0700722 request = ofp.message.flow_add()
Dan Talayco4aa13122010-05-12 15:54:44 -0700723 request.match = match
724 request.buffer_id = 0xffffffff
725 act.port = ofp.OFPP_ALL
Rich Lanec495d9e2013-03-08 17:43:36 -0800726 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -0700727 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700728
Rich Lane9a003812012-10-04 17:17:59 -0700729 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800730 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800731 do_barrier(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700732
Rich Lane9a003812012-10-04 17:17:59 -0700733 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700734 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700735 yes_ports = set(of_ports).difference([ingress_port])
Rich Lanee4b384d2013-09-13 14:33:40 -0700736 verify_packets(self, pkt, yes_ports)
Dan Talayco4aa13122010-05-12 15:54:44 -0700737
Rich Laneb90a1c42012-10-05 09:16:05 -0700738class AllPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700739 """
740 Send to OFPP_ALL port and ingress port
741
742 Generate a packet
743 Generate and install a matching flow
744 Add action to forward to OFPP_ALL
745 Add action to forward to ingress port
746 Send the packet to ingress dataplane port
747 Verify the packet is received at all other ports
748 """
749 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700750 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700751 of_ports.sort()
752 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
753
754 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700755 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700756 match.wildcards &= ~ofp.OFPFW_IN_PORT
757 self.assertTrue(match is not None,
758 "Could not generate flow match from pkt")
Dan Talayco4aa13122010-05-12 15:54:44 -0700759
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700760 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800761 delete_all_flows(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700762
Rich Lane9a003812012-10-04 17:17:59 -0700763 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700764 match.in_port = ingress_port
765
Rich Laneba3f0e22013-03-11 16:43:57 -0700766 request = ofp.message.flow_add()
Dan Talayco4aa13122010-05-12 15:54:44 -0700767 request.match = match
768 request.buffer_id = 0xffffffff
Rich Lane62e96852013-03-11 12:04:45 -0700769 request.actions.append(ofp.action.output(port=ofp.OFPP_ALL))
770 request.actions.append(ofp.action.output(port=ofp.OFPP_IN_PORT))
Rich Lane9a003812012-10-04 17:17:59 -0700771 logging.info(request.show())
Dan Talayco3be5b062010-05-12 15:46:21 -0700772
Rich Lane9a003812012-10-04 17:17:59 -0700773 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800774 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800775 do_barrier(self.controller)
Dan Talayco3be5b062010-05-12 15:46:21 -0700776
Rich Lane9a003812012-10-04 17:17:59 -0700777 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco3be5b062010-05-12 15:46:21 -0700778 self.dataplane.send(ingress_port, str(pkt))
Rich Lanee4b384d2013-09-13 14:33:40 -0700779 verify_packets(self, pkt, of_ports)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700780
Rich Laneb90a1c42012-10-05 09:16:05 -0700781class FloodMinusPort(base_tests.SimpleDataPlane):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700782 """
783 Config port with No_Flood and test Flood action
784
785 Generate a packet
786 Generate a matching flow
787 Add action to forward to OFPP_ALL
788 Set port to no-flood
789 Send the packet to ingress dataplane port
790 Verify the packet is received at all other ports except
791 the ingress port and the no_flood port
792 """
793 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700794 of_ports = config["port_map"].keys()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700795 of_ports.sort()
796 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
797
798 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700799 match = packet_to_flow_match(self, pkt)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700800 match.wildcards &= ~ofp.OFPFW_IN_PORT
801 self.assertTrue(match is not None,
802 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800803 act = ofp.action.output()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700804
Rich Lane4b9e38c2012-12-06 16:33:20 -0800805 # Clear OFPPC_NO_FLOOD on each port
806 for of_port in of_ports:
807 rv = port_config_set(self.controller, of_port,
808 0, ofp.OFPPC_NO_FLOOD)
809 self.assertEqual(rv, 0, "Failed to set port config")
810
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700811 for idx in range(len(of_ports)):
Rich Lane32bf9482013-01-03 17:26:30 -0800812 delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700813
814 ingress_port = of_ports[idx]
815 no_flood_idx = (idx + 1) % len(of_ports)
816 no_flood_port = of_ports[no_flood_idx]
817 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700818 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700819 self.assertEqual(rv, 0, "Failed to set port config")
820
821 match.in_port = ingress_port
822
Rich Laneba3f0e22013-03-11 16:43:57 -0700823 request = ofp.message.flow_add()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700824 request.match = match
825 request.buffer_id = 0xffffffff
826 act.port = ofp.OFPP_FLOOD
Rich Lanec495d9e2013-03-08 17:43:36 -0800827 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -0700828 logging.info(request.show())
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700829
Rich Lane9a003812012-10-04 17:17:59 -0700830 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800831 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800832 do_barrier(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700833
Rich Lane9a003812012-10-04 17:17:59 -0700834 logging.info("Sending packet to dp port " + str(ingress_port))
835 logging.info("No flood port is " + str(no_flood_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700836 self.dataplane.send(ingress_port, str(pkt))
837 no_ports = set([ingress_port, no_flood_port])
838 yes_ports = set(of_ports).difference(no_ports)
Rich Lanee4b384d2013-09-13 14:33:40 -0700839 verify_packets(self, pkt, yes_ports)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700840
841 # Turn no flood off again
842 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700843 0, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700844 self.assertEqual(rv, 0, "Failed to reset port config")
Rich Lane3a261d52013-01-03 17:45:08 -0800845 do_barrier(self.controller)
Rich Lane4ecc1f42012-12-06 16:35:24 -0800846
847 # Check that packets are now flooded to no_flood_port
848 logging.info("Sending packet to dp port " + str(ingress_port))
849 self.dataplane.send(ingress_port, str(pkt))
850 no_ports = set([ingress_port])
851 yes_ports = set(of_ports).difference(no_ports)
Rich Lanee4b384d2013-09-13 14:33:40 -0700852 verify_packets(self, pkt, yes_ports)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700853
854 #@todo Should check no other packets received
855
Dan Talayco21381562010-07-17 00:34:47 -0700856
857
Dan Talayco551befa2010-07-15 17:05:32 -0700858################################################################
859
Rich Laneb90a1c42012-10-05 09:16:05 -0700860class BaseMatchCase(base_tests.SimpleDataPlane):
Dan Talayco551befa2010-07-15 17:05:32 -0700861 def setUp(self):
Rich Laneb90a1c42012-10-05 09:16:05 -0700862 base_tests.SimpleDataPlane.setUp(self)
Dan Talayco551befa2010-07-15 17:05:32 -0700863 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -0700864 logging.info("BaseMatchCase")
Dan Talayco551befa2010-07-15 17:05:32 -0700865
866class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700867 """
Dan Talayco551befa2010-07-15 17:05:32 -0700868 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700869
870 Generate a packet
871 Generate and install a matching flow without wildcard mask
872 Add action to forward to a port
873 Send the packet to the port
874 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700875 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700876
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700877 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700878 flow_match_test(self, config["port_map"])
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700879
Dan Talayco551befa2010-07-15 17:05:32 -0700880class ExactMatchTagged(BaseMatchCase):
881 """
882 Exact match for all port pairs with tagged pkts
883 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700884
Dan Talayco551befa2010-07-15 17:05:32 -0700885 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -0700886 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Laned0478ff2013-03-11 12:46:58 -0700887 flow_match_test(self, config["port_map"], vlan_vid=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700888
Rich Lane0a4f6372013-01-02 14:40:22 -0800889@disabled
Dan Talayco551befa2010-07-15 17:05:32 -0700890class ExactMatchTaggedMany(BaseMatchCase):
891 """
892 ExactMatchTagged with many VLANS
893 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700894
Dan Talayco551befa2010-07-15 17:05:32 -0700895 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700896 for vid in range(2,100,10):
Rich Laned0478ff2013-03-11 12:46:58 -0700897 flow_match_test(self, config["port_map"], vlan_vid=vid, max_test=5)
Dan Talayco551befa2010-07-15 17:05:32 -0700898 for vid in range(100,4000,389):
Rich Laned0478ff2013-03-11 12:46:58 -0700899 flow_match_test(self, config["port_map"], vlan_vid=vid, max_test=5)
900 flow_match_test(self, config["port_map"], vlan_vid=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700901
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700902class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700903 """
904 SingleWildcardMatchPriority
905 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700906
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700907 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700908 self.pkt = simple_tcp_packet()
909 self.flowMsgs = {}
910
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700911 def _ClearTable(self):
Rich Lane32bf9482013-01-03 17:26:30 -0800912 delete_all_flows(self.controller)
Rich Lane3a261d52013-01-03 17:45:08 -0800913 do_barrier(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700914
915 def runTest(self):
916
917 self._Init()
Rich Lane477f4812012-10-04 22:49:00 -0700918 of_ports = config["port_map"].keys()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700919 of_ports.sort()
920
921 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700922 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700923
924 # Run several combinations, each at lower priority settings.
925 # At the end of each call to runPrioFlows(), the table should
926 # be empty. If its not, we'll catch it as the priorities decreases
927 portA = of_ports[0]
928 portB = of_ports[1]
929 portC = of_ports[2]
930
931 # TODO -- these priority numbers should be validated somehow?
932 self.runPrioFlows(portA, portB, portC, 1000, 999)
933 self.runPrioFlows(portB, portC, portA, 998, 997)
934 self.runPrioFlows(portC, portA, portB, 996, 995)
935 self.runPrioFlows(portA, portC, portB, 994, 993)
936
937
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700938
939 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
940 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700941
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700942 if clearTable:
943 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700944
945 # Sanity check flow at lower priority from pA to pB
Rich Lane9a003812012-10-04 17:17:59 -0700946 logging.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700947 % (portA, portB, portC, prioHigher, prioLower))
948
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700949 # Sanity check flow at lower priority from pA to pC
950 self.installFlow(prioLower, portA, portC)
951 self.verifyFlow(portA, portC)
952 self.removeFlow(prioLower)
953
954 # Install and verify pA->pB @ prioLower
955 self.installFlow(prioLower, portA, portB)
956 self.verifyFlow(portA, portB)
957
958 # Install and verify pA->pC @ prioHigher, should override pA->pB
959 self.installFlow(prioHigher, portA, portC)
960 self.verifyFlow(portA, portC)
961 # remove pA->pC
962 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700963 # Old flow pA -> pB @ prioLower should still be active
964 self.verifyFlow(portA, portB)
965 self.removeFlow(prioLower)
966
967 # Table should be empty at this point, leave it alone as
968 # an assumption for future test runs
969
970
971
Ed Swierk99a74de2012-08-22 06:40:54 -0700972 def installFlow(self, prio, inp, egp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700973 wildcards=ofp.OFPFW_DL_SRC):
Ed Swierk99a74de2012-08-22 06:40:54 -0700974 wildcards |= required_wildcards(self)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700975 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700976 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700977 egr_ports=egp)
978 request.priority = prio
Rich Lane9a003812012-10-04 17:17:59 -0700979 logging.debug("Install flow with priority " + str(prio))
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700980 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700981 self.flowMsgs[prio] = request
982
983 def removeFlow(self, prio):
984 if self.flowMsgs.has_key(prio):
Rich Laneba3f0e22013-03-11 16:43:57 -0700985 old_msg = self.flowMsgs[prio]
986 msg = ofp.message.flow_delete_strict(out_port=ofp.OFPP_NONE,
987 match=old_msg.match,
988 priority=old_msg.priority)
Rich Lane9a003812012-10-04 17:17:59 -0700989 logging.debug("Remove flow with priority " + str(prio))
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700990 self.controller.message_send(msg)
Rich Lane3a261d52013-01-03 17:45:08 -0800991 do_barrier(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700992 else:
993 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700994
995
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700996 def verifyFlow(self, inp, egp, pkt=None):
997 if pkt == None:
998 pkt = self.pkt
999
Rich Lane9a003812012-10-04 17:17:59 -07001000 logging.info("Pkt match test: " + str(inp) + " to " + str(egp))
1001 logging.debug("Send packet: " + str(inp) + " to " + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001002 self.dataplane.send(inp, str(pkt))
Rich Lanee4b384d2013-09-13 14:33:40 -07001003 verify_packets(self, pkt, [egp])
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001004
1005
1006
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001007class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
1008
1009 def runTest(self):
1010
1011 self._Init()
1012
Rich Lane477f4812012-10-04 22:49:00 -07001013 of_ports = config["port_map"].keys()
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001014 of_ports.sort()
1015
1016 # Install an entry from 0 -> 1 @ prio 1000
1017 self._ClearTable()
1018 self.installFlow(1000, of_ports[0], of_ports[1])
1019 self.verifyFlow(of_ports[0], of_ports[1])
1020 self.installFlow(1000, of_ports[1], of_ports[0])
1021 self.verifyFlow(of_ports[1], of_ports[0])
1022 self.installFlow(1001, of_ports[0], of_ports[1])
1023 self.verifyFlow(of_ports[0], of_ports[1])
1024 self.installFlow(1001, of_ports[1], of_ports[0])
1025 self.verifyFlow(of_ports[1], of_ports[0])
1026 self.removeFlow(1001)
1027 self.verifyFlow(of_ports[0], of_ports[1])
1028 self.removeFlow(1000)
1029
1030
1031
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001032class WildcardPriority(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001033 """
1034 1. Add wildcard flow, verify packet received.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001035 2. Add wildcard flow with higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001036 on port specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001037 3. Add wildcard flow with lower priority, verify packet received
Rich Laneb8392082012-11-21 15:52:54 -08001038 on port specified by the highest priority flow.
Ken Chiang38d7a152012-05-24 15:33:50 -07001039 """
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001040
1041 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001042
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001043 self._Init()
1044
Rich Lane477f4812012-10-04 22:49:00 -07001045 of_ports = config["port_map"].keys()
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001046 of_ports.sort()
1047
1048 self._ClearTable()
Ken Chiang38d7a152012-05-24 15:33:50 -07001049
1050 # Install a flow with wildcards
1051 self.installFlow(999, of_ports[0], of_ports[1],
1052 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001053 self.verifyFlow(of_ports[0], of_ports[1])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001054 # Install a flow with wildcards with higher priority
1055 self.installFlow(1000, of_ports[0], of_ports[2],
1056 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001057 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001058 # Install a flow with wildcards with lower priority
Rich Laneb8392082012-11-21 15:52:54 -08001059 self.installFlow(999, of_ports[0], of_ports[1],
1060 wildcards=ofp.OFPFW_DL_SRC)
Rich Lane0a78fbd2012-12-31 16:25:04 -08001061 self.verifyFlow(of_ports[0], of_ports[2])
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001062
1063
Rich Lane97e99652013-01-02 17:23:20 -08001064@group("smoke")
Ken Chiang3978f242012-06-13 14:14:09 -07001065class WildcardPriorityWithDelete(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001066 """
Rich Lane0a78fbd2012-12-31 16:25:04 -08001067 1. Add wildcard match flow, verify packet received.
Ken Chiang38d7a152012-05-24 15:33:50 -07001068 2. Add wildcard flow with higher priority, verify packet received on port
1069 specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001070 3. Add wildcard flow with even higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001071 on port specified by this flow.
1072 4. Delete lowest priority flow, verify packet received on port specified
1073 by highest priority flow.
1074 5. Delete highest priority flow, verify packet received on port specified
1075 by remaining flow.
1076 """
1077
1078 def runTest(self):
1079
1080 self._Init()
1081
Rich Lane477f4812012-10-04 22:49:00 -07001082 of_ports = config["port_map"].keys()
Ken Chiang38d7a152012-05-24 15:33:50 -07001083 of_ports.sort()
1084
1085 self._ClearTable()
1086
Rich Lane0a78fbd2012-12-31 16:25:04 -08001087 # Install a flow with wildcards
1088 self.installFlow(250, of_ports[0], of_ports[1],
1089 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001090 self.verifyFlow(of_ports[0], of_ports[1])
1091 # Install a flow with wildcards of higher priority
1092 self.installFlow(1250, of_ports[0], of_ports[2],
1093 wildcards=ofp.OFPFW_DL_DST)
1094 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001095 # Install a flow with wildcards with even higher priority
1096 self.installFlow(2001, of_ports[0], of_ports[3],
1097 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001098 self.verifyFlow(of_ports[0], of_ports[3])
1099 # Delete lowest priority flow
1100 self.removeFlow(250)
1101 self.verifyFlow(of_ports[0], of_ports[3])
1102 # Delete highest priority flow
1103 self.removeFlow(2001)
1104 self.verifyFlow(of_ports[0], of_ports[2])
1105
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001106
Dan Talayco551befa2010-07-15 17:05:32 -07001107class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001108 """
1109 Exercise wildcard matching for all ports
1110
1111 Generate a packet
1112 Generate and install a matching flow with wildcard mask
1113 Add action to forward to a port
1114 Send the packet to the port
1115 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001116 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001117 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001118 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001119 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001120 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001121 wc |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001122 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001123 # Set nonzero VLAN id to avoid sending priority-tagged packet
Rich Laned0478ff2013-03-11 12:46:58 -07001124 vlan_vid = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001125 else:
Rich Laned0478ff2013-03-11 12:46:58 -07001126 vlan_vid = -1
Rich Lane477f4812012-10-04 22:49:00 -07001127 flow_match_test(self, config["port_map"], wildcards=wc,
Rich Laned0478ff2013-03-11 12:46:58 -07001128 vlan_vid=vlan_vid, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001129
Dan Talayco551befa2010-07-15 17:05:32 -07001130class SingleWildcardMatchTagged(BaseMatchCase):
1131 """
1132 SingleWildcardMatch with tagged packets
1133 """
1134 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001135 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001136 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001137 wc |= required_wildcards(self)
Rich Laned0478ff2013-03-11 12:46:58 -07001138 flow_match_test(self, config["port_map"], wildcards=wc, vlan_vid=vid,
Dan Talayco551befa2010-07-15 17:05:32 -07001139 max_test=10)
1140
1141class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001142 """
Dan Talayco80b54ed2010-07-13 09:48:35 -07001143 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001144
1145 Generate a packet
1146 Generate and install a matching flow with wildcard all except one filed
1147 Add action to forward to a port
1148 Send the packet to the port
1149 Verify the packet is received at all other ports (one port at a time)
1150 Verify flow_expiration message is correct when command option is set
1151 """
1152 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001153 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001154 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001155 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001156 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001157 # Set nonzero VLAN id to avoid sending priority-tagged packet
Rich Laned0478ff2013-03-11 12:46:58 -07001158 vlan_vid = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001159 else:
Rich Laned0478ff2013-03-11 12:46:58 -07001160 vlan_vid = -1
Rich Lane477f4812012-10-04 22:49:00 -07001161 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Rich Laned0478ff2013-03-11 12:46:58 -07001162 vlan_vid=vlan_vid)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001163
Dan Talayco551befa2010-07-15 17:05:32 -07001164class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1165 """
1166 Match one field with tagged packets
1167 """
1168 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001169 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001170 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001171 all_exp_one_wildcard |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001172 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Rich Laned0478ff2013-03-11 12:46:58 -07001173 vlan_vid=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001174
1175class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001176 """
1177 Create Wildcard-all flow and exercise for all ports
1178
1179 Generate a packet
1180 Generate and install a matching flow with wildcard-all
1181 Add action to forward to a port
1182 Send the packet to the port
1183 Verify the packet is received at all other ports (one port at a time)
1184 Verify flow_expiration message is correct when command option is set
1185 """
1186 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001187 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001188
Dan Talayco551befa2010-07-15 17:05:32 -07001189class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001190 """
Dan Talayco551befa2010-07-15 17:05:32 -07001191 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001192 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001193 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001194 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Lane477f4812012-10-04 22:49:00 -07001195 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL,
Rich Laned0478ff2013-03-11 12:46:58 -07001196 vlan_vid=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001197
Rich Lane97e99652013-01-02 17:23:20 -08001198@group('smoke')
Dan Talayco551befa2010-07-15 17:05:32 -07001199class AddVLANTag(BaseMatchCase):
1200 """
1201 Add a VLAN tag to an untagged packet
1202 """
1203 def runTest(self):
1204 new_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001205 sup_acts = self.supported_actions
Dan Talayco551befa2010-07-15 17:05:32 -07001206 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001207 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001208 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001209
Dan Talayco551befa2010-07-15 17:05:32 -07001210 len = 100
1211 len_w_vid = 104
1212 pkt = simple_tcp_packet(pktlen=len)
1213 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
Rich Laned0478ff2013-03-11 12:46:58 -07001214 vlan_vid=new_vid)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001215 vid_act = ofp.action.set_vlan_vid()
Dan Talayco551befa2010-07-15 17:05:32 -07001216 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001217
Rich Lane477f4812012-10-04 22:49:00 -07001218 flow_match_test(self, config["port_map"], pkt=pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001219 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001220
Rich Lane0a4f6372013-01-02 14:40:22 -08001221@disabled
Rich Laneb90a1c42012-10-05 09:16:05 -07001222class PacketOnly(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001223 """
1224 Just send a packet thru the switch
1225 """
Rich Laned1d9c282012-10-04 22:07:10 -07001226
Dan Talayco551befa2010-07-15 17:05:32 -07001227 def runTest(self):
1228 pkt = simple_tcp_packet()
Rich Lane477f4812012-10-04 22:49:00 -07001229 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001230 of_ports.sort()
1231 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001232 logging.info("Sending packet to " + str(ing_port))
1233 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001234 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001235
Rich Lane0a4f6372013-01-02 14:40:22 -08001236@disabled
Rich Laneb90a1c42012-10-05 09:16:05 -07001237class PacketOnlyTagged(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001238 """
1239 Just send a packet thru the switch
1240 """
Rich Laned1d9c282012-10-04 22:07:10 -07001241
Dan Talayco551befa2010-07-15 17:05:32 -07001242 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001243 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Laned0478ff2013-03-11 12:46:58 -07001244 pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=vid)
Rich Lane477f4812012-10-04 22:49:00 -07001245 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001246 of_ports.sort()
1247 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001248 logging.info("Sending packet to " + str(ing_port))
1249 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001250 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001251
Dan Talayco551befa2010-07-15 17:05:32 -07001252class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001253 """
1254 Modify the VLAN ID in the VLAN tag of a tagged packet
1255 """
Dan Talaycoaf669322012-09-12 22:51:22 -07001256 def setUp(self):
1257 BaseMatchCase.setUp(self)
1258 self.ing_port=False
1259
Dan Talayco551befa2010-07-15 17:05:32 -07001260 def runTest(self):
1261 old_vid = 2
1262 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001263 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001264 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001265 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001266 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001267
Rich Laned0478ff2013-03-11 12:46:58 -07001268 pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=old_vid)
1269 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=new_vid)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001270 vid_act = ofp.action.set_vlan_vid()
Dan Talayco551befa2010-07-15 17:05:32 -07001271 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001272
Rich Lane477f4812012-10-04 22:49:00 -07001273 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoaf669322012-09-12 22:51:22 -07001274 action_list=[vid_act], ing_port=self.ing_port)
1275
1276class ModifyVIDToIngress(ModifyVID):
1277 """
1278 Modify the VLAN ID in the VLAN tag of a tagged packet and send to
1279 ingress port
1280 """
1281 def setUp(self):
1282 BaseMatchCase.setUp(self)
1283 self.ing_port=True
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001284
Ken Chiange9a211d2012-04-20 14:52:11 -07001285class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1286 """
Rich Lane28fa9272013-03-08 16:00:25 -08001287 With vlan ID and priority wildcarded, perform SET_VLAN_VID ofp.action.
Ken Chiange9a211d2012-04-20 14:52:11 -07001288 The same flow should match on both untagged and tagged packets.
1289 """
1290 def runTest(self):
1291 old_vid = 2
1292 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001293 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001294 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1295 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1296 return
1297
Rich Lane477f4812012-10-04 22:49:00 -07001298 of_ports = config["port_map"].keys()
Ken Chiange9a211d2012-04-20 14:52:11 -07001299 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1300 ing_port = of_ports[0]
Rich Lanee4b384d2013-09-13 14:33:40 -07001301 egress_port = of_ports[1]
Ken Chiange9a211d2012-04-20 14:52:11 -07001302
Rich Lane32bf9482013-01-03 17:26:30 -08001303 delete_all_flows(self.controller)
Ken Chiange9a211d2012-04-20 14:52:11 -07001304
1305 len_untagged = 100
1306 len_w_vid = 104
1307 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1308 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
Rich Laned0478ff2013-03-11 12:46:58 -07001309 dl_vlan_enable=True, vlan_vid=old_vid)
Ken Chiange9a211d2012-04-20 14:52:11 -07001310 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
Rich Laned0478ff2013-03-11 12:46:58 -07001311 vlan_vid=new_vid)
Ed Swierk99a74de2012-08-22 06:40:54 -07001312 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1313 ofp.OFPFW_DL_VLAN_PCP)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001314 vid_act = ofp.action.set_vlan_vid()
Ken Chiange9a211d2012-04-20 14:52:11 -07001315 vid_act.vlan_vid = new_vid
1316 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
Rich Lanee4b384d2013-09-13 14:33:40 -07001317 wildcards=wildcards, egr_ports=egress_port,
Ken Chiange9a211d2012-04-20 14:52:11 -07001318 action_list=[vid_act])
1319 flow_msg_install(self, request)
1320
Rich Lane9a003812012-10-04 17:17:59 -07001321 logging.debug("Send untagged packet: " + str(ing_port) + " to " +
Rich Lanee4b384d2013-09-13 14:33:40 -07001322 str(egress_port))
Ken Chiange9a211d2012-04-20 14:52:11 -07001323 self.dataplane.send(ing_port, str(untagged_pkt))
Rich Lanee4b384d2013-09-13 14:33:40 -07001324 verify_packets(self, exp_pkt, [egress_port])
Ken Chiange9a211d2012-04-20 14:52:11 -07001325
Rich Lane9a003812012-10-04 17:17:59 -07001326 logging.debug("Send tagged packet: " + str(ing_port) + " to " +
Rich Lanee4b384d2013-09-13 14:33:40 -07001327 str(egress_port))
Ken Chiange9a211d2012-04-20 14:52:11 -07001328 self.dataplane.send(ing_port, str(tagged_pkt))
Rich Lanee4b384d2013-09-13 14:33:40 -07001329 verify_packets(self, exp_pkt, [egress_port])
Ken Chiange9a211d2012-04-20 14:52:11 -07001330
Howard Pershc1199d52012-04-11 14:21:32 -07001331class ModifyVlanPcp(BaseMatchCase):
1332 """
1333 Modify the priority field of the VLAN tag of a tagged packet
1334 """
1335 def runTest(self):
1336 vid = 123
1337 old_vlan_pcp = 2
1338 new_vlan_pcp = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001339 sup_acts = self.supported_actions
Ed Swierk8c3af7f2012-04-24 14:19:17 -07001340 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_PCP):
1341 skip_message_emit(self, "Modify VLAN priority test")
Howard Pershc1199d52012-04-11 14:21:32 -07001342 return
1343
Rich Laned0478ff2013-03-11 12:46:58 -07001344 pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=vid, vlan_pcp=old_vlan_pcp)
1345 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=vid, vlan_pcp=new_vlan_pcp)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001346 vid_act = ofp.action.set_vlan_pcp()
Howard Pershc1199d52012-04-11 14:21:32 -07001347 vid_act.vlan_pcp = new_vlan_pcp
1348
Rich Lane477f4812012-10-04 22:49:00 -07001349 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Howard Pershc1199d52012-04-11 14:21:32 -07001350 action_list=[vid_act])
1351
Dan Talayco551befa2010-07-15 17:05:32 -07001352class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001353 """
1354 Strip the VLAN tag from a tagged packet
1355 """
Dan Talayco551befa2010-07-15 17:05:32 -07001356 def runTest(self):
1357 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001358 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001359 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001360 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001361 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001362
Dan Talayco551befa2010-07-15 17:05:32 -07001363 len_w_vid = 104
1364 len = 100
1365 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
Rich Laned0478ff2013-03-11 12:46:58 -07001366 vlan_vid=old_vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001367 exp_pkt = simple_tcp_packet(pktlen=len)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001368 vid_act = ofp.action.strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001369
Rich Lane477f4812012-10-04 22:49:00 -07001370 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001371 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001372
Ken Chiange9a211d2012-04-20 14:52:11 -07001373class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1374 """
1375 Strip the VLAN tag from a tagged packet.
1376 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1377 """
1378 def runTest(self):
1379 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001380 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001381 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1382 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1383 return
1384
1385 len_w_vid = 104
1386 len_untagged = 100
1387 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
Rich Laned0478ff2013-03-11 12:46:58 -07001388 vlan_vid=old_vid)
Ken Chiange9a211d2012-04-20 14:52:11 -07001389 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
Ed Swierk99a74de2012-08-22 06:40:54 -07001390 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1391 ofp.OFPFW_DL_VLAN_PCP)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001392 vid_act = ofp.action.strip_vlan()
Ken Chiange9a211d2012-04-20 14:52:11 -07001393
Rich Lane477f4812012-10-04 22:49:00 -07001394 flow_match_test(self, config["port_map"],
Ed Swierk99a74de2012-08-22 06:40:54 -07001395 wildcards=wildcards,
Ken Chiange9a211d2012-04-20 14:52:11 -07001396 pkt=pkt, exp_pkt=exp_pkt,
1397 action_list=[vid_act])
1398
Dan Talayco4b2bee62010-07-20 14:10:05 -07001399def init_pkt_args():
1400 """
1401 Pass back a dictionary with default packet arguments
1402 """
1403 args = {}
Rich Laned0478ff2013-03-11 12:46:58 -07001404 args["eth_src"] = '00:23:45:67:89:AB'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001405
1406 dl_vlan_enable=False
Rich Laned0478ff2013-03-11 12:46:58 -07001407 vlan_vid=-1
Rich Lane477f4812012-10-04 22:49:00 -07001408 if config["test-params"]["vid"]:
Dan Talayco4b2bee62010-07-20 14:10:05 -07001409 dl_vlan_enable=True
Rich Laned0478ff2013-03-11 12:46:58 -07001410 vlan_vid = config["test-params"]["vid"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001411
1412# Unpack operator is ** on a dictionary
1413
1414 return args
1415
Dan Talayco551befa2010-07-15 17:05:32 -07001416class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001417 """
1418 Modify the source MAC address (TP1)
1419 """
Dan Talayco551befa2010-07-15 17:05:32 -07001420 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001421 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001422 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001423 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001424 return
1425
Rich Laned0478ff2013-03-11 12:46:58 -07001426 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_src'],
Dan Talayco4b2bee62010-07-20 14:10:05 -07001427 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001428 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001429 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001430
Dan Talayco551befa2010-07-15 17:05:32 -07001431class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001432 """
1433 Modify the dest MAC address (TP1)
1434 """
Dan Talayco551befa2010-07-15 17:05:32 -07001435 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001436 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001437 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001438 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001439 return
1440
Rich Laned0478ff2013-03-11 12:46:58 -07001441 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_dst'],
Dan Talayco4b2bee62010-07-20 14:10:05 -07001442 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001443 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001444 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001445
Dan Talayco551befa2010-07-15 17:05:32 -07001446class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001447 """
1448 Modify the source IP address of an IP packet (TP1)
1449 """
Dan Talayco551befa2010-07-15 17:05:32 -07001450 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001451 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001452 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001453 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001454 return
1455
1456 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1457 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001458 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001459 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001460
Dan Talayco551befa2010-07-15 17:05:32 -07001461class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001462 """
1463 Modify the dest IP address of an IP packet (TP1)
1464 """
Dan Talayco551befa2010-07-15 17:05:32 -07001465 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001466 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001467 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001468 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001469 return
1470
1471 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1472 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001473 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001474 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001475
1476class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001477 """
1478 Modify the source TCP port of a TCP packet (TP1)
1479 """
Dan Talayco551befa2010-07-15 17:05:32 -07001480 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001481 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001482 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001483 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001484 return
1485
1486 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1487 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001488 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001489 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001490
Rich Lane01c2b862012-10-26 16:26:25 -07001491class ModifyL4SrcUdp(BaseMatchCase):
1492 """
1493 Modify the source UDP port of a UDP packet
1494 """
1495 def runTest(self):
1496 sup_acts = self.supported_actions
1497 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1498 skip_message_emit(self, "ModifyL4SrcUdp test")
1499 return
1500
1501 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_sport'],
1502 check_test_params=True, tp="udp")
1503 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1504 action_list=acts, max_test=2)
1505
Dan Talayco551befa2010-07-15 17:05:32 -07001506class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001507 """
1508 Modify the dest TCP port of a TCP packet (TP1)
1509 """
Dan Talayco551befa2010-07-15 17:05:32 -07001510 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001511 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001512 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001513 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001514 return
1515
1516 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1517 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001518 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001519 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001520
Rich Lane01c2b862012-10-26 16:26:25 -07001521class ModifyL4DstUdp(BaseMatchCase):
1522 """
1523 Modify the dest UDP port of a UDP packet
1524 """
1525 def runTest(self):
1526 sup_acts = self.supported_actions
1527 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1528 skip_message_emit(self, "ModifyL4DstUdp test")
1529 return
1530
1531 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_dport'],
1532 check_test_params=True, tp="udp")
1533 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1534 action_list=acts, max_test=2)
1535
Dan Talayco551befa2010-07-15 17:05:32 -07001536class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001537 """
1538 Modify the IP type of service of an IP packet (TP1)
1539 """
Dan Talayco551befa2010-07-15 17:05:32 -07001540 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001541 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001542 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001543 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001544 return
Dan Talayco551befa2010-07-15 17:05:32 -07001545
Dan Talayco4b2bee62010-07-20 14:10:05 -07001546 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1547 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001548 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001549 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001550
Dan Talaycof6e76c02012-03-23 10:56:12 -07001551class ModifyL2DstMC(BaseMatchCase):
1552 """
1553 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001554 """
1555 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001556 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001557 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001558 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001559 return
1560
Rich Laned0478ff2013-03-11 12:46:58 -07001561 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_dst'],
Dan Talaycof6e76c02012-03-23 10:56:12 -07001562 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001563 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001564 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001565
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001566class ModifyL2DstIngress(BaseMatchCase):
1567 """
1568 Modify the L2 dest and send to the ingress port
1569 """
1570 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001571 sup_acts = self.supported_actions
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001572 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001573 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001574 return
1575
Rich Laned0478ff2013-03-11 12:46:58 -07001576 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_dst'],
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001577 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001578 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001579 action_list=acts, max_test=2, egr_count=0,
1580 ing_port=True)
1581
Dan Talaycod8ae7582012-03-23 12:24:56 -07001582class ModifyL2DstIngressMC(BaseMatchCase):
1583 """
1584 Modify the L2 dest and send to the ingress port
1585 """
1586 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001587 sup_acts = self.supported_actions
Dan Talaycod8ae7582012-03-23 12:24:56 -07001588 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1589 skip_message_emit(self, "ModifyL2dstMC test")
1590 return
1591
Rich Laned0478ff2013-03-11 12:46:58 -07001592 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_dst'],
Dan Talaycod8ae7582012-03-23 12:24:56 -07001593 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001594 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001595 action_list=acts, max_test=2, egr_count=-1,
1596 ing_port=True)
1597
Dan Talaycof6e76c02012-03-23 10:56:12 -07001598class ModifyL2SrcMC(BaseMatchCase):
1599 """
1600 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001601 """
1602 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001603 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001604 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001605 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001606 return
1607
Rich Laned0478ff2013-03-11 12:46:58 -07001608 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_src'],
Dan Talaycof6e76c02012-03-23 10:56:12 -07001609 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001610 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001611 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001612
1613class ModifyL2SrcDstMC(BaseMatchCase):
1614 """
1615 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001616 """
1617 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001618 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001619 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1620 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1621 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001622 return
1623
Rich Laned0478ff2013-03-11 12:46:58 -07001624 mod_fields = ['eth_dst', 'eth_src']
Dan Talaycof6e76c02012-03-23 10:56:12 -07001625 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
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)
1629
1630class ModifyL2DstVIDMC(BaseMatchCase):
1631 """
1632 Modify the L2 dest and send to 2 ports
1633 """
1634 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001635 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001636 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1637 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1638 skip_message_emit(self, "ModifyL2DstVIDMC test")
1639 return
1640
Rich Laned0478ff2013-03-11 12:46:58 -07001641 mod_fields = ['eth_dst', 'vlan_vid']
Dan Talaycocfa172f2012-03-23 12:03:00 -07001642 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1643 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1644 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001645 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001646 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001647
Rich Lane97e99652013-01-02 17:23:20 -08001648@group("smoke")
Rich Lane22e74c12012-11-12 15:06:06 -08001649class ModifyAll(BaseMatchCase):
1650 """
1651 Modify all supported fields and output to a port
1652 """
1653 def runTest(self):
1654 sup_acts = self.supported_actions
1655
1656 sup_map = {
Rich Laned0478ff2013-03-11 12:46:58 -07001657 "eth_dst" : ofp.OFPAT_SET_DL_DST,
1658 "eth_src" : ofp.OFPAT_SET_DL_SRC,
Rich Lane22e74c12012-11-12 15:06:06 -08001659 "dl_vlan_enable" : ofp.OFPAT_SET_VLAN_VID,
Rich Laned0478ff2013-03-11 12:46:58 -07001660 "vlan_vid" : ofp.OFPAT_SET_VLAN_VID,
1661 "vlan_pcp" : ofp.OFPAT_SET_VLAN_PCP,
Rich Lane22e74c12012-11-12 15:06:06 -08001662 "ip_src" : ofp.OFPAT_SET_NW_SRC,
1663 "ip_dst" : ofp.OFPAT_SET_NW_DST,
1664 "ip_tos" : ofp.OFPAT_SET_NW_TOS,
1665 "tcp_sport" : ofp.OFPAT_SET_TP_SRC,
1666 "tcp_dport" : ofp.OFPAT_SET_TP_DST,
1667 }
1668
1669 mod_fields = [field for (field, bit) in sup_map.items() if (sup_acts & 1 << bit)]
1670 random.shuffle(mod_fields)
1671 start_field_vals = { "dl_vlan_enable" : True }
1672 mod_field_vals = { "dl_vlan_enable" : True }
1673 logging.info("modifying fields: %s" % repr(mod_fields))
1674
1675 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1676 mod_fields=mod_fields,
1677 start_field_vals=start_field_vals,
1678 mod_field_vals=mod_field_vals,
1679 check_test_params=True)
1680 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1681 action_list=acts, max_test=2)
1682
Dan Talaycofa6454f2012-04-05 10:04:13 -07001683class FlowToggle(BaseMatchCase):
1684 """
1685 Add flows to the table and modify them repeatedly
Dan Talaycof7c41312012-07-23 12:53:19 -07001686
1687 This is done by using only "add" flow messages. Since the check overlap
1688 flag is not set, the switch is supposed to modify the existing flow if
1689 the match already exists.
1690
1691 Would probably be better to exercise more of the flow modify commands
1692 (add, modify, delete +/- strict).
Dan Talaycofa6454f2012-04-05 10:04:13 -07001693 """
1694 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001695 flow_count = test_param_get('ft_flow_count', default=20)
1696 iter_count = test_param_get('ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001697
Rich Lane9a003812012-10-04 17:17:59 -07001698 logging.info("Running flow toggle with %d flows, %d iterations" %
Dan Talaycofa6454f2012-04-05 10:04:13 -07001699 (flow_count, iter_count))
1700 acts = []
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001701 acts.append(ofp.action.output())
1702 acts.append(ofp.action.output())
Dan Talaycofa6454f2012-04-05 10:04:13 -07001703
Rich Lane477f4812012-10-04 22:49:00 -07001704 of_ports = config["port_map"].keys()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001705 if len(of_ports) < 3:
1706 self.assertTrue(False, "Too few ports for test")
1707
1708 for idx in range(2):
1709 acts[idx].port = of_ports[idx]
1710
1711 flows = []
1712 flows.append([])
1713 flows.append([])
1714
Ed Swierk99a74de2012-08-22 06:40:54 -07001715 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_SRC |
1716 ofp.OFPFW_DL_DST)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001717 # Create up the flows in an array
1718 for toggle in range(2):
1719 for f_idx in range(flow_count):
1720 pkt = simple_tcp_packet(tcp_sport=f_idx)
Rich Laneba3f0e22013-03-11 16:43:57 -07001721 msg = ofp.message.flow_add()
Ed Swierk99a74de2012-08-22 06:40:54 -07001722 match = packet_to_flow_match(self, pkt)
Shudong Zhou031373c2012-07-19 17:37:42 -07001723 match.in_port = of_ports[2]
Dan Talayco50be7672012-04-05 11:38:08 -07001724 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001725 msg.match = match
1726 msg.buffer_id = 0xffffffff
Rich Lanec495d9e2013-03-08 17:43:36 -08001727 msg.actions.append(acts[toggle])
Dan Talaycofa6454f2012-04-05 10:04:13 -07001728 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001729
1730 # Show two sample flows
Rich Lane9a003812012-10-04 17:17:59 -07001731 logging.debug(flows[0][0].show())
1732 logging.debug(flows[1][0].show())
Dan Talayco50be7672012-04-05 11:38:08 -07001733
Dan Talaycofa6454f2012-04-05 10:04:13 -07001734 # Install the first set of flows
1735 for f_idx in range(flow_count):
Rich Lane5c3151c2013-01-03 17:15:41 -08001736 self.controller.message_send(flows[0][f_idx])
Rich Lane3a261d52013-01-03 17:45:08 -08001737 do_barrier(self.controller)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001738
Rich Lane9a003812012-10-04 17:17:59 -07001739 logging.info("Installed %d flows" % flow_count)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001740
1741 # Repeatedly modify all the flows back and forth
1742 updates = 0
1743 # Report status about 5 times
1744 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001745 start = time.time()
1746 for iter_idx in range(iter_count):
1747 if not iter_idx % mod_val:
Rich Lane9a003812012-10-04 17:17:59 -07001748 logging.info("Flow Toggle: iter %d of %d. " %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001749 (iter_idx, iter_count) +
1750 "%d updates in %d secs" %
1751 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001752 for toggle in range(2):
1753 t_idx = 1 - toggle
1754 for f_idx in range(flow_count):
Rich Lane5c3151c2013-01-03 17:15:41 -08001755 self.controller.message_send(flows[t_idx][f_idx])
Dan Talaycofa6454f2012-04-05 10:04:13 -07001756 updates += 1
Rich Lane3a261d52013-01-03 17:45:08 -08001757 do_barrier(self.controller)
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001758
1759 end = time.time()
1760 divisor = end - start or (end - start + 1)
Rich Lane9a003812012-10-04 17:17:59 -07001761 logging.info("Flow toggle: %d iterations" % iter_count)
1762 logging.info(" %d flow mods in %d secs, %d mods/sec" %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001763 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001764
1765
Dan Talayco8a64e332012-03-28 14:53:20 -07001766# You can pick and choose these by commenting tests in or out
1767iter_classes = [
1768 basic.PacketIn,
1769 basic.PacketOut,
1770 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001771 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001772 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001773 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001774 AllWildcardMatch,
1775 AllWildcardMatchTagged,
1776 SingleWildcardMatch,
1777 SingleWildcardMatchTagged,
1778 ExactMatch,
1779 ExactMatchTagged,
1780 SingleWildcardMatch,
1781 ModifyL2Src,
1782 ModifyL2Dst,
1783 ModifyL2SrcMC,
1784 ModifyL2DstMC,
1785 ModifyL2SrcDstMC
1786 ]
1787
Rich Lane0a4f6372013-01-02 14:40:22 -08001788@disabled
Dan Talayco8a64e332012-03-28 14:53:20 -07001789class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001790 """
1791 Iterate over a bunch of test cases
1792
1793 The cases come from the list above
1794 """
1795
Dan Talayco8a64e332012-03-28 14:53:20 -07001796 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001797 count = test_param_get('iter_count', default=10)
Dan Talayco8a64e332012-03-28 14:53:20 -07001798 tests_done = 0
Rich Lane9a003812012-10-04 17:17:59 -07001799 logging.info("Running iteration test " + str(count) + " times")
Dan Talayco8a64e332012-03-28 14:53:20 -07001800 start = time.time()
1801 last = start
1802 for idx in range(count):
Rich Lane9a003812012-10-04 17:17:59 -07001803 logging.info("Iteration " + str(idx + 1))
Dan Talayco8a64e332012-03-28 14:53:20 -07001804 for cls in iter_classes:
1805 test = cls()
1806 test.inheritSetup(self)
1807 test.runTest()
1808 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001809 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001810 if time.time() - last > 60:
1811 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001812 logging.info(
Dan Talaycofa6454f2012-04-05 10:04:13 -07001813 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1814 (idx, count, tests_done, last - start) +
1815 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001816 stats = all_stats_get(self)
1817 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001818 logging.info("\nIterCases ran %d tests in %d seconds." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001819 (tests_done, last - start))
Rich Lane9a003812012-10-04 17:17:59 -07001820 logging.info(" flows: %d. packets: %d. bytes: %d" %
Dan Talayco8a64e332012-03-28 14:53:20 -07001821 (stats["flows"], stats["packets"], stats["bytes"]))
Rich Lane9a003812012-10-04 17:17:59 -07001822 logging.info(" active: %d. lookups: %d. matched %d." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001823 (stats["active"], stats["lookups"], stats["matched"]))
1824
Dan Talayco4b2bee62010-07-20 14:10:05 -07001825#@todo Need to implement tagged versions of the above tests
1826#
1827#@todo Implement a test case that strips tag 2, adds tag 3
1828# and modifies tag 4 to tag 5. Then verify (in addition) that
1829# tag 6 does not get modified.
1830
Rich Lane0a4f6372013-01-02 14:40:22 -08001831@disabled
Dan Talayco4b2bee62010-07-20 14:10:05 -07001832class MixedVLAN(BaseMatchCase):
1833 """
1834 Test mixture of VLAN tag actions
1835
1836 Strip tag 2 on port 1, send to port 2
1837 Add tag 3 on port 1, send to port 2
1838 Modify tag 4 to 5 on port 1, send to port 2
1839 All other traffic from port 1, send to port 3
1840 All traffic from port 2 sent to port 4
1841 Use exact matches with different packets for all mods
1842 Verify the following: (port, vid)
1843 (port 1, vid 2) => VLAN tag stripped, out port 2
1844 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1845 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1846 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1847 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1848 (port 2, no tag) => untagged packet out port 4
1849 (port 2, vid 2-6) => unmodified packet out port 4
1850
1851 Variation: Might try sending VID 5 to port 3 and check.
1852 If only VID 5 distinguishes pkt, this will fail on some platforms
1853 """
1854
Rich Lane97e99652013-01-02 17:23:20 -08001855@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -07001856class MatchEach(base_tests.SimpleDataPlane):
Rich Lane8d6ab272012-09-23 18:06:20 -07001857 """
1858 Check that each match field is actually matched on.
1859 Installs two flows that differ in one field. The flow that should not
1860 match has a higher priority, so if that field is ignored during matching
1861 the packet will be sent out the wrong port.
1862
1863 TODO test UDP, ARP, ICMP, etc.
1864 """
1865 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001866 of_ports = config["port_map"].keys()
Rich Lane8d6ab272012-09-23 18:06:20 -07001867 of_ports.sort()
1868 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1869
Rich Lane9a003812012-10-04 17:17:59 -07001870 delete_all_flows(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001871
Rich Laned0478ff2013-03-11 12:46:58 -07001872 pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2)
Rich Lane8d6ab272012-09-23 18:06:20 -07001873 ingress_port = of_ports[0]
1874 egress_port = of_ports[1]
1875
1876 def testField(field, mask):
Rich Lane9a003812012-10-04 17:17:59 -07001877 logging.info("Testing field %s" % field)
Rich Lane8d6ab272012-09-23 18:06:20 -07001878
1879 def addFlow(matching, priority, output_port):
1880 match = packet_to_flow_match(self, pkt)
1881 self.assertTrue(match is not None, "Could not generate flow match from pkt")
1882 match.wildcards &= ~ofp.OFPFW_IN_PORT
1883 match.in_port = ingress_port
1884 if not matching:
1885 # Make sure flow doesn't match
1886 orig = getattr(match, field)
1887 if isinstance(orig, list):
1888 new = map(lambda a: ~a[0] & a[1], zip(orig, mask))
1889 else:
1890 new = ~orig & mask
1891 setattr(match, field, new)
Rich Laneba3f0e22013-03-11 16:43:57 -07001892 request = ofp.message.flow_add()
Rich Lane8d6ab272012-09-23 18:06:20 -07001893 request.match = match
1894 request.buffer_id = 0xffffffff
1895 request.priority = priority
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001896 act = ofp.action.output()
Rich Lane8d6ab272012-09-23 18:06:20 -07001897 act.port = output_port
Rich Lanec495d9e2013-03-08 17:43:36 -08001898 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -07001899 logging.info("Inserting flow")
Rich Lane8d6ab272012-09-23 18:06:20 -07001900 self.controller.message_send(request)
1901
1902 # This flow should match.
1903 addFlow(matching=True, priority=0, output_port=egress_port)
1904 # This flow should not match, but it has a higher priority.
1905 addFlow(matching=False, priority=1, output_port=ofp.OFPP_IN_PORT)
1906
Rich Lane3a261d52013-01-03 17:45:08 -08001907 do_barrier(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001908
Rich Lane9a003812012-10-04 17:17:59 -07001909 logging.info("Sending packet to dp port " + str(ingress_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001910 self.dataplane.send(ingress_port, str(pkt))
1911
1912 exp_pkt_arg = None
1913 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -07001914 if config["relax"]:
Rich Lane8d6ab272012-09-23 18:06:20 -07001915 exp_pkt_arg = pkt
1916 exp_port = egress_port
1917
1918 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
1919 exp_pkt=exp_pkt_arg)
1920 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -07001921 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001922 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
1923 self.assertEqual(str(pkt), str(rcv_pkt), 'Response packet does not match send packet')
1924
Ed Swierkb603b192012-12-12 15:38:49 -08001925 wildcards = required_wildcards(self)
Rich Lane8d6ab272012-09-23 18:06:20 -07001926 # TODO in_port
Ed Swierkb603b192012-12-12 15:38:49 -08001927 if not (wildcards & ofp.OFPFW_DL_SRC):
Rich Laned0478ff2013-03-11 12:46:58 -07001928 testField("eth_src", [0xff]*6)
Ed Swierkb603b192012-12-12 15:38:49 -08001929 if not (wildcards & ofp.OFPFW_DL_DST):
Rich Laned0478ff2013-03-11 12:46:58 -07001930 testField("eth_dst", [0xff]*6)
Ed Swierkb603b192012-12-12 15:38:49 -08001931 if not (wildcards & ofp.OFPFW_DL_TYPE):
Rich Laned0478ff2013-03-11 12:46:58 -07001932 testField("eth_type", 0xffff)
Ed Swierkb603b192012-12-12 15:38:49 -08001933 if not (wildcards & ofp.OFPFW_DL_VLAN):
Rich Laned0478ff2013-03-11 12:46:58 -07001934 testField("vlan_vid", 0xfff)
1935 # TODO vlan_pcp
Ed Swierkb603b192012-12-12 15:38:49 -08001936 if not (wildcards & ofp.OFPFW_NW_SRC_ALL):
Rich Laned0478ff2013-03-11 12:46:58 -07001937 testField("ipv4_src", 0xffffffff)
Ed Swierkb603b192012-12-12 15:38:49 -08001938 if not (wildcards & ofp.OFPFW_NW_DST_ALL):
Rich Laned0478ff2013-03-11 12:46:58 -07001939 testField("ipv4_dst", 0xffffffff)
Ed Swierkb603b192012-12-12 15:38:49 -08001940 if not (wildcards & ofp.OFPFW_NW_TOS):
Rich Laned0478ff2013-03-11 12:46:58 -07001941 testField("ip_dscp", 0x3f)
Ed Swierkb603b192012-12-12 15:38:49 -08001942 if not (wildcards & ofp.OFPFW_NW_PROTO):
Rich Laned0478ff2013-03-11 12:46:58 -07001943 testField("ip_proto", 0xff)
Ed Swierkb603b192012-12-12 15:38:49 -08001944 if not (wildcards & ofp.OFPFW_TP_SRC):
Rich Laned0478ff2013-03-11 12:46:58 -07001945 testField("tcp_src", 0xffff)
Ed Swierkb603b192012-12-12 15:38:49 -08001946 if not (wildcards & ofp.OFPFW_TP_DST):
Rich Laned0478ff2013-03-11 12:46:58 -07001947 testField("tcp_dst", 0xffff)
Rich Lane8d6ab272012-09-23 18:06:20 -07001948
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07001949class DirectBadPacketBase(base_tests.SimpleDataPlane):
1950 """
1951 Base class for sending single packets with single flow table entries.
1952 Used to verify matching of unusual packets and parsing/matching of
1953 corrupted packets.
1954
1955 The idea is to generate packets that may either be totally malformed or
1956 malformed just enough to trick the flow matcher into making mistakes.
1957
1958 Generate a 'bad' packet
1959 Generate and install a matching flow
1960 Add action to direct the packet to an egress port
1961 Send the packet to ingress dataplane port
1962 Verify the packet is received at the egress port only
1963 """
1964
1965 RESULT_MATCH = "MATCH"
1966 RESULT_NOMATCH = "NO MATCH"
1967 RESULT_ANY = "ANY MATCH"
1968
1969 def runTest(self):
1970 pass
1971 # TODO:
1972 # - ICMP?
1973 # - VLAN?
1974 # - action
1975
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07001976 def createMatch(self, **kwargs):
Rich Lane0237baf2013-03-11 22:34:59 -07001977 match = ofp.match()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07001978 match.wildcards = ofp.OFPFW_ALL
1979 fields = {
Rich Laned0478ff2013-03-11 12:46:58 -07001980 'eth_dst': ofp.OFPFW_DL_DST,
1981 'eth_src': ofp.OFPFW_DL_SRC,
1982 'eth_type': ofp.OFPFW_DL_TYPE,
1983 'vlan_vid': ofp.OFPFW_DL_VLAN,
1984 'ipv4_src': ofp.OFPFW_NW_SRC_MASK,
1985 'ipv4_dst': ofp.OFPFW_NW_DST_MASK,
1986 'ip_dscp': ofp.OFPFW_NW_TOS,
1987 'ip_proto': ofp.OFPFW_NW_PROTO,
1988 'tcp_src': ofp.OFPFW_TP_SRC,
1989 'tcp_dst': ofp.OFPFW_TP_DST,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07001990 }
1991 for key in kwargs:
1992 setattr(match, key, kwargs[key])
1993 match.wildcards &= ~fields[key]
1994 return match
1995
1996 def testPktsAgainstFlow(self, pkts, acts, match):
1997 if type(acts) != list:
1998 acts = [acts]
1999 for info in pkts:
2000 title, pkt, expected_result = info
2001 self.testPktAgainstFlow(title, pkt, acts, match, expected_result)
2002
2003 def testPktAgainstFlow(self, title, pkt, acts, match, expected_result):
2004 of_ports = config["port_map"].keys()
2005 of_ports.sort()
2006 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
2007
Rich Lane32bf9482013-01-03 17:26:30 -08002008 delete_all_flows(self.controller)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002009
2010 ingress_port = of_ports[0]
2011 egress_port = of_ports[1]
2012
2013 logging.info("Testing packet '%s', expect result %s" %
2014 (title, expected_result))
2015 logging.info("Ingress %s to egress %s" %
2016 (str(ingress_port), str(egress_port)))
2017 logging.info("Packet:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002018 logging.info(inspect_packet(pkt))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002019
2020 match.in_port = ingress_port
2021
Rich Laneba3f0e22013-03-11 16:43:57 -07002022 request = ofp.message.flow_add()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002023 request.match = match
Rich Lane44cf12d2012-10-15 11:10:45 -07002024 request.priority = 1
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002025
2026 request.buffer_id = 0xffffffff
2027 for act in acts:
2028 act.port = egress_port
Rich Lanec495d9e2013-03-08 17:43:36 -08002029 request.actions.append(act)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002030
2031 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08002032 self.controller.message_send(request)
Rich Lane44cf12d2012-10-15 11:10:45 -07002033
2034 # This flow speeds up negative tests
2035 logging.info("Inserting catch-all flow")
Rich Laneba3f0e22013-03-11 16:43:57 -07002036 request2 = ofp.message.flow_add()
Rich Lane44cf12d2012-10-15 11:10:45 -07002037 request2.match = self.createMatch()
Dan Talayco3bfc8222013-02-13 18:18:57 -08002038 request2.match.wildcards &= ~ofp.OFPFW_IN_PORT
2039 request2.match.in_port = ingress_port
2040
Rich Lane44cf12d2012-10-15 11:10:45 -07002041 request2.priority = 0
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002042 act = ofp.action.output()
Rich Lane44cf12d2012-10-15 11:10:45 -07002043 act.port = ofp.OFPP_IN_PORT
Rich Lanec495d9e2013-03-08 17:43:36 -08002044 request2.actions.append(act)
Rich Lane5c3151c2013-01-03 17:15:41 -08002045 self.controller.message_send(request2)
Rich Lane44cf12d2012-10-15 11:10:45 -07002046
Rich Lane3a261d52013-01-03 17:45:08 -08002047 do_barrier(self.controller)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002048
Dan Talayco3bfc8222013-02-13 18:18:57 -08002049 pkt_str = str(pkt)
2050 if config["minsize"] > len(str(pkt)):
2051 pkt_str += '0' * (config["minsize"] - len(str(pkt)))
2052
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002053 logging.info("Sending packet to dp port " +
2054 str(ingress_port))
Dan Talayco3bfc8222013-02-13 18:18:57 -08002055 self.dataplane.send(ingress_port, pkt_str)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002056
2057 exp_pkt_arg = None
2058 exp_port = None
2059 if config["relax"]:
2060 exp_pkt_arg = pkt
2061 exp_port = egress_port
2062
Rich Lane44cf12d2012-10-15 11:10:45 -07002063 if expected_result == self.RESULT_MATCH:
2064 timeout = -1 # default timeout
2065 else:
2066 timeout = 1 # short timeout for negative tests
2067
2068 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(exp_pkt=exp_pkt_arg,
2069 timeout=timeout)
2070 if rcv_port == ingress_port:
2071 logging.debug("Packet matched catch-all flow")
2072 rcv_pkt = None
2073
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002074 if expected_result == self.RESULT_MATCH:
2075 self.assertTrue(rcv_pkt is not None,
2076 "Did not receive packet, expected a match")
2077 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
2078 str(rcv_port))
2079 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
2080 str_pkt = str(pkt)
2081 str_rcv_pkt = str(rcv_pkt)
2082 str_rcv_pkt = str_rcv_pkt[0:len(str_pkt)]
2083 if str_pkt != str_rcv_pkt:
2084 logging.error("Response packet does not match send packet")
2085 logging.info("Response:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002086 logging.info(inspect_packet(scapy.Ether(rcv_pkt)))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002087 self.assertEqual(str_pkt, str_rcv_pkt,
2088 'Response packet does not match send packet')
2089 elif expected_result == self.RESULT_NOMATCH:
2090 self.assertTrue(rcv_pkt is None, "Received packet, expected drop")
2091 else:
2092 logging.debug("Match or drop accepted. Result = %s" %
2093 ("match" if rcv_pkt is not None else "drop"))
2094
2095
2096class DirectBadIpTcpPacketsBase(DirectBadPacketBase):
2097 """
2098 Base class for TCP and UDP parsing/matching verification under corruptions
2099 """
2100 def runTest(self):
2101 pass
2102
2103 def runTestWithProto(self, protoName = 'TCP'):
Rich Laned0478ff2013-03-11 12:46:58 -07002104 eth_dst='00:01:02:03:04:05'
2105 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002106 ip_src='192.168.0.1'
2107 ip_dst='192.168.0.2'
2108 ip_tos=0
2109 tcp_sport=1234
2110 tcp_dport=80
2111
2112 # Generate a proper packet for constructing a match
2113 tp = None
2114 if protoName == 'TCP':
2115 tp = scapy.TCP
2116 proto = 6
2117 elif protoName == 'UDP':
2118 tp = scapy.UDP
2119 proto = 17
2120 else:
2121 raise Exception("Passed in unknown proto name")
2122
Rich Laned0478ff2013-03-11 12:46:58 -07002123 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002124 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2125 tp(sport=tcp_sport, dport=tcp_dport)
2126 match = packet_to_flow_match(self, match_pkt)
2127 self.assertTrue(match is not None,
2128 "Could not generate flow match from pkt")
2129 match.wildcards &= ~ofp.OFPFW_IN_PORT
2130
2131 def testPacket(title, pkt, result):
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002132 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002133 pkts = [
2134 [title, pkt, result]
2135 ]
2136 self.testPktsAgainstFlow(pkts, act, match)
2137
2138 # Try incomplete IP headers
2139 testPacket("Incomplete IP header (1 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002140 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002141 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:1],
2142 self.RESULT_NOMATCH,
2143 )
2144 testPacket("Incomplete IP header (2 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002145 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002146 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:2],
2147 self.RESULT_NOMATCH,
2148 )
2149 testPacket("Incomplete IP header (3 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002150 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002151 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:3],
2152 self.RESULT_NOMATCH,
2153 )
2154 testPacket("Incomplete IP header (12 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002155 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002156 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:12],
2157 self.RESULT_NOMATCH,
2158 )
2159 testPacket("Incomplete IP header (16 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002160 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002161 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:16],
2162 self.RESULT_NOMATCH,
2163 )
2164 testPacket("Incomplete IP header (19 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002165 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002166 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:19],
2167 self.RESULT_NOMATCH,
2168 )
2169
2170 # Try variations where the TCP header is missing or incomplete. As we
2171 # saw bugs before where buffers were reused and lengths weren't honored,
2172 # we initiatlize once with a non-matching full packet and once with a
2173 # matching full packet.
2174 testPacket("Non-Matching TCP packet, warming buffer",
Rich Laned0478ff2013-03-11 12:46:58 -07002175 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002176 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2177 tp(sport=tcp_sport, dport=tcp_dport + 1),
2178 self.RESULT_NOMATCH,
2179 )
2180 testPacket("Missing TCP header, buffer warmed with non-match",
Rich Laned0478ff2013-03-11 12:46:58 -07002181 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002182 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2183 self.RESULT_NOMATCH,
2184 )
2185 testPacket("Matching TCP packet, warming buffer",
Rich Laned0478ff2013-03-11 12:46:58 -07002186 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002187 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2188 tp(sport=tcp_sport, dport=tcp_dport),
2189 self.RESULT_MATCH,
2190 )
2191 testPacket("Missing TCP header, buffer warmed with match",
Rich Laned0478ff2013-03-11 12:46:58 -07002192 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002193 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2194 self.RESULT_NOMATCH,
2195 )
2196 testPacket("Truncated TCP header: 2 bytes",
Rich Laned0478ff2013-03-11 12:46:58 -07002197 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002198 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2199 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:2]),
2200 self.RESULT_NOMATCH,
2201 )
2202
2203 # Play with IP header length values that put the start of TCP either
2204 # inside the generated TCP header or beyond. In some cases it may even
2205 # be beyond the packet boundary. Also play with IP options and more
2206 # importantly IP total length corruptions.
2207 testPacket("TCP packet, corrupt ihl (0x6)",
2208 simple_tcp_packet(ip_ihl=6),
2209 self.RESULT_NOMATCH,
2210 )
2211 testPacket("TCP packet, corrupt ihl (0xf)",
2212 simple_tcp_packet(ip_ihl=0xf), # ihl = 15 * 4 = 60
2213 self.RESULT_NOMATCH,
2214 )
2215 testPacket("TCP packet, corrupt ihl and total length",
2216 simple_tcp_packet(ip_ihl=0xf, pktlen=56), # ihl = 15 * 4 = 60,
2217 self.RESULT_NOMATCH,
2218 )
2219 testPacket("Corrupt IPoption: First 4 bytes of matching TCP header",
2220 simple_tcp_packet(
2221 ip_options=scapy.IPOption('\x04\xd2\x00\x50'),
2222 tcp_dport=2, tcp_sport=2
2223 ),
2224 self.RESULT_NOMATCH,
2225 )
2226 testPacket("Missing TCP header, corrupt ihl",
Rich Laned0478ff2013-03-11 12:46:58 -07002227 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002228 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto),
2229 self.RESULT_NOMATCH,
2230 )
2231 testPacket("Missing TCP header, corrupt total length",
Rich Laned0478ff2013-03-11 12:46:58 -07002232 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002233 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, len= 100),
2234 self.RESULT_NOMATCH,
2235 )
2236 testPacket("Missing TCP header, corrupt ihl and total length",
Rich Laned0478ff2013-03-11 12:46:58 -07002237 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002238 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto, len=43),
2239 self.RESULT_NOMATCH,
2240 )
2241 testPacket("Incomplete IP header (12 bytes), corrupt ihl and total length",
Rich Laned0478ff2013-03-11 12:46:58 -07002242 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002243 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:12],
2244 self.RESULT_NOMATCH,
2245 )
2246 testPacket("Incomplete IP header (16 bytes), corrupt ihl and total length",
Rich Laned0478ff2013-03-11 12:46:58 -07002247 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002248 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:16],
2249 self.RESULT_NOMATCH,
2250 )
2251
2252 # Try an incomplete TCP header that has enough bytes to carry source and
2253 # destination ports. As that is all we care about during matching, some
2254 # implementations may match and some may drop the packet
2255 testPacket("Incomplete TCP header: src/dst port present",
Rich Laned0478ff2013-03-11 12:46:58 -07002256 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002257 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2258 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:4]),
2259 self.RESULT_ANY,
2260 )
2261
2262 for i in range(1):
2263 for length in range(40 / 4): # IPv4 options are a maximum of 40 in length
2264 bytes = "".join([("%c" % random.randint(0, 255)) for x in range(length * 4)])
Rich Laned0478ff2013-03-11 12:46:58 -07002265 eth = scapy.Ether(dst=eth_dst, src=eth_src)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002266 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2267 tcp = tp(sport=tcp_sport, dport=tcp_dport+1)
2268 pkt = eth / ip
2269 pkt = pkt / bytes
2270 pkt = pkt / str(tcp)
2271 testPacket("Random IP options len = %d - TP match must fail" % length * 4,
2272 pkt,
2273 self.RESULT_NOMATCH
2274 )
2275
Rich Laned0478ff2013-03-11 12:46:58 -07002276 eth = scapy.Ether(dst=eth_dst, src=eth_src)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002277 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2278 tcp = tp(sport=tcp_sport, dport=tcp_dport)
2279 pkt = eth / ip
2280 pkt = pkt / bytes
2281 pkt = pkt / str(tcp)
2282
2283 testPacket("Random IP options len = %d - May match",
2284 pkt,
2285 self.RESULT_ANY
2286 )
2287
2288
2289class DirectBadIpTcpPackets(DirectBadIpTcpPacketsBase):
2290 """
2291 Verify IP/TCP parsing and matching. Focus on packet corruptions
2292 """
2293 def runTest(self):
2294 self.runTestWithProto(protoName = 'TCP')
2295
2296class DirectBadIpUdpPackets(DirectBadIpTcpPacketsBase):
2297 """
2298 Verify IP/UDP parsing and matching. Focus on packet corruptions
2299 """
2300 def runTest(self):
2301 self.runTestWithProto(protoName = 'UDP')
2302
2303class DirectBadLlcPackets(DirectBadPacketBase):
2304 """
2305 Verify LLC/SNAP parsing and matching. Focus on packet corruptions
2306 """
2307 def runTest(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002308 eth_dst='00:01:02:03:04:05'
2309 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002310 ip_src='192.168.0.1'
2311 ip_dst='192.168.0.2'
2312 ip_tos=0
2313 tcp_sport=1234
2314 tcp_dport=80
2315
2316 IS_SNAP_IP = 1
2317 IS_SNAP_IP_CORRUPT = 2
2318 IS_NOT_SNAP_IP = 3
2319
2320 def testPacketTcpMatch(title, llc):
Rich Laned0478ff2013-03-11 12:46:58 -07002321 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002322 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2323 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
2324 match = packet_to_flow_match(self, match_pkt)
2325 self.assertTrue(match is not None,
2326 "Could not generate flow match from pkt")
2327 match.wildcards &= ~ofp.OFPFW_IN_PORT
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002328 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002329
2330 self.testPktsAgainstFlow(
2331 [[
2332 "TCP match - LLC frame correct length - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002333 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002334 self.RESULT_ANY,
2335 ]],
2336 act, match
2337 )
2338
2339 # Corrupt length field
2340 ethLen = random.randint(0, 1535)
2341 self.testPktsAgainstFlow(
2342 [[
2343 "TCP match - LLC frame corrupted length - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002344 scapy.Ether(dst=eth_dst, src=eth_src, type=ethLen) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002345 self.RESULT_ANY,
2346 ]],
2347 act, match
2348 )
2349
2350 def testPacketEthSrcDstMatch(title, llc):
2351 # Matching based on Ethernet source and destination
Rich Laned0478ff2013-03-11 12:46:58 -07002352 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002353 match = packet_to_flow_match(self, match_pkt)
2354 self.assertTrue(match is not None,
2355 "Could not generate flow match from pkt")
2356 match.wildcards &= ~ofp.OFPFW_IN_PORT
2357 match.wildcards |= ofp.OFPFW_DL_TYPE
2358 self.testPktsAgainstFlow(
2359 [[
2360 "Eth addr match - LLC frame correct length- %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002361 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002362 self.RESULT_MATCH,
2363 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002364 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002365 )
2366
2367 # Corrupt length field
2368 ethLen = random.randint(0, 1535)
2369 self.testPktsAgainstFlow(
2370 [[
2371 "Eth addr match - LLC frame corrupted length- %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002372 scapy.Ether(dst=eth_dst, src=eth_src, type=ethLen) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002373 self.RESULT_ANY,
2374 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002375 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002376 )
2377
2378 def testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip):
2379 # Matching based on Ethernet source, destination and type
Rich Laned0478ff2013-03-11 12:46:58 -07002380 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=0x800)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002381 match = packet_to_flow_match(self, match_pkt)
2382 self.assertTrue(match is not None,
2383 "Could not generate flow match from pkt")
2384 match.wildcards &= ~ofp.OFPFW_IN_PORT
2385 if is_snap_ip == IS_SNAP_IP:
2386 is_match = self.RESULT_MATCH
2387 elif is_snap_ip == IS_SNAP_IP_CORRUPT:
2388 is_match = self.RESULT_ANY
2389 else:
2390 is_match = self.RESULT_NOMATCH
2391 self.testPktsAgainstFlow(
2392 [[
2393 "Eth addr+type match - LLC frame correct length - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002394 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002395 is_match,
2396 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002397 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002398 )
2399
2400 # Corrupt length field
2401 ethLen = random.randint(0, 1535)
2402 self.testPktsAgainstFlow(
2403 [[
2404 "Eth addr+type match - LLC frame corrupted length - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002405 scapy.Ether(dst=eth_dst, src=eth_src, type=ethLen) / llc,
Christian Dickmanne9b6d252012-10-08 22:56:50 -07002406 self.RESULT_ANY,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002407 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002408 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002409 )
2410
2411 def testPacket(title, llc, is_snap_ip):
2412 testPacketTcpMatch(title, llc)
2413 testPacketEthSrcDstMatch(title, llc)
2414 testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip)
2415
2416 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002417 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002418 IS_NOT_SNAP_IP,
2419 )
2420 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002421 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002422 IS_NOT_SNAP_IP,
2423 )
2424 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002425 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002426 IS_NOT_SNAP_IP,
2427 )
2428 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002429 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002430 IS_NOT_SNAP_IP,
2431 )
2432 testPacket("LLC - SNAP - Small bogus payload",
2433 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2434 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2435 IS_SNAP_IP_CORRUPT,
2436 )
2437 testPacket("LLC - SNAP - Max -1 bogus payload",
2438 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2439 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2440 IS_NOT_SNAP_IP,
2441 )
2442 testPacket("LLC - SNAP - Max bogus payload",
2443 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2444 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2445 IS_NOT_SNAP_IP,
2446 )
2447 testPacket("LLC - SNAP - IP - TCP",
2448 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2449 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2450 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2451 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2452 IS_SNAP_IP,
2453 )
2454
2455
2456class DirectLlcPackets(DirectBadPacketBase):
2457 """
2458 Verify LLC/SNAP parsing (valid and corrupted packets) and matching
2459 """
2460 def runTest(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002461 eth_dst='00:01:02:03:04:05'
2462 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002463 ip_src='192.168.0.1'
2464 ip_dst='192.168.0.2'
2465 ip_tos=0
2466 tcp_sport=1234
2467 tcp_dport=80
2468
2469 # Test ethertype in face of LLC/SNAP and OFP_DL_TYPE_NOT_ETH_TYPE
2470 IS_SNAP_NOT_IP = 1
2471 IS_SNAP_AND_IP = 2
2472 IS_NOT_SNAP = 3
2473
2474 def testPacketEthTypeIP(title, llc, is_snap):
Rich Laned0478ff2013-03-11 12:46:58 -07002475 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=0x800)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002476 match = packet_to_flow_match(self, match_pkt)
2477 self.assertTrue(match is not None,
2478 "Could not generate flow match from pkt")
2479 match.wildcards &= ~ofp.OFPFW_IN_PORT
2480 pkts = []
2481 if is_snap == IS_NOT_SNAP or is_snap == IS_SNAP_NOT_IP:
2482 result = self.RESULT_NOMATCH
2483 else:
2484 result = self.RESULT_MATCH
2485 pkts.append([
2486 "Ether type 0x800 match - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002487 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002488 result,
2489 ])
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002490 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002491 self.testPktsAgainstFlow(pkts, act, match)
2492
2493 def testPacketEthTypeNotEth(title, llc, is_snap):
Rich Laned0478ff2013-03-11 12:46:58 -07002494 match_pkt = scapy.Ether(dst = eth_dst, src = eth_src,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002495 type = ofp.OFP_DL_TYPE_NOT_ETH_TYPE)
2496 match = packet_to_flow_match(self, match_pkt)
2497 self.assertTrue(match is not None,
2498 "Could not generate flow match from pkt")
2499 match.wildcards &= ~ofp.OFPFW_IN_PORT
2500 pkts = []
2501 if is_snap == IS_NOT_SNAP:
2502 result = self.RESULT_MATCH
2503 else:
2504 result = self.RESULT_NOMATCH
2505 pkts.append([
2506 "Ether type OFP_DL_TYPE_NOT_ETH_TYPE match - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002507 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002508 result,
2509 ])
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002510 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002511 self.testPktsAgainstFlow(pkts, act, match)
2512
2513 def testPacket(title, llc, is_snap):
2514 testPacketEthTypeIP(title, llc, is_snap)
2515 testPacketEthTypeNotEth(title, llc, is_snap)
2516
2517 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002518 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
2519 IS_NOT_SNAP,
2520 )
2521 testPacket("LLC (with information field) - No SNAP - No Payload",
2522 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x12) / "S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002523 IS_NOT_SNAP,
2524 )
2525 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002526 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002527 IS_NOT_SNAP,
2528 )
2529 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002530 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002531 IS_NOT_SNAP,
2532 )
2533 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002534 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002535 IS_NOT_SNAP,
2536 )
2537 testPacket("LLC - SNAP - Non-default OUI",
2538 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2539 scapy.SNAP(OUI=0x000001, code=0x800) / ("S" * 10),
2540 IS_NOT_SNAP,
2541 )
2542 testPacket("LLC - SNAP - Default OUI",
2543 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2544 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2545 IS_SNAP_AND_IP,
2546 )
2547 testPacket("LLC - SNAP - Max -1 bogus payload",
2548 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2549 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2550 IS_SNAP_NOT_IP,
2551 )
2552 testPacket("LLC - SNAP - Max bogus payload",
2553 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2554 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2555 IS_SNAP_NOT_IP,
2556 )
2557 testPacket("LLC - SNAP - IP - TCP",
2558 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2559 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2560 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2561 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2562 IS_SNAP_AND_IP,
2563 )
2564
2565
2566class DirectArpPackets(DirectBadPacketBase):
2567 """
2568 Verify ARP parsing (valid and corrupted packets) and ARP matching
2569 """
2570 def runTest(self):
2571 self.testArpHandling()
2572
2573 def testArpHandling(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002574 eth_dst='00:01:02:03:04:05'
2575 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002576 ip_src='192.168.0.1'
2577 ip_dst='192.168.0.2'
2578 ip_src2='192.168.1.1'
2579 ip_dst2='192.168.1.2'
2580 ip_tos=0
2581 tcp_sport=1234
2582 tcp_dport=80
2583
2584 def testPacket(title, arp_match, arp_pkt, result):
2585 pkts = []
2586
Rich Laned0478ff2013-03-11 12:46:58 -07002587 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src) / arp_match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002588 match = packet_to_flow_match(self, match_pkt)
2589 self.assertTrue(match is not None,
2590 "Could not generate flow match from pkt")
2591 match.wildcards &= ~ofp.OFPFW_IN_PORT
2592
2593 pkts.append([
2594 title,
Rich Laned0478ff2013-03-11 12:46:58 -07002595 scapy.Ether(dst=eth_dst, src=eth_src) / arp_pkt,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002596 result,
2597 ])
2598
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002599 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002600 self.testPktsAgainstFlow(pkts, act, match)
2601
2602 testPacket("Basic ARP",
2603 scapy.ARP(psrc=ip_src, pdst=ip_dst, op = 1),
Rich Laned0478ff2013-03-11 12:46:58 -07002604 scapy.ARP(hwdst = '00:00:00:00:00:00', hwsrc = eth_src,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002605 psrc = ip_src, pdst = ip_dst, hwlen = 6, plen = 4,
2606 ptype = 0x800, hwtype = 1, op = 1),
2607 self.RESULT_MATCH
2608 )
2609 # More stuff:
2610 # - Non matches on any property
2611 # - Corrupted hwlen and plen
2612 # - Other hwtype, ptype
2613 # - Truncated ARP pkt
2614
2615
2616class DirectVlanPackets(DirectBadPacketBase):
2617 """
2618 Verify VLAN parsing (valid and corrupted packets) and ARP matching
2619 """
2620 def runTest(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002621 eth_dst='00:01:02:03:04:05'
2622 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002623 ip_src='192.168.0.1'
2624 ip_dst='192.168.0.2'
2625 ip_src2='192.168.1.1'
2626 ip_dst2='192.168.1.2'
2627 ip_tos=0
2628 tcp_sport=1234
2629 tcp_dport=80
2630
2631 def testPacket(title, match, pkt, result):
2632 pkts = []
2633
2634 self.assertTrue(match is not None,
2635 "Could not generate flow match from pkt")
2636 match.wildcards &= ~ofp.OFPFW_IN_PORT
2637
2638 pkts.append([
2639 "%s" % title,
2640 pkt,
2641 result,
2642 ])
2643
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002644 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002645 self.testPktsAgainstFlow(pkts, act, match)
2646
2647 testPacket("Basic MAC matching - IPv4 payload",
Rich Laned0478ff2013-03-11 12:46:58 -07002648 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2649 scapy.Ether(dst=eth_dst, src=eth_src, type=0x800) / scapy.IP(),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002650 self.RESULT_MATCH
2651 )
2652 testPacket("Basic MAC matching - VMware beacon - no payload",
Rich Laned0478ff2013-03-11 12:46:58 -07002653 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2654 scapy.Ether(dst=eth_dst, src=eth_src, type=0x8922),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002655 self.RESULT_MATCH
2656 )
2657 testPacket("Basic MAC matching - VMware beacon - with payload",
Rich Laned0478ff2013-03-11 12:46:58 -07002658 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2659 scapy.Ether(dst=eth_dst, src=eth_src, type=0x8922)/ ("X" * 1),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002660 self.RESULT_MATCH
2661 )
2662 testPacket("Basic MAC matching - IPv6 payload",
Rich Laned0478ff2013-03-11 12:46:58 -07002663 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2664 scapy.Ether(dst=eth_dst, src=eth_src) / scapy.IPv6(),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002665 self.RESULT_MATCH
2666 )
2667 testPacket("Basic MAC matching with VLAN tag present",
Rich Laned0478ff2013-03-11 12:46:58 -07002668 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2669 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002670 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002671 scapy.IP(),
2672 self.RESULT_MATCH
2673 )
2674 testPacket("Basic MAC matching with VLAN tag present",
Rich Laned0478ff2013-03-11 12:46:58 -07002675 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2676 eth_type=0x800),
2677 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002678 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002679 scapy.IP(),
2680 self.RESULT_MATCH
2681 )
2682 testPacket("Ether matching with VLAN tag present - No type match",
Rich Laned0478ff2013-03-11 12:46:58 -07002683 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2684 eth_type=0x801),
2685 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002686 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002687 scapy.IP(),
2688 self.RESULT_NOMATCH
2689 )
2690 testPacket("Ether matching with VLAN tag present - No type match 0x8100",
Rich Laned0478ff2013-03-11 12:46:58 -07002691 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2692 eth_type=0x8100),
2693 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002694 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002695 scapy.IP(),
2696 self.RESULT_NOMATCH
2697 )
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002698 testPacket("IP matching - VLAN tag",
Rich Laned0478ff2013-03-11 12:46:58 -07002699 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2700 eth_type=0x0800,
2701 ipv4_src=parse_ip(ip_src), ipv4_dst=parse_ip(ip_dst)),
2702 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002703 scapy.Dot1Q(prio=5, vlan=1000)/ \
2704 scapy.IP(src=ip_src, dst=ip_dst),
2705 self.RESULT_MATCH
2706 )
2707 # XXX:
2708 # - Matching on VLAN ID and Prio
2709 # - Actions
2710
2711@nonstandard
2712class DirectVlanPacketsDoubleTagged(DirectVlanPackets):
2713 """
2714 VLAN parsing for double tagged packets. Spec is ambiguous about
2715 the treatment of these cases, so broken out to be non-standard
2716 """
2717 def runTest(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002718 eth_dst='00:01:02:03:04:05'
2719 eth_src='00:06:07:08:09:0a'
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002720 ip_src='192.168.0.1'
2721 ip_dst='192.168.0.2'
2722 ip_src2='192.168.1.1'
2723 ip_dst2='192.168.1.2'
2724 ip_tos=0
2725 tcp_sport=1234
2726 tcp_dport=80
2727
2728 def testPacket(title, match, pkt, result):
2729 pkts = []
2730
2731 self.assertTrue(match is not None,
2732 "Could not generate flow match from pkt")
2733 match.wildcards &= ~ofp.OFPFW_IN_PORT
2734
2735 pkts.append([
2736 "%s" % title,
2737 pkt,
2738 result,
2739 ])
2740
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002741 act = ofp.action.output()
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002742 self.testPktsAgainstFlow(pkts, act, match)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002743 testPacket("Ether matching with double VLAN tag - Wrong type match",
Rich Laned0478ff2013-03-11 12:46:58 -07002744 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2745 eth_type=0x800),
2746 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002747 scapy.Dot1Q(prio=5, vlan=1000)/ \
2748 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002749 scapy.IP(),
2750 self.RESULT_NOMATCH
2751 )
2752 testPacket("Ether matching with double VLAN tag - Type match",
Rich Laned0478ff2013-03-11 12:46:58 -07002753 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2754 eth_type=0x8100),
2755 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002756 scapy.Dot1Q(prio=5, vlan=1000)/ \
2757 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002758 scapy.IP(),
2759 self.RESULT_MATCH
2760 )
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002761
2762
2763
Dan Talayco9f47f4d2010-06-03 13:54:37 -07002764if __name__ == "__main__":
2765 print "Please run through oft script: ./oft --test_spec=basic"