blob: 04edf952e1710aa2adb45cbf3bf7f430359ee25b [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))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700498 yes_ports = set([egress_port1, egress_port2])
499 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700500
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700501 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Rich Lane2014f9b2012-10-05 15:29:40 -0700502 self)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700503
Rich Laneb90a1c42012-10-05 09:16:05 -0700504class DirectMCNonIngress(base_tests.SimpleDataPlane):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700505 """
506 Multicast to all non-ingress ports
507
508 Generate a packet
509 Generate and install a matching flow
510 Add action to direct the packet to all non-ingress ports
511 Send the packet to ingress dataplane port
512 Verify the packet is received at all non-ingress ports
513
514 Does not use the flood action
515 """
516 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700517 of_ports = config["port_map"].keys()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700518 of_ports.sort()
519 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
520
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700521 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700522 match = packet_to_flow_match(self, pkt)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700523 match.wildcards &= ~ofp.OFPFW_IN_PORT
524 self.assertTrue(match is not None,
525 "Could not generate flow match from pkt")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700526
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700527 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800528 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700529
Rich Lane9a003812012-10-04 17:17:59 -0700530 logging.info("Ingress " + str(ingress_port) +
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700531 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700532 match.in_port = ingress_port
533
Rich Laneba3f0e22013-03-11 16:43:57 -0700534 request = ofp.message.flow_add()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700535 request.match = match
536 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700537 for egress_port in of_ports:
538 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700539 continue
Rich Lane62e96852013-03-11 12:04:45 -0700540 request.actions.append(ofp.action.output(port=egress_port))
Rich Lane9a003812012-10-04 17:17:59 -0700541 logging.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700542
Rich Lane9a003812012-10-04 17:17:59 -0700543 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800544 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800545 do_barrier(self.controller)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700546
Rich Lane9a003812012-10-04 17:17:59 -0700547 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700548 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700549 yes_ports = set(of_ports).difference([ingress_port])
550 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700551 self)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700552
Dan Talayco32fa6542010-05-11 15:54:08 -0700553
Rich Laneb90a1c42012-10-05 09:16:05 -0700554class DirectMC(base_tests.SimpleDataPlane):
Dan Talayco32fa6542010-05-11 15:54:08 -0700555 """
556 Multicast to all ports including ingress
557
558 Generate a packet
559 Generate and install a matching flow
560 Add action to direct the packet to all non-ingress ports
561 Send the packet to ingress dataplane port
562 Verify the packet is received at all ports
563
564 Does not use the flood action
565 """
566 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700567 of_ports = config["port_map"].keys()
Dan Talayco32fa6542010-05-11 15:54:08 -0700568 of_ports.sort()
569 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
570
Dan Talayco32fa6542010-05-11 15:54:08 -0700571 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700572 match = packet_to_flow_match(self, pkt)
Dan Talayco32fa6542010-05-11 15:54:08 -0700573 match.wildcards &= ~ofp.OFPFW_IN_PORT
574 self.assertTrue(match is not None,
575 "Could not generate flow match from pkt")
Dan Talayco32fa6542010-05-11 15:54:08 -0700576
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700577 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800578 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700579
Rich Lane9a003812012-10-04 17:17:59 -0700580 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700581 match.in_port = ingress_port
582
Rich Laneba3f0e22013-03-11 16:43:57 -0700583 request = ofp.message.flow_add()
Dan Talayco32fa6542010-05-11 15:54:08 -0700584 request.match = match
585 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700586 for egress_port in of_ports:
Rich Lane62e96852013-03-11 12:04:45 -0700587 act = ofp.action.output()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700588 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700589 act.port = ofp.OFPP_IN_PORT
590 else:
591 act.port = egress_port
Rich Lanec495d9e2013-03-08 17:43:36 -0800592 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -0700593 # logging.info(request.show())
Dan Talayco2e77a842010-05-12 15:39:46 -0700594
Rich Lane9a003812012-10-04 17:17:59 -0700595 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800596 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800597 do_barrier(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700598
Rich Lane9a003812012-10-04 17:17:59 -0700599 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700600 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700601 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco2e77a842010-05-12 15:39:46 -0700602
Rich Laneb90a1c42012-10-05 09:16:05 -0700603class Flood(base_tests.SimpleDataPlane):
Dan Talayco2e77a842010-05-12 15:39:46 -0700604 """
605 Flood to all ports except ingress
606
Dan Talaycofcc09912013-02-08 23:46:08 -0800607 Make sure noflood bit is off on all ports
Dan Talayco2e77a842010-05-12 15:39:46 -0700608 Generate a packet
609 Generate and install a matching flow
610 Add action to flood the packet
611 Send the packet to ingress dataplane port
612 Verify the packet is received at all other ports
613 """
614 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700615 of_ports = config["port_map"].keys()
Dan Talayco2e77a842010-05-12 15:39:46 -0700616 of_ports.sort()
617 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
618
619 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700620 match = packet_to_flow_match(self, pkt)
Dan Talayco2e77a842010-05-12 15:39:46 -0700621 match.wildcards &= ~ofp.OFPFW_IN_PORT
622 self.assertTrue(match is not None,
623 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800624 act = ofp.action.output()
Dan Talayco2e77a842010-05-12 15:39:46 -0700625
Dan Talaycofcc09912013-02-08 23:46:08 -0800626 for of_port in of_ports:
627 # Clear relevant bits that might block ports
628 rv = port_config_set(self.controller, of_port, 0,
629 ofp.OFPPC_NO_FLOOD | ofp.OFPPC_NO_FWD |
630 ofp.OFPPC_PORT_DOWN)
631 self.assertTrue(rv == 0, "Did not set port config")
632 logging.debug("Enabled and cleared no-flood for port " + str(of_port))
633
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700634 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800635 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700636
Rich Lane9a003812012-10-04 17:17:59 -0700637 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700638 match.in_port = ingress_port
639
Rich Laneba3f0e22013-03-11 16:43:57 -0700640 request = ofp.message.flow_add()
Dan Talayco2e77a842010-05-12 15:39:46 -0700641 request.match = match
642 request.buffer_id = 0xffffffff
643 act.port = ofp.OFPP_FLOOD
Rich Lanec495d9e2013-03-08 17:43:36 -0800644 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -0700645 logging.info(request.show())
Dan Talayco32fa6542010-05-11 15:54:08 -0700646
Rich Lane9a003812012-10-04 17:17:59 -0700647 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800648 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800649 do_barrier(self.controller)
Dan Talayco32fa6542010-05-11 15:54:08 -0700650
Rich Lane9a003812012-10-04 17:17:59 -0700651 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco32fa6542010-05-11 15:54:08 -0700652 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700653 yes_ports = set(of_ports).difference([ingress_port])
654 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700655 self)
Dan Talayco3be5b062010-05-12 15:46:21 -0700656
Rich Laneb90a1c42012-10-05 09:16:05 -0700657class FloodPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco3be5b062010-05-12 15:46:21 -0700658 """
659 Flood to all ports plus send to ingress port
660
661 Generate a packet
662 Generate and install a matching flow
663 Add action to flood the packet
664 Add action to send to ingress port
665 Send the packet to ingress dataplane port
666 Verify the packet is received at all other ports
667 """
668 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700669 of_ports = config["port_map"].keys()
Dan Talayco3be5b062010-05-12 15:46:21 -0700670 of_ports.sort()
671 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
672
673 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700674 match = packet_to_flow_match(self, pkt)
Dan Talayco3be5b062010-05-12 15:46:21 -0700675 match.wildcards &= ~ofp.OFPFW_IN_PORT
676 self.assertTrue(match is not None,
677 "Could not generate flow match from pkt")
Dan Talayco3be5b062010-05-12 15:46:21 -0700678
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700679 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800680 delete_all_flows(self.controller)
Dan Talayco3be5b062010-05-12 15:46:21 -0700681
Rich Lane9a003812012-10-04 17:17:59 -0700682 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700683 match.in_port = ingress_port
684
Rich Laneba3f0e22013-03-11 16:43:57 -0700685 request = ofp.message.flow_add()
Dan Talayco3be5b062010-05-12 15:46:21 -0700686 request.match = match
687 request.buffer_id = 0xffffffff
Rich Lane62e96852013-03-11 12:04:45 -0700688 request.actions.append(ofp.action.output(port=ofp.OFPP_FLOOD))
689 request.actions.append(ofp.action.output(port=ofp.OFPP_IN_PORT))
Rich Lane9a003812012-10-04 17:17:59 -0700690 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700691
Rich Lane9a003812012-10-04 17:17:59 -0700692 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800693 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800694 do_barrier(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700695
Rich Lane9a003812012-10-04 17:17:59 -0700696 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700697 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700698 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco4aa13122010-05-12 15:54:44 -0700699
Rich Laneb90a1c42012-10-05 09:16:05 -0700700class All(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700701 """
702 Send to OFPP_ALL port
703
704 Generate a packet
705 Generate and install a matching flow
706 Add action to forward to OFPP_ALL
707 Send the packet to ingress dataplane port
708 Verify the packet is received at all other ports
709 """
710 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700711 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700712 of_ports.sort()
713 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
714
715 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700716 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700717 match.wildcards &= ~ofp.OFPFW_IN_PORT
718 self.assertTrue(match is not None,
719 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800720 act = ofp.action.output()
Dan Talayco4aa13122010-05-12 15:54:44 -0700721
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700722 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800723 delete_all_flows(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700724
Rich Lane9a003812012-10-04 17:17:59 -0700725 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700726 match.in_port = ingress_port
727
Rich Laneba3f0e22013-03-11 16:43:57 -0700728 request = ofp.message.flow_add()
Dan Talayco4aa13122010-05-12 15:54:44 -0700729 request.match = match
730 request.buffer_id = 0xffffffff
731 act.port = ofp.OFPP_ALL
Rich Lanec495d9e2013-03-08 17:43:36 -0800732 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -0700733 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700734
Rich Lane9a003812012-10-04 17:17:59 -0700735 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800736 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800737 do_barrier(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700738
Rich Lane9a003812012-10-04 17:17:59 -0700739 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700740 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700741 yes_ports = set(of_ports).difference([ingress_port])
742 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700743 self)
Dan Talayco4aa13122010-05-12 15:54:44 -0700744
Rich Laneb90a1c42012-10-05 09:16:05 -0700745class AllPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700746 """
747 Send to OFPP_ALL port and ingress port
748
749 Generate a packet
750 Generate and install a matching flow
751 Add action to forward to OFPP_ALL
752 Add action to forward to ingress port
753 Send the packet to ingress dataplane port
754 Verify the packet is received at all other ports
755 """
756 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700757 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700758 of_ports.sort()
759 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
760
761 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700762 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700763 match.wildcards &= ~ofp.OFPFW_IN_PORT
764 self.assertTrue(match is not None,
765 "Could not generate flow match from pkt")
Dan Talayco4aa13122010-05-12 15:54:44 -0700766
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700767 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800768 delete_all_flows(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700769
Rich Lane9a003812012-10-04 17:17:59 -0700770 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700771 match.in_port = ingress_port
772
Rich Laneba3f0e22013-03-11 16:43:57 -0700773 request = ofp.message.flow_add()
Dan Talayco4aa13122010-05-12 15:54:44 -0700774 request.match = match
775 request.buffer_id = 0xffffffff
Rich Lane62e96852013-03-11 12:04:45 -0700776 request.actions.append(ofp.action.output(port=ofp.OFPP_ALL))
777 request.actions.append(ofp.action.output(port=ofp.OFPP_IN_PORT))
Rich Lane9a003812012-10-04 17:17:59 -0700778 logging.info(request.show())
Dan Talayco3be5b062010-05-12 15:46:21 -0700779
Rich Lane9a003812012-10-04 17:17:59 -0700780 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800781 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800782 do_barrier(self.controller)
Dan Talayco3be5b062010-05-12 15:46:21 -0700783
Rich Lane9a003812012-10-04 17:17:59 -0700784 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco3be5b062010-05-12 15:46:21 -0700785 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700786 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700787
Rich Laneb90a1c42012-10-05 09:16:05 -0700788class FloodMinusPort(base_tests.SimpleDataPlane):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700789 """
790 Config port with No_Flood and test Flood action
791
792 Generate a packet
793 Generate a matching flow
794 Add action to forward to OFPP_ALL
795 Set port to no-flood
796 Send the packet to ingress dataplane port
797 Verify the packet is received at all other ports except
798 the ingress port and the no_flood port
799 """
800 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700801 of_ports = config["port_map"].keys()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700802 of_ports.sort()
803 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
804
805 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700806 match = packet_to_flow_match(self, pkt)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700807 match.wildcards &= ~ofp.OFPFW_IN_PORT
808 self.assertTrue(match is not None,
809 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800810 act = ofp.action.output()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700811
Rich Lane4b9e38c2012-12-06 16:33:20 -0800812 # Clear OFPPC_NO_FLOOD on each port
813 for of_port in of_ports:
814 rv = port_config_set(self.controller, of_port,
815 0, ofp.OFPPC_NO_FLOOD)
816 self.assertEqual(rv, 0, "Failed to set port config")
817
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700818 for idx in range(len(of_ports)):
Rich Lane32bf9482013-01-03 17:26:30 -0800819 delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700820
821 ingress_port = of_ports[idx]
822 no_flood_idx = (idx + 1) % len(of_ports)
823 no_flood_port = of_ports[no_flood_idx]
824 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700825 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700826 self.assertEqual(rv, 0, "Failed to set port config")
827
828 match.in_port = ingress_port
829
Rich Laneba3f0e22013-03-11 16:43:57 -0700830 request = ofp.message.flow_add()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700831 request.match = match
832 request.buffer_id = 0xffffffff
833 act.port = ofp.OFPP_FLOOD
Rich Lanec495d9e2013-03-08 17:43:36 -0800834 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -0700835 logging.info(request.show())
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700836
Rich Lane9a003812012-10-04 17:17:59 -0700837 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800838 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800839 do_barrier(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700840
Rich Lane9a003812012-10-04 17:17:59 -0700841 logging.info("Sending packet to dp port " + str(ingress_port))
842 logging.info("No flood port is " + str(no_flood_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700843 self.dataplane.send(ingress_port, str(pkt))
844 no_ports = set([ingress_port, no_flood_port])
845 yes_ports = set(of_ports).difference(no_ports)
Rich Lane2014f9b2012-10-05 15:29:40 -0700846 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700847
848 # Turn no flood off again
849 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700850 0, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700851 self.assertEqual(rv, 0, "Failed to reset port config")
Rich Lane3a261d52013-01-03 17:45:08 -0800852 do_barrier(self.controller)
Rich Lane4ecc1f42012-12-06 16:35:24 -0800853
854 # Check that packets are now flooded to no_flood_port
855 logging.info("Sending packet to dp port " + str(ingress_port))
856 self.dataplane.send(ingress_port, str(pkt))
857 no_ports = set([ingress_port])
858 yes_ports = set(of_ports).difference(no_ports)
859 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700860
861 #@todo Should check no other packets received
862
Dan Talayco21381562010-07-17 00:34:47 -0700863
864
Dan Talayco551befa2010-07-15 17:05:32 -0700865################################################################
866
Rich Laneb90a1c42012-10-05 09:16:05 -0700867class BaseMatchCase(base_tests.SimpleDataPlane):
Dan Talayco551befa2010-07-15 17:05:32 -0700868 def setUp(self):
Rich Laneb90a1c42012-10-05 09:16:05 -0700869 base_tests.SimpleDataPlane.setUp(self)
Dan Talayco551befa2010-07-15 17:05:32 -0700870 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -0700871 logging.info("BaseMatchCase")
Dan Talayco551befa2010-07-15 17:05:32 -0700872
873class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700874 """
Dan Talayco551befa2010-07-15 17:05:32 -0700875 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700876
877 Generate a packet
878 Generate and install a matching flow without wildcard mask
879 Add action to forward to a port
880 Send the packet to the port
881 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700882 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700883
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700884 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700885 flow_match_test(self, config["port_map"])
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700886
Dan Talayco551befa2010-07-15 17:05:32 -0700887class ExactMatchTagged(BaseMatchCase):
888 """
889 Exact match for all port pairs with tagged pkts
890 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700891
Dan Talayco551befa2010-07-15 17:05:32 -0700892 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -0700893 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Laned0478ff2013-03-11 12:46:58 -0700894 flow_match_test(self, config["port_map"], vlan_vid=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700895
Rich Lane0a4f6372013-01-02 14:40:22 -0800896@disabled
Dan Talayco551befa2010-07-15 17:05:32 -0700897class ExactMatchTaggedMany(BaseMatchCase):
898 """
899 ExactMatchTagged with many VLANS
900 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700901
Dan Talayco551befa2010-07-15 17:05:32 -0700902 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700903 for vid in range(2,100,10):
Rich Laned0478ff2013-03-11 12:46:58 -0700904 flow_match_test(self, config["port_map"], vlan_vid=vid, max_test=5)
Dan Talayco551befa2010-07-15 17:05:32 -0700905 for vid in range(100,4000,389):
Rich Laned0478ff2013-03-11 12:46:58 -0700906 flow_match_test(self, config["port_map"], vlan_vid=vid, max_test=5)
907 flow_match_test(self, config["port_map"], vlan_vid=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700908
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700909class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700910 """
911 SingleWildcardMatchPriority
912 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700913
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700914 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700915 self.pkt = simple_tcp_packet()
916 self.flowMsgs = {}
917
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700918 def _ClearTable(self):
Rich Lane32bf9482013-01-03 17:26:30 -0800919 delete_all_flows(self.controller)
Rich Lane3a261d52013-01-03 17:45:08 -0800920 do_barrier(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700921
922 def runTest(self):
923
924 self._Init()
Rich Lane477f4812012-10-04 22:49:00 -0700925 of_ports = config["port_map"].keys()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700926 of_ports.sort()
927
928 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700929 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700930
931 # Run several combinations, each at lower priority settings.
932 # At the end of each call to runPrioFlows(), the table should
933 # be empty. If its not, we'll catch it as the priorities decreases
934 portA = of_ports[0]
935 portB = of_ports[1]
936 portC = of_ports[2]
937
938 # TODO -- these priority numbers should be validated somehow?
939 self.runPrioFlows(portA, portB, portC, 1000, 999)
940 self.runPrioFlows(portB, portC, portA, 998, 997)
941 self.runPrioFlows(portC, portA, portB, 996, 995)
942 self.runPrioFlows(portA, portC, portB, 994, 993)
943
944
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700945
946 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
947 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700948
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700949 if clearTable:
950 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700951
952 # Sanity check flow at lower priority from pA to pB
Rich Lane9a003812012-10-04 17:17:59 -0700953 logging.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700954 % (portA, portB, portC, prioHigher, prioLower))
955
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700956 # Sanity check flow at lower priority from pA to pC
957 self.installFlow(prioLower, portA, portC)
958 self.verifyFlow(portA, portC)
959 self.removeFlow(prioLower)
960
961 # Install and verify pA->pB @ prioLower
962 self.installFlow(prioLower, portA, portB)
963 self.verifyFlow(portA, portB)
964
965 # Install and verify pA->pC @ prioHigher, should override pA->pB
966 self.installFlow(prioHigher, portA, portC)
967 self.verifyFlow(portA, portC)
968 # remove pA->pC
969 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700970 # Old flow pA -> pB @ prioLower should still be active
971 self.verifyFlow(portA, portB)
972 self.removeFlow(prioLower)
973
974 # Table should be empty at this point, leave it alone as
975 # an assumption for future test runs
976
977
978
Ed Swierk99a74de2012-08-22 06:40:54 -0700979 def installFlow(self, prio, inp, egp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700980 wildcards=ofp.OFPFW_DL_SRC):
Ed Swierk99a74de2012-08-22 06:40:54 -0700981 wildcards |= required_wildcards(self)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700982 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700983 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700984 egr_ports=egp)
985 request.priority = prio
Rich Lane9a003812012-10-04 17:17:59 -0700986 logging.debug("Install flow with priority " + str(prio))
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700987 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700988 self.flowMsgs[prio] = request
989
990 def removeFlow(self, prio):
991 if self.flowMsgs.has_key(prio):
Rich Laneba3f0e22013-03-11 16:43:57 -0700992 old_msg = self.flowMsgs[prio]
993 msg = ofp.message.flow_delete_strict(out_port=ofp.OFPP_NONE,
994 match=old_msg.match,
995 priority=old_msg.priority)
Rich Lane9a003812012-10-04 17:17:59 -0700996 logging.debug("Remove flow with priority " + str(prio))
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700997 self.controller.message_send(msg)
Rich Lane3a261d52013-01-03 17:45:08 -0800998 do_barrier(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700999 else:
1000 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001001
1002
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001003 def verifyFlow(self, inp, egp, pkt=None):
1004 if pkt == None:
1005 pkt = self.pkt
1006
Rich Lane9a003812012-10-04 17:17:59 -07001007 logging.info("Pkt match test: " + str(inp) + " to " + str(egp))
1008 logging.debug("Send packet: " + str(inp) + " to " + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001009 self.dataplane.send(inp, str(pkt))
1010 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001011
1012
1013
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001014class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
1015
1016 def runTest(self):
1017
1018 self._Init()
1019
Rich Lane477f4812012-10-04 22:49:00 -07001020 of_ports = config["port_map"].keys()
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001021 of_ports.sort()
1022
1023 # Install an entry from 0 -> 1 @ prio 1000
1024 self._ClearTable()
1025 self.installFlow(1000, of_ports[0], of_ports[1])
1026 self.verifyFlow(of_ports[0], of_ports[1])
1027 self.installFlow(1000, of_ports[1], of_ports[0])
1028 self.verifyFlow(of_ports[1], of_ports[0])
1029 self.installFlow(1001, of_ports[0], of_ports[1])
1030 self.verifyFlow(of_ports[0], of_ports[1])
1031 self.installFlow(1001, of_ports[1], of_ports[0])
1032 self.verifyFlow(of_ports[1], of_ports[0])
1033 self.removeFlow(1001)
1034 self.verifyFlow(of_ports[0], of_ports[1])
1035 self.removeFlow(1000)
1036
1037
1038
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001039class WildcardPriority(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001040 """
1041 1. Add wildcard flow, verify packet received.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001042 2. Add wildcard flow with higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001043 on port specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001044 3. Add wildcard flow with lower priority, verify packet received
Rich Laneb8392082012-11-21 15:52:54 -08001045 on port specified by the highest priority flow.
Ken Chiang38d7a152012-05-24 15:33:50 -07001046 """
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001047
1048 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001049
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001050 self._Init()
1051
Rich Lane477f4812012-10-04 22:49:00 -07001052 of_ports = config["port_map"].keys()
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001053 of_ports.sort()
1054
1055 self._ClearTable()
Ken Chiang38d7a152012-05-24 15:33:50 -07001056
1057 # Install a flow with wildcards
1058 self.installFlow(999, of_ports[0], of_ports[1],
1059 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001060 self.verifyFlow(of_ports[0], of_ports[1])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001061 # Install a flow with wildcards with higher priority
1062 self.installFlow(1000, of_ports[0], of_ports[2],
1063 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001064 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001065 # Install a flow with wildcards with lower priority
Rich Laneb8392082012-11-21 15:52:54 -08001066 self.installFlow(999, of_ports[0], of_ports[1],
1067 wildcards=ofp.OFPFW_DL_SRC)
Rich Lane0a78fbd2012-12-31 16:25:04 -08001068 self.verifyFlow(of_ports[0], of_ports[2])
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001069
1070
Rich Lane97e99652013-01-02 17:23:20 -08001071@group("smoke")
Ken Chiang3978f242012-06-13 14:14:09 -07001072class WildcardPriorityWithDelete(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001073 """
Rich Lane0a78fbd2012-12-31 16:25:04 -08001074 1. Add wildcard match flow, verify packet received.
Ken Chiang38d7a152012-05-24 15:33:50 -07001075 2. Add wildcard flow with higher priority, verify packet received on port
1076 specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001077 3. Add wildcard flow with even higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001078 on port specified by this flow.
1079 4. Delete lowest priority flow, verify packet received on port specified
1080 by highest priority flow.
1081 5. Delete highest priority flow, verify packet received on port specified
1082 by remaining flow.
1083 """
1084
1085 def runTest(self):
1086
1087 self._Init()
1088
Rich Lane477f4812012-10-04 22:49:00 -07001089 of_ports = config["port_map"].keys()
Ken Chiang38d7a152012-05-24 15:33:50 -07001090 of_ports.sort()
1091
1092 self._ClearTable()
1093
Rich Lane0a78fbd2012-12-31 16:25:04 -08001094 # Install a flow with wildcards
1095 self.installFlow(250, of_ports[0], of_ports[1],
1096 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001097 self.verifyFlow(of_ports[0], of_ports[1])
1098 # Install a flow with wildcards of higher priority
1099 self.installFlow(1250, of_ports[0], of_ports[2],
1100 wildcards=ofp.OFPFW_DL_DST)
1101 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001102 # Install a flow with wildcards with even higher priority
1103 self.installFlow(2001, of_ports[0], of_ports[3],
1104 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001105 self.verifyFlow(of_ports[0], of_ports[3])
1106 # Delete lowest priority flow
1107 self.removeFlow(250)
1108 self.verifyFlow(of_ports[0], of_ports[3])
1109 # Delete highest priority flow
1110 self.removeFlow(2001)
1111 self.verifyFlow(of_ports[0], of_ports[2])
1112
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001113
Dan Talayco551befa2010-07-15 17:05:32 -07001114class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001115 """
1116 Exercise wildcard matching for all ports
1117
1118 Generate a packet
1119 Generate and install a matching flow with wildcard mask
1120 Add action to forward to a port
1121 Send the packet to the port
1122 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001123 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001124 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001125 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001126 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001127 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001128 wc |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001129 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001130 # Set nonzero VLAN id to avoid sending priority-tagged packet
Rich Laned0478ff2013-03-11 12:46:58 -07001131 vlan_vid = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001132 else:
Rich Laned0478ff2013-03-11 12:46:58 -07001133 vlan_vid = -1
Rich Lane477f4812012-10-04 22:49:00 -07001134 flow_match_test(self, config["port_map"], wildcards=wc,
Rich Laned0478ff2013-03-11 12:46:58 -07001135 vlan_vid=vlan_vid, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001136
Dan Talayco551befa2010-07-15 17:05:32 -07001137class SingleWildcardMatchTagged(BaseMatchCase):
1138 """
1139 SingleWildcardMatch with tagged packets
1140 """
1141 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001142 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001143 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001144 wc |= required_wildcards(self)
Rich Laned0478ff2013-03-11 12:46:58 -07001145 flow_match_test(self, config["port_map"], wildcards=wc, vlan_vid=vid,
Dan Talayco551befa2010-07-15 17:05:32 -07001146 max_test=10)
1147
1148class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001149 """
Dan Talayco80b54ed2010-07-13 09:48:35 -07001150 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001151
1152 Generate a packet
1153 Generate and install a matching flow with wildcard all except one filed
1154 Add action to forward to a port
1155 Send the packet to the port
1156 Verify the packet is received at all other ports (one port at a time)
1157 Verify flow_expiration message is correct when command option is set
1158 """
1159 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001160 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001161 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001162 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001163 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001164 # Set nonzero VLAN id to avoid sending priority-tagged packet
Rich Laned0478ff2013-03-11 12:46:58 -07001165 vlan_vid = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001166 else:
Rich Laned0478ff2013-03-11 12:46:58 -07001167 vlan_vid = -1
Rich Lane477f4812012-10-04 22:49:00 -07001168 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Rich Laned0478ff2013-03-11 12:46:58 -07001169 vlan_vid=vlan_vid)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001170
Dan Talayco551befa2010-07-15 17:05:32 -07001171class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1172 """
1173 Match one field with tagged packets
1174 """
1175 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001176 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001177 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001178 all_exp_one_wildcard |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001179 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Rich Laned0478ff2013-03-11 12:46:58 -07001180 vlan_vid=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001181
1182class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001183 """
1184 Create Wildcard-all flow and exercise for all ports
1185
1186 Generate a packet
1187 Generate and install a matching flow with wildcard-all
1188 Add action to forward to a port
1189 Send the packet to the port
1190 Verify the packet is received at all other ports (one port at a time)
1191 Verify flow_expiration message is correct when command option is set
1192 """
1193 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001194 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001195
Dan Talayco551befa2010-07-15 17:05:32 -07001196class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001197 """
Dan Talayco551befa2010-07-15 17:05:32 -07001198 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001199 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001200 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001201 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Lane477f4812012-10-04 22:49:00 -07001202 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL,
Rich Laned0478ff2013-03-11 12:46:58 -07001203 vlan_vid=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001204
Rich Lane97e99652013-01-02 17:23:20 -08001205@group('smoke')
Dan Talayco551befa2010-07-15 17:05:32 -07001206class AddVLANTag(BaseMatchCase):
1207 """
1208 Add a VLAN tag to an untagged packet
1209 """
1210 def runTest(self):
1211 new_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001212 sup_acts = self.supported_actions
Dan Talayco551befa2010-07-15 17:05:32 -07001213 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001214 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001215 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001216
Dan Talayco551befa2010-07-15 17:05:32 -07001217 len = 100
1218 len_w_vid = 104
1219 pkt = simple_tcp_packet(pktlen=len)
1220 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
Rich Laned0478ff2013-03-11 12:46:58 -07001221 vlan_vid=new_vid)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001222 vid_act = ofp.action.set_vlan_vid()
Dan Talayco551befa2010-07-15 17:05:32 -07001223 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001224
Rich Lane477f4812012-10-04 22:49:00 -07001225 flow_match_test(self, config["port_map"], pkt=pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001226 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001227
Rich Lane0a4f6372013-01-02 14:40:22 -08001228@disabled
Rich Laneb90a1c42012-10-05 09:16:05 -07001229class PacketOnly(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001230 """
1231 Just send a packet thru the switch
1232 """
Rich Laned1d9c282012-10-04 22:07:10 -07001233
Dan Talayco551befa2010-07-15 17:05:32 -07001234 def runTest(self):
1235 pkt = simple_tcp_packet()
Rich Lane477f4812012-10-04 22:49:00 -07001236 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001237 of_ports.sort()
1238 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001239 logging.info("Sending packet to " + str(ing_port))
1240 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001241 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001242
Rich Lane0a4f6372013-01-02 14:40:22 -08001243@disabled
Rich Laneb90a1c42012-10-05 09:16:05 -07001244class PacketOnlyTagged(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001245 """
1246 Just send a packet thru the switch
1247 """
Rich Laned1d9c282012-10-04 22:07:10 -07001248
Dan Talayco551befa2010-07-15 17:05:32 -07001249 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001250 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Laned0478ff2013-03-11 12:46:58 -07001251 pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=vid)
Rich Lane477f4812012-10-04 22:49:00 -07001252 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001253 of_ports.sort()
1254 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001255 logging.info("Sending packet to " + str(ing_port))
1256 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001257 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001258
Dan Talayco551befa2010-07-15 17:05:32 -07001259class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001260 """
1261 Modify the VLAN ID in the VLAN tag of a tagged packet
1262 """
Dan Talaycoaf669322012-09-12 22:51:22 -07001263 def setUp(self):
1264 BaseMatchCase.setUp(self)
1265 self.ing_port=False
1266
Dan Talayco551befa2010-07-15 17:05:32 -07001267 def runTest(self):
1268 old_vid = 2
1269 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001270 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001271 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001272 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001273 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001274
Rich Laned0478ff2013-03-11 12:46:58 -07001275 pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=old_vid)
1276 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=new_vid)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001277 vid_act = ofp.action.set_vlan_vid()
Dan Talayco551befa2010-07-15 17:05:32 -07001278 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001279
Rich Lane477f4812012-10-04 22:49:00 -07001280 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoaf669322012-09-12 22:51:22 -07001281 action_list=[vid_act], ing_port=self.ing_port)
1282
1283class ModifyVIDToIngress(ModifyVID):
1284 """
1285 Modify the VLAN ID in the VLAN tag of a tagged packet and send to
1286 ingress port
1287 """
1288 def setUp(self):
1289 BaseMatchCase.setUp(self)
1290 self.ing_port=True
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001291
Ken Chiange9a211d2012-04-20 14:52:11 -07001292class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1293 """
Rich Lane28fa9272013-03-08 16:00:25 -08001294 With vlan ID and priority wildcarded, perform SET_VLAN_VID ofp.action.
Ken Chiange9a211d2012-04-20 14:52:11 -07001295 The same flow should match on both untagged and tagged packets.
1296 """
1297 def runTest(self):
1298 old_vid = 2
1299 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001300 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001301 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1302 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1303 return
1304
Rich Lane477f4812012-10-04 22:49:00 -07001305 of_ports = config["port_map"].keys()
Ken Chiange9a211d2012-04-20 14:52:11 -07001306 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1307 ing_port = of_ports[0]
1308 egr_ports = of_ports[1]
1309
Rich Lane32bf9482013-01-03 17:26:30 -08001310 delete_all_flows(self.controller)
Ken Chiange9a211d2012-04-20 14:52:11 -07001311
1312 len_untagged = 100
1313 len_w_vid = 104
1314 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1315 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
Rich Laned0478ff2013-03-11 12:46:58 -07001316 dl_vlan_enable=True, vlan_vid=old_vid)
Ken Chiange9a211d2012-04-20 14:52:11 -07001317 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
Rich Laned0478ff2013-03-11 12:46:58 -07001318 vlan_vid=new_vid)
Ed Swierk99a74de2012-08-22 06:40:54 -07001319 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1320 ofp.OFPFW_DL_VLAN_PCP)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001321 vid_act = ofp.action.set_vlan_vid()
Ken Chiange9a211d2012-04-20 14:52:11 -07001322 vid_act.vlan_vid = new_vid
1323 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
1324 wildcards=wildcards, egr_ports=egr_ports,
1325 action_list=[vid_act])
1326 flow_msg_install(self, request)
1327
Rich Lane9a003812012-10-04 17:17:59 -07001328 logging.debug("Send untagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001329 str(egr_ports))
1330 self.dataplane.send(ing_port, str(untagged_pkt))
1331 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1332
Rich Lane9a003812012-10-04 17:17:59 -07001333 logging.debug("Send tagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001334 str(egr_ports))
1335 self.dataplane.send(ing_port, str(tagged_pkt))
1336 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1337
Howard Pershc1199d52012-04-11 14:21:32 -07001338class ModifyVlanPcp(BaseMatchCase):
1339 """
1340 Modify the priority field of the VLAN tag of a tagged packet
1341 """
1342 def runTest(self):
1343 vid = 123
1344 old_vlan_pcp = 2
1345 new_vlan_pcp = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001346 sup_acts = self.supported_actions
Ed Swierk8c3af7f2012-04-24 14:19:17 -07001347 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_PCP):
1348 skip_message_emit(self, "Modify VLAN priority test")
Howard Pershc1199d52012-04-11 14:21:32 -07001349 return
1350
Rich Laned0478ff2013-03-11 12:46:58 -07001351 pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=vid, vlan_pcp=old_vlan_pcp)
1352 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=vid, vlan_pcp=new_vlan_pcp)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001353 vid_act = ofp.action.set_vlan_pcp()
Howard Pershc1199d52012-04-11 14:21:32 -07001354 vid_act.vlan_pcp = new_vlan_pcp
1355
Rich Lane477f4812012-10-04 22:49:00 -07001356 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Howard Pershc1199d52012-04-11 14:21:32 -07001357 action_list=[vid_act])
1358
Dan Talayco551befa2010-07-15 17:05:32 -07001359class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001360 """
1361 Strip the VLAN tag from a tagged packet
1362 """
Dan Talayco551befa2010-07-15 17:05:32 -07001363 def runTest(self):
1364 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001365 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001366 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001367 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001368 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001369
Dan Talayco551befa2010-07-15 17:05:32 -07001370 len_w_vid = 104
1371 len = 100
1372 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
Rich Laned0478ff2013-03-11 12:46:58 -07001373 vlan_vid=old_vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001374 exp_pkt = simple_tcp_packet(pktlen=len)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001375 vid_act = ofp.action.strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001376
Rich Lane477f4812012-10-04 22:49:00 -07001377 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001378 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001379
Ken Chiange9a211d2012-04-20 14:52:11 -07001380class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1381 """
1382 Strip the VLAN tag from a tagged packet.
1383 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1384 """
1385 def runTest(self):
1386 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001387 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001388 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1389 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1390 return
1391
1392 len_w_vid = 104
1393 len_untagged = 100
1394 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
Rich Laned0478ff2013-03-11 12:46:58 -07001395 vlan_vid=old_vid)
Ken Chiange9a211d2012-04-20 14:52:11 -07001396 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
Ed Swierk99a74de2012-08-22 06:40:54 -07001397 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1398 ofp.OFPFW_DL_VLAN_PCP)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001399 vid_act = ofp.action.strip_vlan()
Ken Chiange9a211d2012-04-20 14:52:11 -07001400
Rich Lane477f4812012-10-04 22:49:00 -07001401 flow_match_test(self, config["port_map"],
Ed Swierk99a74de2012-08-22 06:40:54 -07001402 wildcards=wildcards,
Ken Chiange9a211d2012-04-20 14:52:11 -07001403 pkt=pkt, exp_pkt=exp_pkt,
1404 action_list=[vid_act])
1405
Dan Talayco4b2bee62010-07-20 14:10:05 -07001406def init_pkt_args():
1407 """
1408 Pass back a dictionary with default packet arguments
1409 """
1410 args = {}
Rich Laned0478ff2013-03-11 12:46:58 -07001411 args["eth_src"] = '00:23:45:67:89:AB'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001412
1413 dl_vlan_enable=False
Rich Laned0478ff2013-03-11 12:46:58 -07001414 vlan_vid=-1
Rich Lane477f4812012-10-04 22:49:00 -07001415 if config["test-params"]["vid"]:
Dan Talayco4b2bee62010-07-20 14:10:05 -07001416 dl_vlan_enable=True
Rich Laned0478ff2013-03-11 12:46:58 -07001417 vlan_vid = config["test-params"]["vid"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001418
1419# Unpack operator is ** on a dictionary
1420
1421 return args
1422
Dan Talayco551befa2010-07-15 17:05:32 -07001423class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001424 """
1425 Modify the source MAC address (TP1)
1426 """
Dan Talayco551befa2010-07-15 17:05:32 -07001427 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001428 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001429 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001430 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001431 return
1432
Rich Laned0478ff2013-03-11 12:46:58 -07001433 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_src'],
Dan Talayco4b2bee62010-07-20 14:10:05 -07001434 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001435 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001436 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001437
Dan Talayco551befa2010-07-15 17:05:32 -07001438class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001439 """
1440 Modify the dest MAC address (TP1)
1441 """
Dan Talayco551befa2010-07-15 17:05:32 -07001442 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001443 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001444 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001445 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001446 return
1447
Rich Laned0478ff2013-03-11 12:46:58 -07001448 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_dst'],
Dan Talayco4b2bee62010-07-20 14:10:05 -07001449 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001450 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001451 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001452
Dan Talayco551befa2010-07-15 17:05:32 -07001453class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001454 """
1455 Modify the source IP address of an IP packet (TP1)
1456 """
Dan Talayco551befa2010-07-15 17:05:32 -07001457 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001458 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001459 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001460 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001461 return
1462
1463 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1464 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001465 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001466 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001467
Dan Talayco551befa2010-07-15 17:05:32 -07001468class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001469 """
1470 Modify the dest IP address of an IP packet (TP1)
1471 """
Dan Talayco551befa2010-07-15 17:05:32 -07001472 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001473 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001474 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001475 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001476 return
1477
1478 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1479 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001480 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001481 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001482
1483class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001484 """
1485 Modify the source TCP port of a TCP packet (TP1)
1486 """
Dan Talayco551befa2010-07-15 17:05:32 -07001487 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001488 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001489 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001490 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001491 return
1492
1493 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1494 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001495 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001496 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001497
Rich Lane01c2b862012-10-26 16:26:25 -07001498class ModifyL4SrcUdp(BaseMatchCase):
1499 """
1500 Modify the source UDP port of a UDP packet
1501 """
1502 def runTest(self):
1503 sup_acts = self.supported_actions
1504 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1505 skip_message_emit(self, "ModifyL4SrcUdp test")
1506 return
1507
1508 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_sport'],
1509 check_test_params=True, tp="udp")
1510 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1511 action_list=acts, max_test=2)
1512
Dan Talayco551befa2010-07-15 17:05:32 -07001513class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001514 """
1515 Modify the dest TCP port of a TCP packet (TP1)
1516 """
Dan Talayco551befa2010-07-15 17:05:32 -07001517 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001518 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001519 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001520 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001521 return
1522
1523 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1524 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001525 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001526 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001527
Rich Lane01c2b862012-10-26 16:26:25 -07001528class ModifyL4DstUdp(BaseMatchCase):
1529 """
1530 Modify the dest UDP port of a UDP packet
1531 """
1532 def runTest(self):
1533 sup_acts = self.supported_actions
1534 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1535 skip_message_emit(self, "ModifyL4DstUdp test")
1536 return
1537
1538 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_dport'],
1539 check_test_params=True, tp="udp")
1540 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1541 action_list=acts, max_test=2)
1542
Dan Talayco551befa2010-07-15 17:05:32 -07001543class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001544 """
1545 Modify the IP type of service of an IP packet (TP1)
1546 """
Dan Talayco551befa2010-07-15 17:05:32 -07001547 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001548 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001549 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001550 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001551 return
Dan Talayco551befa2010-07-15 17:05:32 -07001552
Dan Talayco4b2bee62010-07-20 14:10:05 -07001553 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1554 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001555 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001556 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001557
Dan Talaycof6e76c02012-03-23 10:56:12 -07001558class ModifyL2DstMC(BaseMatchCase):
1559 """
1560 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001561 """
1562 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001563 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001564 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001565 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001566 return
1567
Rich Laned0478ff2013-03-11 12:46:58 -07001568 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_dst'],
Dan Talaycof6e76c02012-03-23 10:56:12 -07001569 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001570 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001571 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001572
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001573class ModifyL2DstIngress(BaseMatchCase):
1574 """
1575 Modify the L2 dest and send to the ingress port
1576 """
1577 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001578 sup_acts = self.supported_actions
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001579 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001580 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001581 return
1582
Rich Laned0478ff2013-03-11 12:46:58 -07001583 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_dst'],
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001584 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001585 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001586 action_list=acts, max_test=2, egr_count=0,
1587 ing_port=True)
1588
Dan Talaycod8ae7582012-03-23 12:24:56 -07001589class ModifyL2DstIngressMC(BaseMatchCase):
1590 """
1591 Modify the L2 dest and send to the ingress port
1592 """
1593 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001594 sup_acts = self.supported_actions
Dan Talaycod8ae7582012-03-23 12:24:56 -07001595 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1596 skip_message_emit(self, "ModifyL2dstMC test")
1597 return
1598
Rich Laned0478ff2013-03-11 12:46:58 -07001599 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_dst'],
Dan Talaycod8ae7582012-03-23 12:24:56 -07001600 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001601 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001602 action_list=acts, max_test=2, egr_count=-1,
1603 ing_port=True)
1604
Dan Talaycof6e76c02012-03-23 10:56:12 -07001605class ModifyL2SrcMC(BaseMatchCase):
1606 """
1607 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001608 """
1609 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001610 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001611 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001612 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001613 return
1614
Rich Laned0478ff2013-03-11 12:46:58 -07001615 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_src'],
Dan Talaycof6e76c02012-03-23 10:56:12 -07001616 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001617 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001618 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001619
1620class ModifyL2SrcDstMC(BaseMatchCase):
1621 """
1622 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001623 """
1624 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001625 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001626 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1627 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1628 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001629 return
1630
Rich Laned0478ff2013-03-11 12:46:58 -07001631 mod_fields = ['eth_dst', 'eth_src']
Dan Talaycof6e76c02012-03-23 10:56:12 -07001632 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1633 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001634 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001635 action_list=acts, max_test=2, egr_count=-1)
1636
1637class ModifyL2DstVIDMC(BaseMatchCase):
1638 """
1639 Modify the L2 dest and send to 2 ports
1640 """
1641 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001642 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001643 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1644 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1645 skip_message_emit(self, "ModifyL2DstVIDMC test")
1646 return
1647
Rich Laned0478ff2013-03-11 12:46:58 -07001648 mod_fields = ['eth_dst', 'vlan_vid']
Dan Talaycocfa172f2012-03-23 12:03:00 -07001649 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1650 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1651 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001652 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001653 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001654
Rich Lane97e99652013-01-02 17:23:20 -08001655@group("smoke")
Rich Lane22e74c12012-11-12 15:06:06 -08001656class ModifyAll(BaseMatchCase):
1657 """
1658 Modify all supported fields and output to a port
1659 """
1660 def runTest(self):
1661 sup_acts = self.supported_actions
1662
1663 sup_map = {
Rich Laned0478ff2013-03-11 12:46:58 -07001664 "eth_dst" : ofp.OFPAT_SET_DL_DST,
1665 "eth_src" : ofp.OFPAT_SET_DL_SRC,
Rich Lane22e74c12012-11-12 15:06:06 -08001666 "dl_vlan_enable" : ofp.OFPAT_SET_VLAN_VID,
Rich Laned0478ff2013-03-11 12:46:58 -07001667 "vlan_vid" : ofp.OFPAT_SET_VLAN_VID,
1668 "vlan_pcp" : ofp.OFPAT_SET_VLAN_PCP,
Rich Lane22e74c12012-11-12 15:06:06 -08001669 "ip_src" : ofp.OFPAT_SET_NW_SRC,
1670 "ip_dst" : ofp.OFPAT_SET_NW_DST,
1671 "ip_tos" : ofp.OFPAT_SET_NW_TOS,
1672 "tcp_sport" : ofp.OFPAT_SET_TP_SRC,
1673 "tcp_dport" : ofp.OFPAT_SET_TP_DST,
1674 }
1675
1676 mod_fields = [field for (field, bit) in sup_map.items() if (sup_acts & 1 << bit)]
1677 random.shuffle(mod_fields)
1678 start_field_vals = { "dl_vlan_enable" : True }
1679 mod_field_vals = { "dl_vlan_enable" : True }
1680 logging.info("modifying fields: %s" % repr(mod_fields))
1681
1682 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1683 mod_fields=mod_fields,
1684 start_field_vals=start_field_vals,
1685 mod_field_vals=mod_field_vals,
1686 check_test_params=True)
1687 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1688 action_list=acts, max_test=2)
1689
Dan Talaycofa6454f2012-04-05 10:04:13 -07001690class FlowToggle(BaseMatchCase):
1691 """
1692 Add flows to the table and modify them repeatedly
Dan Talaycof7c41312012-07-23 12:53:19 -07001693
1694 This is done by using only "add" flow messages. Since the check overlap
1695 flag is not set, the switch is supposed to modify the existing flow if
1696 the match already exists.
1697
1698 Would probably be better to exercise more of the flow modify commands
1699 (add, modify, delete +/- strict).
Dan Talaycofa6454f2012-04-05 10:04:13 -07001700 """
1701 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001702 flow_count = test_param_get('ft_flow_count', default=20)
1703 iter_count = test_param_get('ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001704
Rich Lane9a003812012-10-04 17:17:59 -07001705 logging.info("Running flow toggle with %d flows, %d iterations" %
Dan Talaycofa6454f2012-04-05 10:04:13 -07001706 (flow_count, iter_count))
1707 acts = []
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001708 acts.append(ofp.action.output())
1709 acts.append(ofp.action.output())
Dan Talaycofa6454f2012-04-05 10:04:13 -07001710
Rich Lane477f4812012-10-04 22:49:00 -07001711 of_ports = config["port_map"].keys()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001712 if len(of_ports) < 3:
1713 self.assertTrue(False, "Too few ports for test")
1714
1715 for idx in range(2):
1716 acts[idx].port = of_ports[idx]
1717
1718 flows = []
1719 flows.append([])
1720 flows.append([])
1721
Ed Swierk99a74de2012-08-22 06:40:54 -07001722 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_SRC |
1723 ofp.OFPFW_DL_DST)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001724 # Create up the flows in an array
1725 for toggle in range(2):
1726 for f_idx in range(flow_count):
1727 pkt = simple_tcp_packet(tcp_sport=f_idx)
Rich Laneba3f0e22013-03-11 16:43:57 -07001728 msg = ofp.message.flow_add()
Ed Swierk99a74de2012-08-22 06:40:54 -07001729 match = packet_to_flow_match(self, pkt)
Shudong Zhou031373c2012-07-19 17:37:42 -07001730 match.in_port = of_ports[2]
Dan Talayco50be7672012-04-05 11:38:08 -07001731 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001732 msg.match = match
1733 msg.buffer_id = 0xffffffff
Rich Lanec495d9e2013-03-08 17:43:36 -08001734 msg.actions.append(acts[toggle])
Dan Talaycofa6454f2012-04-05 10:04:13 -07001735 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001736
1737 # Show two sample flows
Rich Lane9a003812012-10-04 17:17:59 -07001738 logging.debug(flows[0][0].show())
1739 logging.debug(flows[1][0].show())
Dan Talayco50be7672012-04-05 11:38:08 -07001740
Dan Talaycofa6454f2012-04-05 10:04:13 -07001741 # Install the first set of flows
1742 for f_idx in range(flow_count):
Rich Lane5c3151c2013-01-03 17:15:41 -08001743 self.controller.message_send(flows[0][f_idx])
Rich Lane3a261d52013-01-03 17:45:08 -08001744 do_barrier(self.controller)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001745
Rich Lane9a003812012-10-04 17:17:59 -07001746 logging.info("Installed %d flows" % flow_count)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001747
1748 # Repeatedly modify all the flows back and forth
1749 updates = 0
1750 # Report status about 5 times
1751 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001752 start = time.time()
1753 for iter_idx in range(iter_count):
1754 if not iter_idx % mod_val:
Rich Lane9a003812012-10-04 17:17:59 -07001755 logging.info("Flow Toggle: iter %d of %d. " %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001756 (iter_idx, iter_count) +
1757 "%d updates in %d secs" %
1758 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001759 for toggle in range(2):
1760 t_idx = 1 - toggle
1761 for f_idx in range(flow_count):
Rich Lane5c3151c2013-01-03 17:15:41 -08001762 self.controller.message_send(flows[t_idx][f_idx])
Dan Talaycofa6454f2012-04-05 10:04:13 -07001763 updates += 1
Rich Lane3a261d52013-01-03 17:45:08 -08001764 do_barrier(self.controller)
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001765
1766 end = time.time()
1767 divisor = end - start or (end - start + 1)
Rich Lane9a003812012-10-04 17:17:59 -07001768 logging.info("Flow toggle: %d iterations" % iter_count)
1769 logging.info(" %d flow mods in %d secs, %d mods/sec" %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001770 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001771
1772
Dan Talayco8a64e332012-03-28 14:53:20 -07001773# You can pick and choose these by commenting tests in or out
1774iter_classes = [
1775 basic.PacketIn,
1776 basic.PacketOut,
1777 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001778 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001779 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001780 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001781 AllWildcardMatch,
1782 AllWildcardMatchTagged,
1783 SingleWildcardMatch,
1784 SingleWildcardMatchTagged,
1785 ExactMatch,
1786 ExactMatchTagged,
1787 SingleWildcardMatch,
1788 ModifyL2Src,
1789 ModifyL2Dst,
1790 ModifyL2SrcMC,
1791 ModifyL2DstMC,
1792 ModifyL2SrcDstMC
1793 ]
1794
Rich Lane0a4f6372013-01-02 14:40:22 -08001795@disabled
Dan Talayco8a64e332012-03-28 14:53:20 -07001796class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001797 """
1798 Iterate over a bunch of test cases
1799
1800 The cases come from the list above
1801 """
1802
Dan Talayco8a64e332012-03-28 14:53:20 -07001803 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001804 count = test_param_get('iter_count', default=10)
Dan Talayco8a64e332012-03-28 14:53:20 -07001805 tests_done = 0
Rich Lane9a003812012-10-04 17:17:59 -07001806 logging.info("Running iteration test " + str(count) + " times")
Dan Talayco8a64e332012-03-28 14:53:20 -07001807 start = time.time()
1808 last = start
1809 for idx in range(count):
Rich Lane9a003812012-10-04 17:17:59 -07001810 logging.info("Iteration " + str(idx + 1))
Dan Talayco8a64e332012-03-28 14:53:20 -07001811 for cls in iter_classes:
1812 test = cls()
1813 test.inheritSetup(self)
1814 test.runTest()
1815 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001816 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001817 if time.time() - last > 60:
1818 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001819 logging.info(
Dan Talaycofa6454f2012-04-05 10:04:13 -07001820 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1821 (idx, count, tests_done, last - start) +
1822 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001823 stats = all_stats_get(self)
1824 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001825 logging.info("\nIterCases ran %d tests in %d seconds." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001826 (tests_done, last - start))
Rich Lane9a003812012-10-04 17:17:59 -07001827 logging.info(" flows: %d. packets: %d. bytes: %d" %
Dan Talayco8a64e332012-03-28 14:53:20 -07001828 (stats["flows"], stats["packets"], stats["bytes"]))
Rich Lane9a003812012-10-04 17:17:59 -07001829 logging.info(" active: %d. lookups: %d. matched %d." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001830 (stats["active"], stats["lookups"], stats["matched"]))
1831
Dan Talayco4b2bee62010-07-20 14:10:05 -07001832#@todo Need to implement tagged versions of the above tests
1833#
1834#@todo Implement a test case that strips tag 2, adds tag 3
1835# and modifies tag 4 to tag 5. Then verify (in addition) that
1836# tag 6 does not get modified.
1837
Rich Lane0a4f6372013-01-02 14:40:22 -08001838@disabled
Dan Talayco4b2bee62010-07-20 14:10:05 -07001839class MixedVLAN(BaseMatchCase):
1840 """
1841 Test mixture of VLAN tag actions
1842
1843 Strip tag 2 on port 1, send to port 2
1844 Add tag 3 on port 1, send to port 2
1845 Modify tag 4 to 5 on port 1, send to port 2
1846 All other traffic from port 1, send to port 3
1847 All traffic from port 2 sent to port 4
1848 Use exact matches with different packets for all mods
1849 Verify the following: (port, vid)
1850 (port 1, vid 2) => VLAN tag stripped, out port 2
1851 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1852 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1853 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1854 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1855 (port 2, no tag) => untagged packet out port 4
1856 (port 2, vid 2-6) => unmodified packet out port 4
1857
1858 Variation: Might try sending VID 5 to port 3 and check.
1859 If only VID 5 distinguishes pkt, this will fail on some platforms
1860 """
1861
Rich Lane97e99652013-01-02 17:23:20 -08001862@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -07001863class MatchEach(base_tests.SimpleDataPlane):
Rich Lane8d6ab272012-09-23 18:06:20 -07001864 """
1865 Check that each match field is actually matched on.
1866 Installs two flows that differ in one field. The flow that should not
1867 match has a higher priority, so if that field is ignored during matching
1868 the packet will be sent out the wrong port.
1869
1870 TODO test UDP, ARP, ICMP, etc.
1871 """
1872 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001873 of_ports = config["port_map"].keys()
Rich Lane8d6ab272012-09-23 18:06:20 -07001874 of_ports.sort()
1875 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1876
Rich Lane9a003812012-10-04 17:17:59 -07001877 delete_all_flows(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001878
Rich Laned0478ff2013-03-11 12:46:58 -07001879 pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2)
Rich Lane8d6ab272012-09-23 18:06:20 -07001880 ingress_port = of_ports[0]
1881 egress_port = of_ports[1]
1882
1883 def testField(field, mask):
Rich Lane9a003812012-10-04 17:17:59 -07001884 logging.info("Testing field %s" % field)
Rich Lane8d6ab272012-09-23 18:06:20 -07001885
1886 def addFlow(matching, priority, output_port):
1887 match = packet_to_flow_match(self, pkt)
1888 self.assertTrue(match is not None, "Could not generate flow match from pkt")
1889 match.wildcards &= ~ofp.OFPFW_IN_PORT
1890 match.in_port = ingress_port
1891 if not matching:
1892 # Make sure flow doesn't match
1893 orig = getattr(match, field)
1894 if isinstance(orig, list):
1895 new = map(lambda a: ~a[0] & a[1], zip(orig, mask))
1896 else:
1897 new = ~orig & mask
1898 setattr(match, field, new)
Rich Laneba3f0e22013-03-11 16:43:57 -07001899 request = ofp.message.flow_add()
Rich Lane8d6ab272012-09-23 18:06:20 -07001900 request.match = match
1901 request.buffer_id = 0xffffffff
1902 request.priority = priority
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001903 act = ofp.action.output()
Rich Lane8d6ab272012-09-23 18:06:20 -07001904 act.port = output_port
Rich Lanec495d9e2013-03-08 17:43:36 -08001905 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -07001906 logging.info("Inserting flow")
Rich Lane8d6ab272012-09-23 18:06:20 -07001907 self.controller.message_send(request)
1908
1909 # This flow should match.
1910 addFlow(matching=True, priority=0, output_port=egress_port)
1911 # This flow should not match, but it has a higher priority.
1912 addFlow(matching=False, priority=1, output_port=ofp.OFPP_IN_PORT)
1913
Rich Lane3a261d52013-01-03 17:45:08 -08001914 do_barrier(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001915
Rich Lane9a003812012-10-04 17:17:59 -07001916 logging.info("Sending packet to dp port " + str(ingress_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001917 self.dataplane.send(ingress_port, str(pkt))
1918
1919 exp_pkt_arg = None
1920 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -07001921 if config["relax"]:
Rich Lane8d6ab272012-09-23 18:06:20 -07001922 exp_pkt_arg = pkt
1923 exp_port = egress_port
1924
1925 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
1926 exp_pkt=exp_pkt_arg)
1927 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -07001928 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001929 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
1930 self.assertEqual(str(pkt), str(rcv_pkt), 'Response packet does not match send packet')
1931
Ed Swierkb603b192012-12-12 15:38:49 -08001932 wildcards = required_wildcards(self)
Rich Lane8d6ab272012-09-23 18:06:20 -07001933 # TODO in_port
Ed Swierkb603b192012-12-12 15:38:49 -08001934 if not (wildcards & ofp.OFPFW_DL_SRC):
Rich Laned0478ff2013-03-11 12:46:58 -07001935 testField("eth_src", [0xff]*6)
Ed Swierkb603b192012-12-12 15:38:49 -08001936 if not (wildcards & ofp.OFPFW_DL_DST):
Rich Laned0478ff2013-03-11 12:46:58 -07001937 testField("eth_dst", [0xff]*6)
Ed Swierkb603b192012-12-12 15:38:49 -08001938 if not (wildcards & ofp.OFPFW_DL_TYPE):
Rich Laned0478ff2013-03-11 12:46:58 -07001939 testField("eth_type", 0xffff)
Ed Swierkb603b192012-12-12 15:38:49 -08001940 if not (wildcards & ofp.OFPFW_DL_VLAN):
Rich Laned0478ff2013-03-11 12:46:58 -07001941 testField("vlan_vid", 0xfff)
1942 # TODO vlan_pcp
Ed Swierkb603b192012-12-12 15:38:49 -08001943 if not (wildcards & ofp.OFPFW_NW_SRC_ALL):
Rich Laned0478ff2013-03-11 12:46:58 -07001944 testField("ipv4_src", 0xffffffff)
Ed Swierkb603b192012-12-12 15:38:49 -08001945 if not (wildcards & ofp.OFPFW_NW_DST_ALL):
Rich Laned0478ff2013-03-11 12:46:58 -07001946 testField("ipv4_dst", 0xffffffff)
Ed Swierkb603b192012-12-12 15:38:49 -08001947 if not (wildcards & ofp.OFPFW_NW_TOS):
Rich Laned0478ff2013-03-11 12:46:58 -07001948 testField("ip_dscp", 0x3f)
Ed Swierkb603b192012-12-12 15:38:49 -08001949 if not (wildcards & ofp.OFPFW_NW_PROTO):
Rich Laned0478ff2013-03-11 12:46:58 -07001950 testField("ip_proto", 0xff)
Ed Swierkb603b192012-12-12 15:38:49 -08001951 if not (wildcards & ofp.OFPFW_TP_SRC):
Rich Laned0478ff2013-03-11 12:46:58 -07001952 testField("tcp_src", 0xffff)
Ed Swierkb603b192012-12-12 15:38:49 -08001953 if not (wildcards & ofp.OFPFW_TP_DST):
Rich Laned0478ff2013-03-11 12:46:58 -07001954 testField("tcp_dst", 0xffff)
Rich Lane8d6ab272012-09-23 18:06:20 -07001955
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07001956class DirectBadPacketBase(base_tests.SimpleDataPlane):
1957 """
1958 Base class for sending single packets with single flow table entries.
1959 Used to verify matching of unusual packets and parsing/matching of
1960 corrupted packets.
1961
1962 The idea is to generate packets that may either be totally malformed or
1963 malformed just enough to trick the flow matcher into making mistakes.
1964
1965 Generate a 'bad' packet
1966 Generate and install a matching flow
1967 Add action to direct the packet to an egress port
1968 Send the packet to ingress dataplane port
1969 Verify the packet is received at the egress port only
1970 """
1971
1972 RESULT_MATCH = "MATCH"
1973 RESULT_NOMATCH = "NO MATCH"
1974 RESULT_ANY = "ANY MATCH"
1975
1976 def runTest(self):
1977 pass
1978 # TODO:
1979 # - ICMP?
1980 # - VLAN?
1981 # - action
1982
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07001983 def createMatch(self, **kwargs):
Rich Lane0237baf2013-03-11 22:34:59 -07001984 match = ofp.match()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07001985 match.wildcards = ofp.OFPFW_ALL
1986 fields = {
Rich Laned0478ff2013-03-11 12:46:58 -07001987 'eth_dst': ofp.OFPFW_DL_DST,
1988 'eth_src': ofp.OFPFW_DL_SRC,
1989 'eth_type': ofp.OFPFW_DL_TYPE,
1990 'vlan_vid': ofp.OFPFW_DL_VLAN,
1991 'ipv4_src': ofp.OFPFW_NW_SRC_MASK,
1992 'ipv4_dst': ofp.OFPFW_NW_DST_MASK,
1993 'ip_dscp': ofp.OFPFW_NW_TOS,
1994 'ip_proto': ofp.OFPFW_NW_PROTO,
1995 'tcp_src': ofp.OFPFW_TP_SRC,
1996 'tcp_dst': ofp.OFPFW_TP_DST,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07001997 }
1998 for key in kwargs:
1999 setattr(match, key, kwargs[key])
2000 match.wildcards &= ~fields[key]
2001 return match
2002
2003 def testPktsAgainstFlow(self, pkts, acts, match):
2004 if type(acts) != list:
2005 acts = [acts]
2006 for info in pkts:
2007 title, pkt, expected_result = info
2008 self.testPktAgainstFlow(title, pkt, acts, match, expected_result)
2009
2010 def testPktAgainstFlow(self, title, pkt, acts, match, expected_result):
2011 of_ports = config["port_map"].keys()
2012 of_ports.sort()
2013 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
2014
Rich Lane32bf9482013-01-03 17:26:30 -08002015 delete_all_flows(self.controller)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002016
2017 ingress_port = of_ports[0]
2018 egress_port = of_ports[1]
2019
2020 logging.info("Testing packet '%s', expect result %s" %
2021 (title, expected_result))
2022 logging.info("Ingress %s to egress %s" %
2023 (str(ingress_port), str(egress_port)))
2024 logging.info("Packet:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002025 logging.info(inspect_packet(pkt))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002026
2027 match.in_port = ingress_port
2028
Rich Laneba3f0e22013-03-11 16:43:57 -07002029 request = ofp.message.flow_add()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002030 request.match = match
Rich Lane44cf12d2012-10-15 11:10:45 -07002031 request.priority = 1
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002032
2033 request.buffer_id = 0xffffffff
2034 for act in acts:
2035 act.port = egress_port
Rich Lanec495d9e2013-03-08 17:43:36 -08002036 request.actions.append(act)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002037
2038 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08002039 self.controller.message_send(request)
Rich Lane44cf12d2012-10-15 11:10:45 -07002040
2041 # This flow speeds up negative tests
2042 logging.info("Inserting catch-all flow")
Rich Laneba3f0e22013-03-11 16:43:57 -07002043 request2 = ofp.message.flow_add()
Rich Lane44cf12d2012-10-15 11:10:45 -07002044 request2.match = self.createMatch()
Dan Talayco3bfc8222013-02-13 18:18:57 -08002045 request2.match.wildcards &= ~ofp.OFPFW_IN_PORT
2046 request2.match.in_port = ingress_port
2047
Rich Lane44cf12d2012-10-15 11:10:45 -07002048 request2.priority = 0
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002049 act = ofp.action.output()
Rich Lane44cf12d2012-10-15 11:10:45 -07002050 act.port = ofp.OFPP_IN_PORT
Rich Lanec495d9e2013-03-08 17:43:36 -08002051 request2.actions.append(act)
Rich Lane5c3151c2013-01-03 17:15:41 -08002052 self.controller.message_send(request2)
Rich Lane44cf12d2012-10-15 11:10:45 -07002053
Rich Lane3a261d52013-01-03 17:45:08 -08002054 do_barrier(self.controller)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002055
Dan Talayco3bfc8222013-02-13 18:18:57 -08002056 pkt_str = str(pkt)
2057 if config["minsize"] > len(str(pkt)):
2058 pkt_str += '0' * (config["minsize"] - len(str(pkt)))
2059
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002060 logging.info("Sending packet to dp port " +
2061 str(ingress_port))
Dan Talayco3bfc8222013-02-13 18:18:57 -08002062 self.dataplane.send(ingress_port, pkt_str)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002063
2064 exp_pkt_arg = None
2065 exp_port = None
2066 if config["relax"]:
2067 exp_pkt_arg = pkt
2068 exp_port = egress_port
2069
Rich Lane44cf12d2012-10-15 11:10:45 -07002070 if expected_result == self.RESULT_MATCH:
2071 timeout = -1 # default timeout
2072 else:
2073 timeout = 1 # short timeout for negative tests
2074
2075 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(exp_pkt=exp_pkt_arg,
2076 timeout=timeout)
2077 if rcv_port == ingress_port:
2078 logging.debug("Packet matched catch-all flow")
2079 rcv_pkt = None
2080
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002081 if expected_result == self.RESULT_MATCH:
2082 self.assertTrue(rcv_pkt is not None,
2083 "Did not receive packet, expected a match")
2084 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
2085 str(rcv_port))
2086 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
2087 str_pkt = str(pkt)
2088 str_rcv_pkt = str(rcv_pkt)
2089 str_rcv_pkt = str_rcv_pkt[0:len(str_pkt)]
2090 if str_pkt != str_rcv_pkt:
2091 logging.error("Response packet does not match send packet")
2092 logging.info("Response:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002093 logging.info(inspect_packet(scapy.Ether(rcv_pkt)))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002094 self.assertEqual(str_pkt, str_rcv_pkt,
2095 'Response packet does not match send packet')
2096 elif expected_result == self.RESULT_NOMATCH:
2097 self.assertTrue(rcv_pkt is None, "Received packet, expected drop")
2098 else:
2099 logging.debug("Match or drop accepted. Result = %s" %
2100 ("match" if rcv_pkt is not None else "drop"))
2101
2102
2103class DirectBadIpTcpPacketsBase(DirectBadPacketBase):
2104 """
2105 Base class for TCP and UDP parsing/matching verification under corruptions
2106 """
2107 def runTest(self):
2108 pass
2109
2110 def runTestWithProto(self, protoName = 'TCP'):
Rich Laned0478ff2013-03-11 12:46:58 -07002111 eth_dst='00:01:02:03:04:05'
2112 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002113 ip_src='192.168.0.1'
2114 ip_dst='192.168.0.2'
2115 ip_tos=0
2116 tcp_sport=1234
2117 tcp_dport=80
2118
2119 # Generate a proper packet for constructing a match
2120 tp = None
2121 if protoName == 'TCP':
2122 tp = scapy.TCP
2123 proto = 6
2124 elif protoName == 'UDP':
2125 tp = scapy.UDP
2126 proto = 17
2127 else:
2128 raise Exception("Passed in unknown proto name")
2129
Rich Laned0478ff2013-03-11 12:46:58 -07002130 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002131 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2132 tp(sport=tcp_sport, dport=tcp_dport)
2133 match = packet_to_flow_match(self, match_pkt)
2134 self.assertTrue(match is not None,
2135 "Could not generate flow match from pkt")
2136 match.wildcards &= ~ofp.OFPFW_IN_PORT
2137
2138 def testPacket(title, pkt, result):
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002139 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002140 pkts = [
2141 [title, pkt, result]
2142 ]
2143 self.testPktsAgainstFlow(pkts, act, match)
2144
2145 # Try incomplete IP headers
2146 testPacket("Incomplete IP header (1 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002147 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002148 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:1],
2149 self.RESULT_NOMATCH,
2150 )
2151 testPacket("Incomplete IP header (2 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002152 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002153 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:2],
2154 self.RESULT_NOMATCH,
2155 )
2156 testPacket("Incomplete IP header (3 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002157 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002158 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:3],
2159 self.RESULT_NOMATCH,
2160 )
2161 testPacket("Incomplete IP header (12 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002162 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002163 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:12],
2164 self.RESULT_NOMATCH,
2165 )
2166 testPacket("Incomplete IP header (16 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002167 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002168 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:16],
2169 self.RESULT_NOMATCH,
2170 )
2171 testPacket("Incomplete IP header (19 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002172 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002173 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:19],
2174 self.RESULT_NOMATCH,
2175 )
2176
2177 # Try variations where the TCP header is missing or incomplete. As we
2178 # saw bugs before where buffers were reused and lengths weren't honored,
2179 # we initiatlize once with a non-matching full packet and once with a
2180 # matching full packet.
2181 testPacket("Non-Matching TCP packet, warming buffer",
Rich Laned0478ff2013-03-11 12:46:58 -07002182 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002183 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2184 tp(sport=tcp_sport, dport=tcp_dport + 1),
2185 self.RESULT_NOMATCH,
2186 )
2187 testPacket("Missing TCP header, buffer warmed with non-match",
Rich Laned0478ff2013-03-11 12:46:58 -07002188 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002189 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2190 self.RESULT_NOMATCH,
2191 )
2192 testPacket("Matching TCP packet, warming buffer",
Rich Laned0478ff2013-03-11 12:46:58 -07002193 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002194 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2195 tp(sport=tcp_sport, dport=tcp_dport),
2196 self.RESULT_MATCH,
2197 )
2198 testPacket("Missing TCP header, buffer warmed with match",
Rich Laned0478ff2013-03-11 12:46:58 -07002199 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002200 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2201 self.RESULT_NOMATCH,
2202 )
2203 testPacket("Truncated TCP header: 2 bytes",
Rich Laned0478ff2013-03-11 12:46:58 -07002204 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002205 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2206 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:2]),
2207 self.RESULT_NOMATCH,
2208 )
2209
2210 # Play with IP header length values that put the start of TCP either
2211 # inside the generated TCP header or beyond. In some cases it may even
2212 # be beyond the packet boundary. Also play with IP options and more
2213 # importantly IP total length corruptions.
2214 testPacket("TCP packet, corrupt ihl (0x6)",
2215 simple_tcp_packet(ip_ihl=6),
2216 self.RESULT_NOMATCH,
2217 )
2218 testPacket("TCP packet, corrupt ihl (0xf)",
2219 simple_tcp_packet(ip_ihl=0xf), # ihl = 15 * 4 = 60
2220 self.RESULT_NOMATCH,
2221 )
2222 testPacket("TCP packet, corrupt ihl and total length",
2223 simple_tcp_packet(ip_ihl=0xf, pktlen=56), # ihl = 15 * 4 = 60,
2224 self.RESULT_NOMATCH,
2225 )
2226 testPacket("Corrupt IPoption: First 4 bytes of matching TCP header",
2227 simple_tcp_packet(
2228 ip_options=scapy.IPOption('\x04\xd2\x00\x50'),
2229 tcp_dport=2, tcp_sport=2
2230 ),
2231 self.RESULT_NOMATCH,
2232 )
2233 testPacket("Missing TCP header, corrupt ihl",
Rich Laned0478ff2013-03-11 12:46:58 -07002234 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002235 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto),
2236 self.RESULT_NOMATCH,
2237 )
2238 testPacket("Missing TCP header, corrupt total length",
Rich Laned0478ff2013-03-11 12:46:58 -07002239 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002240 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, len= 100),
2241 self.RESULT_NOMATCH,
2242 )
2243 testPacket("Missing TCP header, corrupt ihl and total length",
Rich Laned0478ff2013-03-11 12:46:58 -07002244 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002245 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto, len=43),
2246 self.RESULT_NOMATCH,
2247 )
2248 testPacket("Incomplete IP header (12 bytes), corrupt ihl and total length",
Rich Laned0478ff2013-03-11 12:46:58 -07002249 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002250 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:12],
2251 self.RESULT_NOMATCH,
2252 )
2253 testPacket("Incomplete IP header (16 bytes), corrupt ihl and total length",
Rich Laned0478ff2013-03-11 12:46:58 -07002254 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002255 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:16],
2256 self.RESULT_NOMATCH,
2257 )
2258
2259 # Try an incomplete TCP header that has enough bytes to carry source and
2260 # destination ports. As that is all we care about during matching, some
2261 # implementations may match and some may drop the packet
2262 testPacket("Incomplete TCP header: src/dst port present",
Rich Laned0478ff2013-03-11 12:46:58 -07002263 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002264 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2265 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:4]),
2266 self.RESULT_ANY,
2267 )
2268
2269 for i in range(1):
2270 for length in range(40 / 4): # IPv4 options are a maximum of 40 in length
2271 bytes = "".join([("%c" % random.randint(0, 255)) for x in range(length * 4)])
Rich Laned0478ff2013-03-11 12:46:58 -07002272 eth = scapy.Ether(dst=eth_dst, src=eth_src)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002273 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2274 tcp = tp(sport=tcp_sport, dport=tcp_dport+1)
2275 pkt = eth / ip
2276 pkt = pkt / bytes
2277 pkt = pkt / str(tcp)
2278 testPacket("Random IP options len = %d - TP match must fail" % length * 4,
2279 pkt,
2280 self.RESULT_NOMATCH
2281 )
2282
Rich Laned0478ff2013-03-11 12:46:58 -07002283 eth = scapy.Ether(dst=eth_dst, src=eth_src)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002284 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2285 tcp = tp(sport=tcp_sport, dport=tcp_dport)
2286 pkt = eth / ip
2287 pkt = pkt / bytes
2288 pkt = pkt / str(tcp)
2289
2290 testPacket("Random IP options len = %d - May match",
2291 pkt,
2292 self.RESULT_ANY
2293 )
2294
2295
2296class DirectBadIpTcpPackets(DirectBadIpTcpPacketsBase):
2297 """
2298 Verify IP/TCP parsing and matching. Focus on packet corruptions
2299 """
2300 def runTest(self):
2301 self.runTestWithProto(protoName = 'TCP')
2302
2303class DirectBadIpUdpPackets(DirectBadIpTcpPacketsBase):
2304 """
2305 Verify IP/UDP parsing and matching. Focus on packet corruptions
2306 """
2307 def runTest(self):
2308 self.runTestWithProto(protoName = 'UDP')
2309
2310class DirectBadLlcPackets(DirectBadPacketBase):
2311 """
2312 Verify LLC/SNAP parsing and matching. Focus on packet corruptions
2313 """
2314 def runTest(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002315 eth_dst='00:01:02:03:04:05'
2316 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002317 ip_src='192.168.0.1'
2318 ip_dst='192.168.0.2'
2319 ip_tos=0
2320 tcp_sport=1234
2321 tcp_dport=80
2322
2323 IS_SNAP_IP = 1
2324 IS_SNAP_IP_CORRUPT = 2
2325 IS_NOT_SNAP_IP = 3
2326
2327 def testPacketTcpMatch(title, llc):
Rich Laned0478ff2013-03-11 12:46:58 -07002328 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002329 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2330 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
2331 match = packet_to_flow_match(self, match_pkt)
2332 self.assertTrue(match is not None,
2333 "Could not generate flow match from pkt")
2334 match.wildcards &= ~ofp.OFPFW_IN_PORT
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002335 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002336
2337 self.testPktsAgainstFlow(
2338 [[
2339 "TCP match - LLC frame correct length - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002340 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002341 self.RESULT_ANY,
2342 ]],
2343 act, match
2344 )
2345
2346 # Corrupt length field
2347 ethLen = random.randint(0, 1535)
2348 self.testPktsAgainstFlow(
2349 [[
2350 "TCP match - LLC frame corrupted length - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002351 scapy.Ether(dst=eth_dst, src=eth_src, type=ethLen) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002352 self.RESULT_ANY,
2353 ]],
2354 act, match
2355 )
2356
2357 def testPacketEthSrcDstMatch(title, llc):
2358 # Matching based on Ethernet source and destination
Rich Laned0478ff2013-03-11 12:46:58 -07002359 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002360 match = packet_to_flow_match(self, match_pkt)
2361 self.assertTrue(match is not None,
2362 "Could not generate flow match from pkt")
2363 match.wildcards &= ~ofp.OFPFW_IN_PORT
2364 match.wildcards |= ofp.OFPFW_DL_TYPE
2365 self.testPktsAgainstFlow(
2366 [[
2367 "Eth addr match - LLC frame correct length- %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002368 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002369 self.RESULT_MATCH,
2370 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002371 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002372 )
2373
2374 # Corrupt length field
2375 ethLen = random.randint(0, 1535)
2376 self.testPktsAgainstFlow(
2377 [[
2378 "Eth addr match - LLC frame corrupted length- %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002379 scapy.Ether(dst=eth_dst, src=eth_src, type=ethLen) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002380 self.RESULT_ANY,
2381 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002382 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002383 )
2384
2385 def testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip):
2386 # Matching based on Ethernet source, destination and type
Rich Laned0478ff2013-03-11 12:46:58 -07002387 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=0x800)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002388 match = packet_to_flow_match(self, match_pkt)
2389 self.assertTrue(match is not None,
2390 "Could not generate flow match from pkt")
2391 match.wildcards &= ~ofp.OFPFW_IN_PORT
2392 if is_snap_ip == IS_SNAP_IP:
2393 is_match = self.RESULT_MATCH
2394 elif is_snap_ip == IS_SNAP_IP_CORRUPT:
2395 is_match = self.RESULT_ANY
2396 else:
2397 is_match = self.RESULT_NOMATCH
2398 self.testPktsAgainstFlow(
2399 [[
2400 "Eth addr+type match - LLC frame correct length - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002401 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002402 is_match,
2403 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002404 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002405 )
2406
2407 # Corrupt length field
2408 ethLen = random.randint(0, 1535)
2409 self.testPktsAgainstFlow(
2410 [[
2411 "Eth addr+type match - LLC frame corrupted length - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002412 scapy.Ether(dst=eth_dst, src=eth_src, type=ethLen) / llc,
Christian Dickmanne9b6d252012-10-08 22:56:50 -07002413 self.RESULT_ANY,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002414 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002415 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002416 )
2417
2418 def testPacket(title, llc, is_snap_ip):
2419 testPacketTcpMatch(title, llc)
2420 testPacketEthSrcDstMatch(title, llc)
2421 testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip)
2422
2423 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002424 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002425 IS_NOT_SNAP_IP,
2426 )
2427 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002428 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002429 IS_NOT_SNAP_IP,
2430 )
2431 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002432 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002433 IS_NOT_SNAP_IP,
2434 )
2435 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002436 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002437 IS_NOT_SNAP_IP,
2438 )
2439 testPacket("LLC - SNAP - Small bogus payload",
2440 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2441 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2442 IS_SNAP_IP_CORRUPT,
2443 )
2444 testPacket("LLC - SNAP - Max -1 bogus payload",
2445 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2446 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2447 IS_NOT_SNAP_IP,
2448 )
2449 testPacket("LLC - SNAP - Max bogus payload",
2450 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2451 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2452 IS_NOT_SNAP_IP,
2453 )
2454 testPacket("LLC - SNAP - IP - TCP",
2455 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2456 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2457 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2458 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2459 IS_SNAP_IP,
2460 )
2461
2462
2463class DirectLlcPackets(DirectBadPacketBase):
2464 """
2465 Verify LLC/SNAP parsing (valid and corrupted packets) and matching
2466 """
2467 def runTest(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002468 eth_dst='00:01:02:03:04:05'
2469 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002470 ip_src='192.168.0.1'
2471 ip_dst='192.168.0.2'
2472 ip_tos=0
2473 tcp_sport=1234
2474 tcp_dport=80
2475
2476 # Test ethertype in face of LLC/SNAP and OFP_DL_TYPE_NOT_ETH_TYPE
2477 IS_SNAP_NOT_IP = 1
2478 IS_SNAP_AND_IP = 2
2479 IS_NOT_SNAP = 3
2480
2481 def testPacketEthTypeIP(title, llc, is_snap):
Rich Laned0478ff2013-03-11 12:46:58 -07002482 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=0x800)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002483 match = packet_to_flow_match(self, match_pkt)
2484 self.assertTrue(match is not None,
2485 "Could not generate flow match from pkt")
2486 match.wildcards &= ~ofp.OFPFW_IN_PORT
2487 pkts = []
2488 if is_snap == IS_NOT_SNAP or is_snap == IS_SNAP_NOT_IP:
2489 result = self.RESULT_NOMATCH
2490 else:
2491 result = self.RESULT_MATCH
2492 pkts.append([
2493 "Ether type 0x800 match - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002494 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002495 result,
2496 ])
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002497 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002498 self.testPktsAgainstFlow(pkts, act, match)
2499
2500 def testPacketEthTypeNotEth(title, llc, is_snap):
Rich Laned0478ff2013-03-11 12:46:58 -07002501 match_pkt = scapy.Ether(dst = eth_dst, src = eth_src,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002502 type = ofp.OFP_DL_TYPE_NOT_ETH_TYPE)
2503 match = packet_to_flow_match(self, match_pkt)
2504 self.assertTrue(match is not None,
2505 "Could not generate flow match from pkt")
2506 match.wildcards &= ~ofp.OFPFW_IN_PORT
2507 pkts = []
2508 if is_snap == IS_NOT_SNAP:
2509 result = self.RESULT_MATCH
2510 else:
2511 result = self.RESULT_NOMATCH
2512 pkts.append([
2513 "Ether type OFP_DL_TYPE_NOT_ETH_TYPE match - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002514 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002515 result,
2516 ])
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002517 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002518 self.testPktsAgainstFlow(pkts, act, match)
2519
2520 def testPacket(title, llc, is_snap):
2521 testPacketEthTypeIP(title, llc, is_snap)
2522 testPacketEthTypeNotEth(title, llc, is_snap)
2523
2524 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002525 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
2526 IS_NOT_SNAP,
2527 )
2528 testPacket("LLC (with information field) - No SNAP - No Payload",
2529 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x12) / "S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002530 IS_NOT_SNAP,
2531 )
2532 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002533 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002534 IS_NOT_SNAP,
2535 )
2536 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002537 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002538 IS_NOT_SNAP,
2539 )
2540 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002541 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002542 IS_NOT_SNAP,
2543 )
2544 testPacket("LLC - SNAP - Non-default OUI",
2545 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2546 scapy.SNAP(OUI=0x000001, code=0x800) / ("S" * 10),
2547 IS_NOT_SNAP,
2548 )
2549 testPacket("LLC - SNAP - Default OUI",
2550 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2551 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2552 IS_SNAP_AND_IP,
2553 )
2554 testPacket("LLC - SNAP - Max -1 bogus payload",
2555 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2556 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2557 IS_SNAP_NOT_IP,
2558 )
2559 testPacket("LLC - SNAP - Max bogus payload",
2560 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2561 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2562 IS_SNAP_NOT_IP,
2563 )
2564 testPacket("LLC - SNAP - IP - TCP",
2565 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2566 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2567 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2568 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2569 IS_SNAP_AND_IP,
2570 )
2571
2572
2573class DirectArpPackets(DirectBadPacketBase):
2574 """
2575 Verify ARP parsing (valid and corrupted packets) and ARP matching
2576 """
2577 def runTest(self):
2578 self.testArpHandling()
2579
2580 def testArpHandling(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002581 eth_dst='00:01:02:03:04:05'
2582 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002583 ip_src='192.168.0.1'
2584 ip_dst='192.168.0.2'
2585 ip_src2='192.168.1.1'
2586 ip_dst2='192.168.1.2'
2587 ip_tos=0
2588 tcp_sport=1234
2589 tcp_dport=80
2590
2591 def testPacket(title, arp_match, arp_pkt, result):
2592 pkts = []
2593
Rich Laned0478ff2013-03-11 12:46:58 -07002594 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src) / arp_match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002595 match = packet_to_flow_match(self, match_pkt)
2596 self.assertTrue(match is not None,
2597 "Could not generate flow match from pkt")
2598 match.wildcards &= ~ofp.OFPFW_IN_PORT
2599
2600 pkts.append([
2601 title,
Rich Laned0478ff2013-03-11 12:46:58 -07002602 scapy.Ether(dst=eth_dst, src=eth_src) / arp_pkt,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002603 result,
2604 ])
2605
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002606 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002607 self.testPktsAgainstFlow(pkts, act, match)
2608
2609 testPacket("Basic ARP",
2610 scapy.ARP(psrc=ip_src, pdst=ip_dst, op = 1),
Rich Laned0478ff2013-03-11 12:46:58 -07002611 scapy.ARP(hwdst = '00:00:00:00:00:00', hwsrc = eth_src,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002612 psrc = ip_src, pdst = ip_dst, hwlen = 6, plen = 4,
2613 ptype = 0x800, hwtype = 1, op = 1),
2614 self.RESULT_MATCH
2615 )
2616 # More stuff:
2617 # - Non matches on any property
2618 # - Corrupted hwlen and plen
2619 # - Other hwtype, ptype
2620 # - Truncated ARP pkt
2621
2622
2623class DirectVlanPackets(DirectBadPacketBase):
2624 """
2625 Verify VLAN parsing (valid and corrupted packets) and ARP matching
2626 """
2627 def runTest(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002628 eth_dst='00:01:02:03:04:05'
2629 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002630 ip_src='192.168.0.1'
2631 ip_dst='192.168.0.2'
2632 ip_src2='192.168.1.1'
2633 ip_dst2='192.168.1.2'
2634 ip_tos=0
2635 tcp_sport=1234
2636 tcp_dport=80
2637
2638 def testPacket(title, match, pkt, result):
2639 pkts = []
2640
2641 self.assertTrue(match is not None,
2642 "Could not generate flow match from pkt")
2643 match.wildcards &= ~ofp.OFPFW_IN_PORT
2644
2645 pkts.append([
2646 "%s" % title,
2647 pkt,
2648 result,
2649 ])
2650
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002651 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002652 self.testPktsAgainstFlow(pkts, act, match)
2653
2654 testPacket("Basic MAC matching - IPv4 payload",
Rich Laned0478ff2013-03-11 12:46:58 -07002655 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2656 scapy.Ether(dst=eth_dst, src=eth_src, type=0x800) / scapy.IP(),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002657 self.RESULT_MATCH
2658 )
2659 testPacket("Basic MAC matching - VMware beacon - no payload",
Rich Laned0478ff2013-03-11 12:46:58 -07002660 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2661 scapy.Ether(dst=eth_dst, src=eth_src, type=0x8922),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002662 self.RESULT_MATCH
2663 )
2664 testPacket("Basic MAC matching - VMware beacon - with payload",
Rich Laned0478ff2013-03-11 12:46:58 -07002665 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2666 scapy.Ether(dst=eth_dst, src=eth_src, type=0x8922)/ ("X" * 1),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002667 self.RESULT_MATCH
2668 )
2669 testPacket("Basic MAC matching - IPv6 payload",
Rich Laned0478ff2013-03-11 12:46:58 -07002670 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2671 scapy.Ether(dst=eth_dst, src=eth_src) / scapy.IPv6(),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002672 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 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002677 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002678 scapy.IP(),
2679 self.RESULT_MATCH
2680 )
2681 testPacket("Basic MAC matching with VLAN tag present",
Rich Laned0478ff2013-03-11 12:46:58 -07002682 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2683 eth_type=0x800),
2684 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002685 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002686 scapy.IP(),
2687 self.RESULT_MATCH
2688 )
2689 testPacket("Ether matching with VLAN tag present - No type match",
Rich Laned0478ff2013-03-11 12:46:58 -07002690 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2691 eth_type=0x801),
2692 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002693 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002694 scapy.IP(),
2695 self.RESULT_NOMATCH
2696 )
2697 testPacket("Ether matching with VLAN tag present - No type match 0x8100",
Rich Laned0478ff2013-03-11 12:46:58 -07002698 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2699 eth_type=0x8100),
2700 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002701 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002702 scapy.IP(),
2703 self.RESULT_NOMATCH
2704 )
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002705 testPacket("IP matching - VLAN tag",
Rich Laned0478ff2013-03-11 12:46:58 -07002706 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2707 eth_type=0x0800,
2708 ipv4_src=parse_ip(ip_src), ipv4_dst=parse_ip(ip_dst)),
2709 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002710 scapy.Dot1Q(prio=5, vlan=1000)/ \
2711 scapy.IP(src=ip_src, dst=ip_dst),
2712 self.RESULT_MATCH
2713 )
2714 # XXX:
2715 # - Matching on VLAN ID and Prio
2716 # - Actions
2717
2718@nonstandard
2719class DirectVlanPacketsDoubleTagged(DirectVlanPackets):
2720 """
2721 VLAN parsing for double tagged packets. Spec is ambiguous about
2722 the treatment of these cases, so broken out to be non-standard
2723 """
2724 def runTest(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002725 eth_dst='00:01:02:03:04:05'
2726 eth_src='00:06:07:08:09:0a'
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002727 ip_src='192.168.0.1'
2728 ip_dst='192.168.0.2'
2729 ip_src2='192.168.1.1'
2730 ip_dst2='192.168.1.2'
2731 ip_tos=0
2732 tcp_sport=1234
2733 tcp_dport=80
2734
2735 def testPacket(title, match, pkt, result):
2736 pkts = []
2737
2738 self.assertTrue(match is not None,
2739 "Could not generate flow match from pkt")
2740 match.wildcards &= ~ofp.OFPFW_IN_PORT
2741
2742 pkts.append([
2743 "%s" % title,
2744 pkt,
2745 result,
2746 ])
2747
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002748 act = ofp.action.output()
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002749 self.testPktsAgainstFlow(pkts, act, match)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002750 testPacket("Ether matching with double VLAN tag - Wrong type match",
Rich Laned0478ff2013-03-11 12:46:58 -07002751 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2752 eth_type=0x800),
2753 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002754 scapy.Dot1Q(prio=5, vlan=1000)/ \
2755 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002756 scapy.IP(),
2757 self.RESULT_NOMATCH
2758 )
2759 testPacket("Ether matching with double VLAN tag - Type match",
Rich Laned0478ff2013-03-11 12:46:58 -07002760 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2761 eth_type=0x8100),
2762 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002763 scapy.Dot1Q(prio=5, vlan=1000)/ \
2764 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002765 scapy.IP(),
2766 self.RESULT_MATCH
2767 )
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002768
2769
2770
Dan Talayco9f47f4d2010-06-03 13:54:37 -07002771if __name__ == "__main__":
2772 print "Please run through oft script: ./oft --test_spec=basic"