blob: ad6195653e71700d9826c64430e80b5041248230 [file] [log] [blame]
Matteo Scandoloa229eca2017-08-08 13:05:28 -07001
2# Copyright 2017-present Open Networking Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
Dan Talayco5eba8442010-03-10 13:58:43 -080017"""
18Test cases for testing actions taken on packets
19
20See basic.py for other info.
21
22It is recommended that these definitions be kept in their own
23namespace as different groups of tests will likely define
24similar identifiers.
25
Rich Lane477f4812012-10-04 22:49:00 -070026The switch is actively attempting to contact the controller at the address
27indicated in config.
Dan Talayco5eba8442010-03-10 13:58:43 -080028
29"""
30
Dan Talayco9f47f4d2010-06-03 13:54:37 -070031import copy
Dan Talayco5eba8442010-03-10 13:58:43 -080032import logging
Rich Laneb90a1c42012-10-05 09:16:05 -070033import time
Dan Talayco5eba8442010-03-10 13:58:43 -080034import unittest
Christian Dickmann8b59b4b2012-09-23 16:48:30 -070035import random
Rich Lanea68176f2013-08-09 17:41:05 -070036import oftest.packet as scapy
Dan Talayco5eba8442010-03-10 13:58:43 -080037
Rich Lane477f4812012-10-04 22:49:00 -070038from oftest import config
Dan Talayco5eba8442010-03-10 13:58:43 -080039import oftest.controller as controller
Rich Laned7b0ffa2013-03-08 15:53:42 -080040import ofp
Dan Talayco5eba8442010-03-10 13:58:43 -080041import oftest.dataplane as dataplane
Dan Talayco5eba8442010-03-10 13:58:43 -080042import oftest.parse as parse
Rich Laneb90a1c42012-10-05 09:16:05 -070043import oftest.base_tests as base_tests
44import basic # for IterCases
Dan Talayco5eba8442010-03-10 13:58:43 -080045
Christian Dickmann8b59b4b2012-09-23 16:48:30 -070046from oftest.parse import parse_mac, parse_ip
47
Rich Laneda3b5ad2012-10-03 09:05:32 -070048from oftest.testutils import *
Dan Talayco5eba8442010-03-10 13:58:43 -080049
Dan Talayco551befa2010-07-15 17:05:32 -070050WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
Dan Talayco488fbc52012-04-09 16:30:41 -070051 ofp.OFPFW_DL_VLAN | ofp.OFPFW_DL_VLAN_PCP,
Dan Talayco551befa2010-07-15 17:05:32 -070052 ofp.OFPFW_DL_SRC,
53 ofp.OFPFW_DL_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070054 (ofp.OFPFW_DL_TYPE | ofp.OFPFW_NW_SRC_ALL |
55 ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS | ofp.OFPFW_NW_PROTO |
56 ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
57 (ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
Dan Talayco551befa2010-07-15 17:05:32 -070058 ofp.OFPFW_TP_SRC,
59 ofp.OFPFW_TP_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070060 ofp.OFPFW_NW_SRC_MASK,
61 ofp.OFPFW_NW_DST_MASK,
Dan Talayco551befa2010-07-15 17:05:32 -070062 ofp.OFPFW_DL_VLAN_PCP,
63 ofp.OFPFW_NW_TOS]
64
Dan Talayco488fbc52012-04-09 16:30:41 -070065NO_WILDCARD_VALUES = [(ofp.OFPFW_ALL ^ ofp.OFPFW_IN_PORT),
66 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN),
67 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_SRC),
68 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_DST),
69 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE),
70 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO),
71 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
72 ofp.OFPFW_TP_SRC),
73 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
74 ofp.OFPFW_TP_DST),
75 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
76 ofp.OFPFW_NW_SRC_MASK),
77 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
78 ofp.OFPFW_NW_DST_MASK),
79 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN ^ ofp.OFPFW_DL_VLAN_PCP),
80 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
81 ofp.OFPFW_NW_TOS)]
82
Dan Talayco551befa2010-07-15 17:05:32 -070083MODIFY_ACTION_VALUES = [ofp.OFPAT_SET_VLAN_VID,
84 ofp.OFPAT_SET_VLAN_PCP,
85 ofp.OFPAT_STRIP_VLAN,
86 ofp.OFPAT_SET_DL_SRC,
87 ofp.OFPAT_SET_DL_DST,
88 ofp.OFPAT_SET_NW_SRC,
89 ofp.OFPAT_SET_NW_DST,
90 ofp.OFPAT_SET_NW_TOS,
91 ofp.OFPAT_SET_TP_SRC,
92 ofp.OFPAT_SET_TP_DST]
93
Dan Talayco21381562010-07-17 00:34:47 -070094TEST_VID_DEFAULT = 2
95
Rich Lane97e99652013-01-02 17:23:20 -080096@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -070097class DirectPacket(base_tests.SimpleDataPlane):
Dan Talayco5eba8442010-03-10 13:58:43 -080098 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -070099 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -0800100
101 Generate a packet
102 Generate and install a matching flow
103 Add action to direct the packet to an egress port
104 Send the packet to ingress dataplane port
105 Verify the packet is received at the egress port only
106 """
107 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700108 self.handleFlow()
109
110 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700111 of_ports = config["port_map"].keys()
Dan Talayco5eba8442010-03-10 13:58:43 -0800112 of_ports.sort()
113 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
114
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700115 if (pkttype == 'ICMP'):
116 pkt = simple_icmp_packet()
117 else:
118 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700119 match = packet_to_flow_match(self, pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700120 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800121 self.assertTrue(match is not None,
122 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800123 act = ofp.action.output()
Dan Talayco5eba8442010-03-10 13:58:43 -0800124
125 for idx in range(len(of_ports)):
Rich Lane32bf9482013-01-03 17:26:30 -0800126 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700127
Dan Talayco5eba8442010-03-10 13:58:43 -0800128 ingress_port = of_ports[idx]
129 egress_port = of_ports[(idx + 1) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700130 logging.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700131 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800132
133 match.in_port = ingress_port
134
Rich Laneba3f0e22013-03-11 16:43:57 -0700135 request = ofp.message.flow_add()
Dan Talayco5eba8442010-03-10 13:58:43 -0800136 request.match = match
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700137
Dan Talayco5eba8442010-03-10 13:58:43 -0800138 request.buffer_id = 0xffffffff
139 act.port = egress_port
Rich Lanec495d9e2013-03-08 17:43:36 -0800140 request.actions.append(act)
Dan Talayco5eba8442010-03-10 13:58:43 -0800141
Rich Lane9a003812012-10-04 17:17:59 -0700142 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800143 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800144 do_barrier(self.controller)
Dan Talayco5eba8442010-03-10 13:58:43 -0800145
Rich Lane9a003812012-10-04 17:17:59 -0700146 logging.info("Sending packet to dp port " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800147 str(ingress_port))
148 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700149
150 exp_pkt_arg = None
151 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700152 if config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700153 exp_pkt_arg = pkt
154 exp_port = egress_port
155
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700156 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700157 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800158 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700159 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800160 str(rcv_port))
161 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
162 self.assertEqual(str(pkt), str(rcv_pkt),
163 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700164
Rich Lane97e99652013-01-02 17:23:20 -0800165@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -0700166class DirectPacketController(base_tests.SimpleDataPlane):
Rich Lane51c23b32012-07-27 16:37:25 -0700167 """
168 Send packet to the controller port
169
170 Generate a packet
171 Generate and install a matching flow
172 Add action to direct the packet to the controller port
173 Send the packet to ingress dataplane port
174 Verify the packet is received at the controller port
175 """
176 def runTest(self):
177 self.handleFlow()
178
179 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700180 of_ports = config["port_map"].keys()
Rich Lane51c23b32012-07-27 16:37:25 -0700181 of_ports.sort()
182 self.assertTrue(len(of_ports) > 0, "Not enough ports for test")
183
184 if (pkttype == 'ICMP'):
185 pkt = simple_icmp_packet()
186 else:
187 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700188 match = packet_to_flow_match(self, pkt)
Rich Lane51c23b32012-07-27 16:37:25 -0700189 match.wildcards &= ~ofp.OFPFW_IN_PORT
190 self.assertTrue(match is not None,
191 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800192 act = ofp.action.output()
Rich Lane51c23b32012-07-27 16:37:25 -0700193
Rich Lane32bf9482013-01-03 17:26:30 -0800194 delete_all_flows(self.controller)
Rich Lane51c23b32012-07-27 16:37:25 -0700195
196 ingress_port = of_ports[0]
197 match.in_port = ingress_port
198
Rich Laneba3f0e22013-03-11 16:43:57 -0700199 request = ofp.message.flow_add()
Rich Lane51c23b32012-07-27 16:37:25 -0700200 request.match = match
201
202 request.buffer_id = 0xffffffff
203 act.port = ofp.OFPP_CONTROLLER
204 act.max_len = 65535
Rich Lanec495d9e2013-03-08 17:43:36 -0800205 request.actions.append(act)
Rich Lane51c23b32012-07-27 16:37:25 -0700206
Rich Lane9a003812012-10-04 17:17:59 -0700207 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800208 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800209 do_barrier(self.controller)
Rich Lane51c23b32012-07-27 16:37:25 -0700210
Rich Lane9a003812012-10-04 17:17:59 -0700211 logging.info("Sending packet to dp port " +
Rich Lane51c23b32012-07-27 16:37:25 -0700212 str(ingress_port))
213 self.dataplane.send(ingress_port, str(pkt))
214
Rich Lane4c504f32013-06-07 17:24:14 -0700215 verify_packet_in(self, str(pkt), ingress_port, ofp.OFPR_ACTION)
Howard Pershf97840f2012-04-10 16:30:42 -0700216
Rich Laneb90a1c42012-10-05 09:16:05 -0700217class DirectPacketQueue(base_tests.SimpleDataPlane):
Howard Pershf97840f2012-04-10 16:30:42 -0700218 """
219 Send packet to single queue on single egress port
220
221 Generate a packet
222 Generate and install a matching flow
223 Add action to direct the packet to an egress port and queue
224 Send the packet to ingress dataplane port
225 Verify the packet is received at the egress port only
226 """
227 def runTest(self):
228 self.handleFlow()
229
Howard Persh670b5672012-04-13 09:08:29 -0700230 def portQueuesGet(self, queue_stats, port_num):
231 result = []
Rich Lane5fd6faf2013-03-11 13:30:20 -0700232 for qs in queue_stats.entries:
Howard Persh670b5672012-04-13 09:08:29 -0700233 if qs.port_no != port_num:
234 continue
235 result.append(qs.queue_id)
236 return result
237
Howard Pershf97840f2012-04-10 16:30:42 -0700238 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700239 of_ports = config["port_map"].keys()
Howard Pershf97840f2012-04-10 16:30:42 -0700240 of_ports.sort()
241 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
242
243 if (pkttype == 'ICMP'):
244 pkt = simple_icmp_packet()
245 else:
246 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700247 match = packet_to_flow_match(self, pkt)
Howard Pershf97840f2012-04-10 16:30:42 -0700248 match.wildcards &= ~ofp.OFPFW_IN_PORT
249 self.assertTrue(match is not None,
250 "Could not generate flow match from pkt")
251
Howard Persh670b5672012-04-13 09:08:29 -0700252 # Get queue stats from switch
253
Rich Lane28fa9272013-03-08 16:00:25 -0800254 request = ofp.message.queue_stats_request()
Howard Persh670b5672012-04-13 09:08:29 -0700255 request.port_no = ofp.OFPP_ALL
256 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700257 (queue_stats, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700258 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
259
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800260 act = ofp.action.enqueue()
Howard Pershf97840f2012-04-10 16:30:42 -0700261
262 for idx in range(len(of_ports)):
Howard Pershf97840f2012-04-10 16:30:42 -0700263 ingress_port = of_ports[idx]
264 egress_port = of_ports[(idx + 1) % len(of_ports)]
Howard Pershf97840f2012-04-10 16:30:42 -0700265
Howard Persh670b5672012-04-13 09:08:29 -0700266 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700267 logging.info("Ingress " + str(ingress_port)
Howard Persh670b5672012-04-13 09:08:29 -0700268 + " to egress " + str(egress_port)
269 + " queue " + str(egress_queue_id)
270 )
Howard Pershf97840f2012-04-10 16:30:42 -0700271
Rich Lane32bf9482013-01-03 17:26:30 -0800272 delete_all_flows(self.controller)
Howard Pershf97840f2012-04-10 16:30:42 -0700273
Howard Persh670b5672012-04-13 09:08:29 -0700274 match.in_port = ingress_port
275
Rich Laneba3f0e22013-03-11 16:43:57 -0700276 request = ofp.message.flow_add()
Howard Persh670b5672012-04-13 09:08:29 -0700277 request.match = match
Howard Pershf97840f2012-04-10 16:30:42 -0700278
Howard Persh670b5672012-04-13 09:08:29 -0700279 request.buffer_id = 0xffffffff
280 act.port = egress_port
281 act.queue_id = egress_queue_id
Rich Lanec495d9e2013-03-08 17:43:36 -0800282 request.actions.append(act)
Howard Pershf97840f2012-04-10 16:30:42 -0700283
Rich Lane9a003812012-10-04 17:17:59 -0700284 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800285 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800286 do_barrier(self.controller)
Howard Pershf97840f2012-04-10 16:30:42 -0700287
Howard Persh670b5672012-04-13 09:08:29 -0700288 # Get current stats for selected egress queue
Howard Pershf97840f2012-04-10 16:30:42 -0700289
Rich Lane28fa9272013-03-08 16:00:25 -0800290 request = ofp.message.queue_stats_request()
Howard Persh670b5672012-04-13 09:08:29 -0700291 request.port_no = egress_port
292 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700293 (qs_before, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700294 self.assertNotEqual(qs_before, None, "Queue stats request failed")
295
Rich Lane9a003812012-10-04 17:17:59 -0700296 logging.info("Sending packet to dp port " +
Howard Persh670b5672012-04-13 09:08:29 -0700297 str(ingress_port))
298 self.dataplane.send(ingress_port, str(pkt))
299
300 exp_pkt_arg = None
301 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700302 if config["relax"]:
Howard Persh670b5672012-04-13 09:08:29 -0700303 exp_pkt_arg = pkt
304 exp_port = egress_port
305
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700306 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Howard Persh670b5672012-04-13 09:08:29 -0700307 exp_pkt=exp_pkt_arg)
308 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700309 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Howard Persh670b5672012-04-13 09:08:29 -0700310 str(rcv_port))
311 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
312 self.assertEqual(str(pkt), str(rcv_pkt),
313 'Response packet does not match send packet')
314
Ed Swierkb8a86512012-04-18 18:45:58 -0700315 # FIXME: instead of sleeping, keep requesting queue stats until
316 # the expected queue counter increases or some large timeout is
317 # reached
318 time.sleep(2)
319
Howard Persh670b5672012-04-13 09:08:29 -0700320 # Get current stats for selected egress queue again
321
Rich Lane28fa9272013-03-08 16:00:25 -0800322 request = ofp.message.queue_stats_request()
Howard Persh670b5672012-04-13 09:08:29 -0700323 request.port_no = egress_port
324 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700325 (qs_after, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700326 self.assertNotEqual(qs_after, None, "Queue stats request failed")
327
328 # Make sure that tx packet counter for selected egress queue was
329 # incremented
330
Rich Lane5fd6faf2013-03-11 13:30:20 -0700331 self.assertEqual(qs_after.entries[0].tx_packets, \
332 qs_before.entries[0].tx_packets + 1, \
Howard Persh670b5672012-04-13 09:08:29 -0700333 "Verification of egress queue tx packet count failed"
334 )
335
336
Rich Laneb90a1c42012-10-05 09:16:05 -0700337class DirectPacketControllerQueue(base_tests.SimpleDataPlane):
Ken Chiang899ff8e2012-05-23 18:26:12 -0700338 """
339 Send a packet from each of the openflow ports
340 to each of the queues configured on the controller port.
341 If no queues have been configured, no packets are sent.
Howard Pershf97840f2012-04-10 16:30:42 -0700342
Ken Chiang899ff8e2012-05-23 18:26:12 -0700343 Generate a packet
344 Generate and install a matching flow
345 Add action to direct the packet to one of the controller port queues
346 Send the packet to ingress dataplane port
347 Verify the packet is received on the controller port queue
348 """
349 def runTest(self):
350 self.handleFlow()
351
352 def portQueuesGet(self, queue_stats, port_num):
353 result = []
Rich Lane5fd6faf2013-03-11 13:30:20 -0700354 for qs in queue_stats.entries:
Ken Chiang899ff8e2012-05-23 18:26:12 -0700355 if qs.port_no != port_num:
356 continue
357 result.append(qs.queue_id)
358 return result
359
360 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700361 of_ports = config["port_map"].keys()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700362 of_ports.sort()
363 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
364
365 if (pkttype == 'ICMP'):
366 pkt = simple_icmp_packet()
367 else:
368 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700369 match = packet_to_flow_match(self, pkt)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700370 match.wildcards &= ~ofp.OFPFW_IN_PORT
371 self.assertTrue(match is not None,
372 "Could not generate flow match from pkt")
373
374 # Get queue stats from switch
375
Rich Lane28fa9272013-03-08 16:00:25 -0800376 request = ofp.message.queue_stats_request()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700377 request.port_no = ofp.OFPP_CONTROLLER
378 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700379 (queue_stats, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700380 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
Rich Laneb73808c2013-03-11 15:22:23 -0700381 if queue_stats.type == ofp.OFPT_ERROR:
Rich Laneb8c845a2012-12-31 17:23:51 -0800382 skip_message_emit(self, "Enqueue packet to controller")
383 return
Ken Chiang899ff8e2012-05-23 18:26:12 -0700384
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800385 act = ofp.action.enqueue()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700386
387 for idx in range(len(of_ports)):
388 ingress_port = of_ports[idx]
389 egress_port = ofp.OFPP_CONTROLLER
390
Rich Lane9a003812012-10-04 17:17:59 -0700391 logging.info("Ingress port " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700392 + ", controller port queues "
393 + str(self.portQueuesGet(queue_stats, egress_port)))
394
395 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700396 logging.info("Ingress " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700397 + " to egress " + str(egress_port)
398 + " queue " + str(egress_queue_id)
399 )
400
Rich Lane32bf9482013-01-03 17:26:30 -0800401 delete_all_flows(self.controller)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700402
403 match.in_port = ingress_port
404
Rich Laneba3f0e22013-03-11 16:43:57 -0700405 request = ofp.message.flow_add()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700406 request.match = match
407
408 request.buffer_id = 0xffffffff
409 act.port = egress_port
410 act.queue_id = egress_queue_id
Rich Lanec495d9e2013-03-08 17:43:36 -0800411 request.actions.append(act)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700412
Rich Lane9a003812012-10-04 17:17:59 -0700413 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800414 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800415 do_barrier(self.controller)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700416
417 # Get current stats for selected egress queue
418
Rich Lane28fa9272013-03-08 16:00:25 -0800419 request = ofp.message.queue_stats_request()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700420 request.port_no = egress_port
421 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700422 (qs_before, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700423 self.assertNotEqual(qs_before, None, "Queue stats request failed")
424
Rich Lane9a003812012-10-04 17:17:59 -0700425 logging.info("Sending packet to dp port " +
Ken Chiang899ff8e2012-05-23 18:26:12 -0700426 str(ingress_port))
427 self.dataplane.send(ingress_port, str(pkt))
Ken Chiang899ff8e2012-05-23 18:26:12 -0700428
Rich Lane4c504f32013-06-07 17:24:14 -0700429 verify_packet_in(self, str(pkt), ingress_port, ofp.OFPR_ACTION)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700430
431 # FIXME: instead of sleeping, keep requesting queue stats until
432 # the expected queue counter increases or some large timeout is
433 # reached
434 time.sleep(2)
435
436 # Get current stats for selected egress queue again
437
Rich Lane28fa9272013-03-08 16:00:25 -0800438 request = ofp.message.queue_stats_request()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700439 request.port_no = egress_port
440 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700441 (qs_after, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700442 self.assertNotEqual(qs_after, None, "Queue stats request failed")
443
444 # Make sure that tx packet counter for selected egress queue was
445 # incremented
446
Rich Lane5fd6faf2013-03-11 13:30:20 -0700447 self.assertEqual(qs_after.entries[0].tx_packets, \
448 qs_before.entries[0].tx_packets + 1, \
Ken Chiang899ff8e2012-05-23 18:26:12 -0700449 "Verification of egress queue tx packet count failed"
450 )
451
Howard Pershf97840f2012-04-10 16:30:42 -0700452
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700453class DirectPacketICMP(DirectPacket):
454 """
455 Send ICMP packet to single egress port
456
457 Generate a ICMP packet
458 Generate and install a matching flow
459 Add action to direct the packet to an egress port
460 Send the packet to ingress dataplane port
461 Verify the packet is received at the egress port only
462 Difference from DirectPacket test is that sent packet is ICMP
463 """
464 def runTest(self):
465 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700466
Rich Laneb90a1c42012-10-05 09:16:05 -0700467class DirectTwoPorts(base_tests.SimpleDataPlane):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700468 """
469 Send packet to two egress ports
470
471 Generate a packet
472 Generate and install a matching flow
473 Add action to direct the packet to two egress ports
474 Send the packet to ingress dataplane port
475 Verify the packet is received at the two egress ports
476 """
477 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700478 of_ports = config["port_map"].keys()
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700479 of_ports.sort()
480 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
481
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700482 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700483 match = packet_to_flow_match(self, pkt)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700484 match.wildcards &= ~ofp.OFPFW_IN_PORT
485 self.assertTrue(match is not None,
486 "Could not generate flow match from pkt")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700487
488 for idx in range(len(of_ports)):
Rich Lane32bf9482013-01-03 17:26:30 -0800489 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700490
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700491 ingress_port = of_ports[idx]
492 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
493 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700494 logging.info("Ingress " + str(ingress_port) +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700495 " to egress " + str(egress_port1) + " and " +
496 str(egress_port2))
497
498 match.in_port = ingress_port
499
Rich Laneba3f0e22013-03-11 16:43:57 -0700500 request = ofp.message.flow_add()
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700501 request.match = match
502 request.buffer_id = 0xffffffff
Rich Lane62e96852013-03-11 12:04:45 -0700503 request.actions.append(ofp.action.output(port=egress_port1))
504 request.actions.append(ofp.action.output(port=egress_port2))
Rich Lane9a003812012-10-04 17:17:59 -0700505 # logging.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700506
Rich Lane9a003812012-10-04 17:17:59 -0700507 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800508 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800509 do_barrier(self.controller)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700510
Rich Lane9a003812012-10-04 17:17:59 -0700511 logging.info("Sending packet to dp port " +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700512 str(ingress_port))
513 self.dataplane.send(ingress_port, str(pkt))
Rich Lanee4b384d2013-09-13 14:33:40 -0700514 verify_packets(self, pkt, [egress_port1, egress_port2])
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700515
Rich Laneb90a1c42012-10-05 09:16:05 -0700516class DirectMCNonIngress(base_tests.SimpleDataPlane):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700517 """
518 Multicast to all non-ingress ports
519
520 Generate a packet
521 Generate and install a matching flow
522 Add action to direct the packet to all non-ingress ports
523 Send the packet to ingress dataplane port
524 Verify the packet is received at all non-ingress ports
525
526 Does not use the flood action
527 """
528 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700529 of_ports = config["port_map"].keys()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700530 of_ports.sort()
531 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
532
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700533 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700534 match = packet_to_flow_match(self, pkt)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700535 match.wildcards &= ~ofp.OFPFW_IN_PORT
536 self.assertTrue(match is not None,
537 "Could not generate flow match from pkt")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700538
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700539 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800540 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700541
Rich Lane9a003812012-10-04 17:17:59 -0700542 logging.info("Ingress " + str(ingress_port) +
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700543 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700544 match.in_port = ingress_port
545
Rich Laneba3f0e22013-03-11 16:43:57 -0700546 request = ofp.message.flow_add()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700547 request.match = match
548 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700549 for egress_port in of_ports:
550 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700551 continue
Rich Lane62e96852013-03-11 12:04:45 -0700552 request.actions.append(ofp.action.output(port=egress_port))
Rich Lane9a003812012-10-04 17:17:59 -0700553 logging.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700554
Rich Lane9a003812012-10-04 17:17:59 -0700555 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800556 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800557 do_barrier(self.controller)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700558
Rich Lane9a003812012-10-04 17:17:59 -0700559 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700560 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700561 yes_ports = set(of_ports).difference([ingress_port])
Rich Lanee4b384d2013-09-13 14:33:40 -0700562 verify_packets(self, pkt, yes_ports)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700563
Dan Talayco32fa6542010-05-11 15:54:08 -0700564
Rich Laneb90a1c42012-10-05 09:16:05 -0700565class DirectMC(base_tests.SimpleDataPlane):
Dan Talayco32fa6542010-05-11 15:54:08 -0700566 """
567 Multicast to all ports including ingress
568
569 Generate a packet
570 Generate and install a matching flow
571 Add action to direct the packet to all non-ingress ports
572 Send the packet to ingress dataplane port
573 Verify the packet is received at all ports
574
575 Does not use the flood action
576 """
577 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700578 of_ports = config["port_map"].keys()
Dan Talayco32fa6542010-05-11 15:54:08 -0700579 of_ports.sort()
580 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
581
Dan Talayco32fa6542010-05-11 15:54:08 -0700582 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700583 match = packet_to_flow_match(self, pkt)
Dan Talayco32fa6542010-05-11 15:54:08 -0700584 match.wildcards &= ~ofp.OFPFW_IN_PORT
585 self.assertTrue(match is not None,
586 "Could not generate flow match from pkt")
Dan Talayco32fa6542010-05-11 15:54:08 -0700587
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700588 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800589 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700590
Rich Lane9a003812012-10-04 17:17:59 -0700591 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700592 match.in_port = ingress_port
593
Rich Laneba3f0e22013-03-11 16:43:57 -0700594 request = ofp.message.flow_add()
Dan Talayco32fa6542010-05-11 15:54:08 -0700595 request.match = match
596 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700597 for egress_port in of_ports:
Rich Lane62e96852013-03-11 12:04:45 -0700598 act = ofp.action.output()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700599 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700600 act.port = ofp.OFPP_IN_PORT
601 else:
602 act.port = egress_port
Rich Lanec495d9e2013-03-08 17:43:36 -0800603 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -0700604 # logging.info(request.show())
Dan Talayco2e77a842010-05-12 15:39:46 -0700605
Rich Lane9a003812012-10-04 17:17:59 -0700606 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800607 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800608 do_barrier(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700609
Rich Lane9a003812012-10-04 17:17:59 -0700610 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700611 self.dataplane.send(ingress_port, str(pkt))
Rich Lanee4b384d2013-09-13 14:33:40 -0700612 verify_packets(self, pkt, of_ports)
Dan Talayco2e77a842010-05-12 15:39:46 -0700613
Rich Laneb90a1c42012-10-05 09:16:05 -0700614class Flood(base_tests.SimpleDataPlane):
Dan Talayco2e77a842010-05-12 15:39:46 -0700615 """
616 Flood to all ports except ingress
617
Dan Talaycofcc09912013-02-08 23:46:08 -0800618 Make sure noflood bit is off on all ports
Dan Talayco2e77a842010-05-12 15:39:46 -0700619 Generate a packet
620 Generate and install a matching flow
621 Add action to flood the packet
622 Send the packet to ingress dataplane port
623 Verify the packet is received at all other ports
624 """
625 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700626 of_ports = config["port_map"].keys()
Dan Talayco2e77a842010-05-12 15:39:46 -0700627 of_ports.sort()
628 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
629
630 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700631 match = packet_to_flow_match(self, pkt)
Dan Talayco2e77a842010-05-12 15:39:46 -0700632 match.wildcards &= ~ofp.OFPFW_IN_PORT
633 self.assertTrue(match is not None,
634 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800635 act = ofp.action.output()
Dan Talayco2e77a842010-05-12 15:39:46 -0700636
Dan Talaycofcc09912013-02-08 23:46:08 -0800637 for of_port in of_ports:
638 # Clear relevant bits that might block ports
639 rv = port_config_set(self.controller, of_port, 0,
640 ofp.OFPPC_NO_FLOOD | ofp.OFPPC_NO_FWD |
641 ofp.OFPPC_PORT_DOWN)
642 self.assertTrue(rv == 0, "Did not set port config")
643 logging.debug("Enabled and cleared no-flood for port " + str(of_port))
644
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700645 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800646 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700647
Rich Lane9a003812012-10-04 17:17:59 -0700648 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700649 match.in_port = ingress_port
650
Rich Laneba3f0e22013-03-11 16:43:57 -0700651 request = ofp.message.flow_add()
Dan Talayco2e77a842010-05-12 15:39:46 -0700652 request.match = match
653 request.buffer_id = 0xffffffff
654 act.port = ofp.OFPP_FLOOD
Rich Lanec495d9e2013-03-08 17:43:36 -0800655 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -0700656 logging.info(request.show())
Dan Talayco32fa6542010-05-11 15:54:08 -0700657
Rich Lane9a003812012-10-04 17:17:59 -0700658 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800659 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800660 do_barrier(self.controller)
Dan Talayco32fa6542010-05-11 15:54:08 -0700661
Rich Lane9a003812012-10-04 17:17:59 -0700662 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco32fa6542010-05-11 15:54:08 -0700663 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700664 yes_ports = set(of_ports).difference([ingress_port])
Rich Lanee4b384d2013-09-13 14:33:40 -0700665 verify_packets(self, pkt, yes_ports)
Dan Talayco3be5b062010-05-12 15:46:21 -0700666
Rich Laneb90a1c42012-10-05 09:16:05 -0700667class FloodPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco3be5b062010-05-12 15:46:21 -0700668 """
669 Flood to all ports plus send to ingress port
670
671 Generate a packet
672 Generate and install a matching flow
673 Add action to flood the packet
674 Add action to send to ingress port
675 Send the packet to ingress dataplane port
676 Verify the packet is received at all other ports
677 """
678 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700679 of_ports = config["port_map"].keys()
Dan Talayco3be5b062010-05-12 15:46:21 -0700680 of_ports.sort()
681 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
682
683 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700684 match = packet_to_flow_match(self, pkt)
Dan Talayco3be5b062010-05-12 15:46:21 -0700685 match.wildcards &= ~ofp.OFPFW_IN_PORT
686 self.assertTrue(match is not None,
687 "Could not generate flow match from pkt")
Dan Talayco3be5b062010-05-12 15:46:21 -0700688
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700689 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800690 delete_all_flows(self.controller)
Dan Talayco3be5b062010-05-12 15:46:21 -0700691
Rich Lane9a003812012-10-04 17:17:59 -0700692 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700693 match.in_port = ingress_port
694
Rich Laneba3f0e22013-03-11 16:43:57 -0700695 request = ofp.message.flow_add()
Dan Talayco3be5b062010-05-12 15:46:21 -0700696 request.match = match
697 request.buffer_id = 0xffffffff
Rich Lane62e96852013-03-11 12:04:45 -0700698 request.actions.append(ofp.action.output(port=ofp.OFPP_FLOOD))
699 request.actions.append(ofp.action.output(port=ofp.OFPP_IN_PORT))
Rich Lane9a003812012-10-04 17:17:59 -0700700 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700701
Rich Lane9a003812012-10-04 17:17:59 -0700702 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800703 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800704 do_barrier(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700705
Rich Lane9a003812012-10-04 17:17:59 -0700706 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700707 self.dataplane.send(ingress_port, str(pkt))
Rich Lanee4b384d2013-09-13 14:33:40 -0700708 verify_packets(self, pkt, of_ports)
Dan Talayco4aa13122010-05-12 15:54:44 -0700709
Rich Laneb90a1c42012-10-05 09:16:05 -0700710class All(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700711 """
712 Send to OFPP_ALL port
713
714 Generate a packet
715 Generate and install a matching flow
716 Add action to forward to OFPP_ALL
717 Send the packet to ingress dataplane port
718 Verify the packet is received at all other ports
719 """
720 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700721 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700722 of_ports.sort()
723 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
724
725 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700726 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700727 match.wildcards &= ~ofp.OFPFW_IN_PORT
728 self.assertTrue(match is not None,
729 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800730 act = ofp.action.output()
Dan Talayco4aa13122010-05-12 15:54:44 -0700731
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700732 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800733 delete_all_flows(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700734
Rich Lane9a003812012-10-04 17:17:59 -0700735 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700736 match.in_port = ingress_port
737
Rich Laneba3f0e22013-03-11 16:43:57 -0700738 request = ofp.message.flow_add()
Dan Talayco4aa13122010-05-12 15:54:44 -0700739 request.match = match
740 request.buffer_id = 0xffffffff
741 act.port = ofp.OFPP_ALL
Rich Lanec495d9e2013-03-08 17:43:36 -0800742 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -0700743 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700744
Rich Lane9a003812012-10-04 17:17:59 -0700745 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800746 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800747 do_barrier(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700748
Rich Lane9a003812012-10-04 17:17:59 -0700749 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700750 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700751 yes_ports = set(of_ports).difference([ingress_port])
Rich Lanee4b384d2013-09-13 14:33:40 -0700752 verify_packets(self, pkt, yes_ports)
Dan Talayco4aa13122010-05-12 15:54:44 -0700753
Rich Laneb90a1c42012-10-05 09:16:05 -0700754class AllPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700755 """
756 Send to OFPP_ALL port and ingress port
757
758 Generate a packet
759 Generate and install a matching flow
760 Add action to forward to OFPP_ALL
761 Add action to forward to ingress port
762 Send the packet to ingress dataplane port
763 Verify the packet is received at all other ports
764 """
765 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700766 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700767 of_ports.sort()
768 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
769
770 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700771 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700772 match.wildcards &= ~ofp.OFPFW_IN_PORT
773 self.assertTrue(match is not None,
774 "Could not generate flow match from pkt")
Dan Talayco4aa13122010-05-12 15:54:44 -0700775
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700776 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800777 delete_all_flows(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700778
Rich Lane9a003812012-10-04 17:17:59 -0700779 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700780 match.in_port = ingress_port
781
Rich Laneba3f0e22013-03-11 16:43:57 -0700782 request = ofp.message.flow_add()
Dan Talayco4aa13122010-05-12 15:54:44 -0700783 request.match = match
784 request.buffer_id = 0xffffffff
Rich Lane62e96852013-03-11 12:04:45 -0700785 request.actions.append(ofp.action.output(port=ofp.OFPP_ALL))
786 request.actions.append(ofp.action.output(port=ofp.OFPP_IN_PORT))
Rich Lane9a003812012-10-04 17:17:59 -0700787 logging.info(request.show())
Dan Talayco3be5b062010-05-12 15:46:21 -0700788
Rich Lane9a003812012-10-04 17:17:59 -0700789 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800790 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800791 do_barrier(self.controller)
Dan Talayco3be5b062010-05-12 15:46:21 -0700792
Rich Lane9a003812012-10-04 17:17:59 -0700793 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco3be5b062010-05-12 15:46:21 -0700794 self.dataplane.send(ingress_port, str(pkt))
Rich Lanee4b384d2013-09-13 14:33:40 -0700795 verify_packets(self, pkt, of_ports)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700796
Rich Laneb90a1c42012-10-05 09:16:05 -0700797class FloodMinusPort(base_tests.SimpleDataPlane):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700798 """
799 Config port with No_Flood and test Flood action
800
801 Generate a packet
802 Generate a matching flow
803 Add action to forward to OFPP_ALL
804 Set port to no-flood
805 Send the packet to ingress dataplane port
806 Verify the packet is received at all other ports except
807 the ingress port and the no_flood port
808 """
809 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700810 of_ports = config["port_map"].keys()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700811 of_ports.sort()
812 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
813
814 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700815 match = packet_to_flow_match(self, pkt)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700816 match.wildcards &= ~ofp.OFPFW_IN_PORT
817 self.assertTrue(match is not None,
818 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800819 act = ofp.action.output()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700820
Rich Lane4b9e38c2012-12-06 16:33:20 -0800821 # Clear OFPPC_NO_FLOOD on each port
822 for of_port in of_ports:
823 rv = port_config_set(self.controller, of_port,
824 0, ofp.OFPPC_NO_FLOOD)
825 self.assertEqual(rv, 0, "Failed to set port config")
826
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700827 for idx in range(len(of_ports)):
Rich Lane32bf9482013-01-03 17:26:30 -0800828 delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700829
830 ingress_port = of_ports[idx]
831 no_flood_idx = (idx + 1) % len(of_ports)
832 no_flood_port = of_ports[no_flood_idx]
833 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700834 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700835 self.assertEqual(rv, 0, "Failed to set port config")
836
837 match.in_port = ingress_port
838
Rich Laneba3f0e22013-03-11 16:43:57 -0700839 request = ofp.message.flow_add()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700840 request.match = match
841 request.buffer_id = 0xffffffff
842 act.port = ofp.OFPP_FLOOD
Rich Lanec495d9e2013-03-08 17:43:36 -0800843 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -0700844 logging.info(request.show())
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700845
Rich Lane9a003812012-10-04 17:17:59 -0700846 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800847 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800848 do_barrier(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700849
Rich Lane9a003812012-10-04 17:17:59 -0700850 logging.info("Sending packet to dp port " + str(ingress_port))
851 logging.info("No flood port is " + str(no_flood_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700852 self.dataplane.send(ingress_port, str(pkt))
853 no_ports = set([ingress_port, no_flood_port])
854 yes_ports = set(of_ports).difference(no_ports)
Rich Lanee4b384d2013-09-13 14:33:40 -0700855 verify_packets(self, pkt, yes_ports)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700856
857 # Turn no flood off again
858 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700859 0, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700860 self.assertEqual(rv, 0, "Failed to reset port config")
Rich Lane3a261d52013-01-03 17:45:08 -0800861 do_barrier(self.controller)
Rich Lane4ecc1f42012-12-06 16:35:24 -0800862
863 # Check that packets are now flooded to no_flood_port
864 logging.info("Sending packet to dp port " + str(ingress_port))
865 self.dataplane.send(ingress_port, str(pkt))
866 no_ports = set([ingress_port])
867 yes_ports = set(of_ports).difference(no_ports)
Rich Lanee4b384d2013-09-13 14:33:40 -0700868 verify_packets(self, pkt, yes_ports)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700869
870 #@todo Should check no other packets received
871
Dan Talayco21381562010-07-17 00:34:47 -0700872
873
Dan Talayco551befa2010-07-15 17:05:32 -0700874################################################################
875
Rich Laneb90a1c42012-10-05 09:16:05 -0700876class BaseMatchCase(base_tests.SimpleDataPlane):
Dan Talayco551befa2010-07-15 17:05:32 -0700877 def setUp(self):
Rich Laneb90a1c42012-10-05 09:16:05 -0700878 base_tests.SimpleDataPlane.setUp(self)
Dan Talayco551befa2010-07-15 17:05:32 -0700879 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -0700880 logging.info("BaseMatchCase")
Dan Talayco551befa2010-07-15 17:05:32 -0700881
882class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700883 """
Dan Talayco551befa2010-07-15 17:05:32 -0700884 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700885
886 Generate a packet
887 Generate and install a matching flow without wildcard mask
888 Add action to forward to a port
889 Send the packet to the port
890 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700891 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700892
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700893 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700894 flow_match_test(self, config["port_map"])
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700895
Dan Talayco551befa2010-07-15 17:05:32 -0700896class ExactMatchTagged(BaseMatchCase):
897 """
898 Exact match for all port pairs with tagged pkts
899 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700900
Dan Talayco551befa2010-07-15 17:05:32 -0700901 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -0700902 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Laned0478ff2013-03-11 12:46:58 -0700903 flow_match_test(self, config["port_map"], vlan_vid=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700904
Rich Lane0a4f6372013-01-02 14:40:22 -0800905@disabled
Dan Talayco551befa2010-07-15 17:05:32 -0700906class ExactMatchTaggedMany(BaseMatchCase):
907 """
908 ExactMatchTagged with many VLANS
909 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700910
Dan Talayco551befa2010-07-15 17:05:32 -0700911 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700912 for vid in range(2,100,10):
Rich Laned0478ff2013-03-11 12:46:58 -0700913 flow_match_test(self, config["port_map"], vlan_vid=vid, max_test=5)
Dan Talayco551befa2010-07-15 17:05:32 -0700914 for vid in range(100,4000,389):
Rich Laned0478ff2013-03-11 12:46:58 -0700915 flow_match_test(self, config["port_map"], vlan_vid=vid, max_test=5)
916 flow_match_test(self, config["port_map"], vlan_vid=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700917
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700918class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700919 """
920 SingleWildcardMatchPriority
921 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700922
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700923 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700924 self.pkt = simple_tcp_packet()
925 self.flowMsgs = {}
926
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700927 def _ClearTable(self):
Rich Lane32bf9482013-01-03 17:26:30 -0800928 delete_all_flows(self.controller)
Rich Lane3a261d52013-01-03 17:45:08 -0800929 do_barrier(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700930
931 def runTest(self):
932
933 self._Init()
Rich Lane477f4812012-10-04 22:49:00 -0700934 of_ports = config["port_map"].keys()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700935 of_ports.sort()
936
937 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700938 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700939
940 # Run several combinations, each at lower priority settings.
941 # At the end of each call to runPrioFlows(), the table should
942 # be empty. If its not, we'll catch it as the priorities decreases
943 portA = of_ports[0]
944 portB = of_ports[1]
945 portC = of_ports[2]
946
947 # TODO -- these priority numbers should be validated somehow?
948 self.runPrioFlows(portA, portB, portC, 1000, 999)
949 self.runPrioFlows(portB, portC, portA, 998, 997)
950 self.runPrioFlows(portC, portA, portB, 996, 995)
951 self.runPrioFlows(portA, portC, portB, 994, 993)
952
953
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700954
955 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
956 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700957
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700958 if clearTable:
959 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700960
961 # Sanity check flow at lower priority from pA to pB
Rich Lane9a003812012-10-04 17:17:59 -0700962 logging.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700963 % (portA, portB, portC, prioHigher, prioLower))
964
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700965 # Sanity check flow at lower priority from pA to pC
966 self.installFlow(prioLower, portA, portC)
967 self.verifyFlow(portA, portC)
968 self.removeFlow(prioLower)
969
970 # Install and verify pA->pB @ prioLower
971 self.installFlow(prioLower, portA, portB)
972 self.verifyFlow(portA, portB)
973
974 # Install and verify pA->pC @ prioHigher, should override pA->pB
975 self.installFlow(prioHigher, portA, portC)
976 self.verifyFlow(portA, portC)
977 # remove pA->pC
978 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700979 # Old flow pA -> pB @ prioLower should still be active
980 self.verifyFlow(portA, portB)
981 self.removeFlow(prioLower)
982
983 # Table should be empty at this point, leave it alone as
984 # an assumption for future test runs
985
986
987
Ed Swierk99a74de2012-08-22 06:40:54 -0700988 def installFlow(self, prio, inp, egp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700989 wildcards=ofp.OFPFW_DL_SRC):
Ed Swierk99a74de2012-08-22 06:40:54 -0700990 wildcards |= required_wildcards(self)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700991 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -0700992 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700993 egr_ports=egp)
994 request.priority = prio
Rich Lane9a003812012-10-04 17:17:59 -0700995 logging.debug("Install flow with priority " + str(prio))
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700996 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700997 self.flowMsgs[prio] = request
998
999 def removeFlow(self, prio):
1000 if self.flowMsgs.has_key(prio):
Rich Laneba3f0e22013-03-11 16:43:57 -07001001 old_msg = self.flowMsgs[prio]
1002 msg = ofp.message.flow_delete_strict(out_port=ofp.OFPP_NONE,
1003 match=old_msg.match,
1004 priority=old_msg.priority)
Rich Lane9a003812012-10-04 17:17:59 -07001005 logging.debug("Remove flow with priority " + str(prio))
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001006 self.controller.message_send(msg)
Rich Lane3a261d52013-01-03 17:45:08 -08001007 do_barrier(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001008 else:
1009 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001010
1011
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001012 def verifyFlow(self, inp, egp, pkt=None):
1013 if pkt == None:
1014 pkt = self.pkt
1015
Rich Lane9a003812012-10-04 17:17:59 -07001016 logging.info("Pkt match test: " + str(inp) + " to " + str(egp))
1017 logging.debug("Send packet: " + str(inp) + " to " + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001018 self.dataplane.send(inp, str(pkt))
Rich Lanee4b384d2013-09-13 14:33:40 -07001019 verify_packets(self, pkt, [egp])
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001020
1021
1022
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001023class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
1024
1025 def runTest(self):
1026
1027 self._Init()
1028
Rich Lane477f4812012-10-04 22:49:00 -07001029 of_ports = config["port_map"].keys()
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001030 of_ports.sort()
1031
1032 # Install an entry from 0 -> 1 @ prio 1000
1033 self._ClearTable()
1034 self.installFlow(1000, of_ports[0], of_ports[1])
1035 self.verifyFlow(of_ports[0], of_ports[1])
1036 self.installFlow(1000, of_ports[1], of_ports[0])
1037 self.verifyFlow(of_ports[1], of_ports[0])
1038 self.installFlow(1001, of_ports[0], of_ports[1])
1039 self.verifyFlow(of_ports[0], of_ports[1])
1040 self.installFlow(1001, of_ports[1], of_ports[0])
1041 self.verifyFlow(of_ports[1], of_ports[0])
1042 self.removeFlow(1001)
1043 self.verifyFlow(of_ports[0], of_ports[1])
1044 self.removeFlow(1000)
1045
1046
1047
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001048class WildcardPriority(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001049 """
1050 1. Add wildcard flow, verify packet received.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001051 2. Add wildcard flow with higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001052 on port specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001053 3. Add wildcard flow with lower priority, verify packet received
Rich Laneb8392082012-11-21 15:52:54 -08001054 on port specified by the highest priority flow.
Ken Chiang38d7a152012-05-24 15:33:50 -07001055 """
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001056
1057 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001058
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001059 self._Init()
1060
Rich Lane477f4812012-10-04 22:49:00 -07001061 of_ports = config["port_map"].keys()
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001062 of_ports.sort()
1063
1064 self._ClearTable()
Ken Chiang38d7a152012-05-24 15:33:50 -07001065
1066 # Install a flow with wildcards
1067 self.installFlow(999, of_ports[0], of_ports[1],
1068 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001069 self.verifyFlow(of_ports[0], of_ports[1])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001070 # Install a flow with wildcards with higher priority
1071 self.installFlow(1000, of_ports[0], of_ports[2],
1072 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001073 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001074 # Install a flow with wildcards with lower priority
Rich Laneb8392082012-11-21 15:52:54 -08001075 self.installFlow(999, of_ports[0], of_ports[1],
1076 wildcards=ofp.OFPFW_DL_SRC)
Rich Lane0a78fbd2012-12-31 16:25:04 -08001077 self.verifyFlow(of_ports[0], of_ports[2])
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001078
1079
Rich Lane97e99652013-01-02 17:23:20 -08001080@group("smoke")
Ken Chiang3978f242012-06-13 14:14:09 -07001081class WildcardPriorityWithDelete(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001082 """
Rich Lane0a78fbd2012-12-31 16:25:04 -08001083 1. Add wildcard match flow, verify packet received.
Ken Chiang38d7a152012-05-24 15:33:50 -07001084 2. Add wildcard flow with higher priority, verify packet received on port
1085 specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001086 3. Add wildcard flow with even higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001087 on port specified by this flow.
1088 4. Delete lowest priority flow, verify packet received on port specified
1089 by highest priority flow.
1090 5. Delete highest priority flow, verify packet received on port specified
1091 by remaining flow.
1092 """
1093
1094 def runTest(self):
1095
1096 self._Init()
1097
Rich Lane477f4812012-10-04 22:49:00 -07001098 of_ports = config["port_map"].keys()
Ken Chiang38d7a152012-05-24 15:33:50 -07001099 of_ports.sort()
1100
1101 self._ClearTable()
1102
Rich Lane0a78fbd2012-12-31 16:25:04 -08001103 # Install a flow with wildcards
1104 self.installFlow(250, of_ports[0], of_ports[1],
1105 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001106 self.verifyFlow(of_ports[0], of_ports[1])
1107 # Install a flow with wildcards of higher priority
1108 self.installFlow(1250, of_ports[0], of_ports[2],
1109 wildcards=ofp.OFPFW_DL_DST)
1110 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001111 # Install a flow with wildcards with even higher priority
1112 self.installFlow(2001, of_ports[0], of_ports[3],
1113 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001114 self.verifyFlow(of_ports[0], of_ports[3])
1115 # Delete lowest priority flow
1116 self.removeFlow(250)
1117 self.verifyFlow(of_ports[0], of_ports[3])
1118 # Delete highest priority flow
1119 self.removeFlow(2001)
1120 self.verifyFlow(of_ports[0], of_ports[2])
1121
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001122
Dan Talayco551befa2010-07-15 17:05:32 -07001123class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001124 """
1125 Exercise wildcard matching for all ports
1126
1127 Generate a packet
1128 Generate and install a matching flow with wildcard mask
1129 Add action to forward to a port
1130 Send the packet to the port
1131 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001132 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001133 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001134 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001135 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001136 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001137 wc |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001138 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001139 # Set nonzero VLAN id to avoid sending priority-tagged packet
Rich Laned0478ff2013-03-11 12:46:58 -07001140 vlan_vid = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001141 else:
Rich Laned0478ff2013-03-11 12:46:58 -07001142 vlan_vid = -1
Rich Lane477f4812012-10-04 22:49:00 -07001143 flow_match_test(self, config["port_map"], wildcards=wc,
Rich Laned0478ff2013-03-11 12:46:58 -07001144 vlan_vid=vlan_vid, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001145
Dan Talayco551befa2010-07-15 17:05:32 -07001146class SingleWildcardMatchTagged(BaseMatchCase):
1147 """
1148 SingleWildcardMatch with tagged packets
1149 """
1150 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001151 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001152 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001153 wc |= required_wildcards(self)
Rich Laned0478ff2013-03-11 12:46:58 -07001154 flow_match_test(self, config["port_map"], wildcards=wc, vlan_vid=vid,
Dan Talayco551befa2010-07-15 17:05:32 -07001155 max_test=10)
1156
1157class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001158 """
Dan Talayco80b54ed2010-07-13 09:48:35 -07001159 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001160
1161 Generate a packet
1162 Generate and install a matching flow with wildcard all except one filed
1163 Add action to forward to a port
1164 Send the packet to the port
1165 Verify the packet is received at all other ports (one port at a time)
1166 Verify flow_expiration message is correct when command option is set
1167 """
1168 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001169 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001170 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001171 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001172 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001173 # Set nonzero VLAN id to avoid sending priority-tagged packet
Rich Laned0478ff2013-03-11 12:46:58 -07001174 vlan_vid = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001175 else:
Rich Laned0478ff2013-03-11 12:46:58 -07001176 vlan_vid = -1
Rich Lane477f4812012-10-04 22:49:00 -07001177 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Rich Laned0478ff2013-03-11 12:46:58 -07001178 vlan_vid=vlan_vid)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001179
Dan Talayco551befa2010-07-15 17:05:32 -07001180class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1181 """
1182 Match one field with tagged packets
1183 """
1184 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001185 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001186 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001187 all_exp_one_wildcard |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001188 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Rich Laned0478ff2013-03-11 12:46:58 -07001189 vlan_vid=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001190
1191class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001192 """
1193 Create Wildcard-all flow and exercise for all ports
1194
1195 Generate a packet
1196 Generate and install a matching flow with wildcard-all
1197 Add action to forward to a port
1198 Send the packet to the port
1199 Verify the packet is received at all other ports (one port at a time)
1200 Verify flow_expiration message is correct when command option is set
1201 """
1202 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001203 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001204
Dan Talayco551befa2010-07-15 17:05:32 -07001205class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001206 """
Dan Talayco551befa2010-07-15 17:05:32 -07001207 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001208 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001209 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001210 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Lane477f4812012-10-04 22:49:00 -07001211 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL,
Rich Laned0478ff2013-03-11 12:46:58 -07001212 vlan_vid=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001213
Rich Lane97e99652013-01-02 17:23:20 -08001214@group('smoke')
Dan Talayco551befa2010-07-15 17:05:32 -07001215class AddVLANTag(BaseMatchCase):
1216 """
1217 Add a VLAN tag to an untagged packet
1218 """
1219 def runTest(self):
1220 new_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001221 sup_acts = self.supported_actions
Dan Talayco551befa2010-07-15 17:05:32 -07001222 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001223 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001224 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001225
Dan Talayco551befa2010-07-15 17:05:32 -07001226 len = 100
1227 len_w_vid = 104
1228 pkt = simple_tcp_packet(pktlen=len)
1229 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
Rich Laned0478ff2013-03-11 12:46:58 -07001230 vlan_vid=new_vid)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001231 vid_act = ofp.action.set_vlan_vid()
Dan Talayco551befa2010-07-15 17:05:32 -07001232 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001233
Rich Lane477f4812012-10-04 22:49:00 -07001234 flow_match_test(self, config["port_map"], pkt=pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001235 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001236
Rich Lane0a4f6372013-01-02 14:40:22 -08001237@disabled
Rich Laneb90a1c42012-10-05 09:16:05 -07001238class PacketOnly(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001239 """
1240 Just send a packet thru the switch
1241 """
Rich Laned1d9c282012-10-04 22:07:10 -07001242
Dan Talayco551befa2010-07-15 17:05:32 -07001243 def runTest(self):
1244 pkt = simple_tcp_packet()
Rich Lane477f4812012-10-04 22:49:00 -07001245 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001246 of_ports.sort()
1247 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001248 logging.info("Sending packet to " + str(ing_port))
1249 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001250 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001251
Rich Lane0a4f6372013-01-02 14:40:22 -08001252@disabled
Rich Laneb90a1c42012-10-05 09:16:05 -07001253class PacketOnlyTagged(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001254 """
1255 Just send a packet thru the switch
1256 """
Rich Laned1d9c282012-10-04 22:07:10 -07001257
Dan Talayco551befa2010-07-15 17:05:32 -07001258 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001259 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Laned0478ff2013-03-11 12:46:58 -07001260 pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=vid)
Rich Lane477f4812012-10-04 22:49:00 -07001261 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001262 of_ports.sort()
1263 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001264 logging.info("Sending packet to " + str(ing_port))
1265 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001266 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001267
Dan Talayco551befa2010-07-15 17:05:32 -07001268class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001269 """
1270 Modify the VLAN ID in the VLAN tag of a tagged packet
1271 """
Dan Talaycoaf669322012-09-12 22:51:22 -07001272 def setUp(self):
1273 BaseMatchCase.setUp(self)
1274 self.ing_port=False
1275
Dan Talayco551befa2010-07-15 17:05:32 -07001276 def runTest(self):
1277 old_vid = 2
1278 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001279 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001280 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001281 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001282 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001283
Rich Laned0478ff2013-03-11 12:46:58 -07001284 pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=old_vid)
1285 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=new_vid)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001286 vid_act = ofp.action.set_vlan_vid()
Dan Talayco551befa2010-07-15 17:05:32 -07001287 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001288
Rich Lane477f4812012-10-04 22:49:00 -07001289 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoaf669322012-09-12 22:51:22 -07001290 action_list=[vid_act], ing_port=self.ing_port)
1291
1292class ModifyVIDToIngress(ModifyVID):
1293 """
1294 Modify the VLAN ID in the VLAN tag of a tagged packet and send to
1295 ingress port
1296 """
1297 def setUp(self):
1298 BaseMatchCase.setUp(self)
1299 self.ing_port=True
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001300
Ken Chiange9a211d2012-04-20 14:52:11 -07001301class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1302 """
Rich Lane28fa9272013-03-08 16:00:25 -08001303 With vlan ID and priority wildcarded, perform SET_VLAN_VID ofp.action.
Ken Chiange9a211d2012-04-20 14:52:11 -07001304 The same flow should match on both untagged and tagged packets.
1305 """
1306 def runTest(self):
1307 old_vid = 2
1308 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001309 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001310 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1311 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1312 return
1313
Rich Lane477f4812012-10-04 22:49:00 -07001314 of_ports = config["port_map"].keys()
Ken Chiange9a211d2012-04-20 14:52:11 -07001315 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1316 ing_port = of_ports[0]
Rich Lanee4b384d2013-09-13 14:33:40 -07001317 egress_port = of_ports[1]
Ken Chiange9a211d2012-04-20 14:52:11 -07001318
Rich Lane32bf9482013-01-03 17:26:30 -08001319 delete_all_flows(self.controller)
Ken Chiange9a211d2012-04-20 14:52:11 -07001320
1321 len_untagged = 100
1322 len_w_vid = 104
1323 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1324 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
Rich Laned0478ff2013-03-11 12:46:58 -07001325 dl_vlan_enable=True, vlan_vid=old_vid)
Ken Chiange9a211d2012-04-20 14:52:11 -07001326 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
Rich Laned0478ff2013-03-11 12:46:58 -07001327 vlan_vid=new_vid)
Ed Swierk99a74de2012-08-22 06:40:54 -07001328 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1329 ofp.OFPFW_DL_VLAN_PCP)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001330 vid_act = ofp.action.set_vlan_vid()
Ken Chiange9a211d2012-04-20 14:52:11 -07001331 vid_act.vlan_vid = new_vid
1332 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
Rich Lanee4b384d2013-09-13 14:33:40 -07001333 wildcards=wildcards, egr_ports=egress_port,
Ken Chiange9a211d2012-04-20 14:52:11 -07001334 action_list=[vid_act])
1335 flow_msg_install(self, request)
1336
Rich Lane9a003812012-10-04 17:17:59 -07001337 logging.debug("Send untagged packet: " + str(ing_port) + " to " +
Rich Lanee4b384d2013-09-13 14:33:40 -07001338 str(egress_port))
Ken Chiange9a211d2012-04-20 14:52:11 -07001339 self.dataplane.send(ing_port, str(untagged_pkt))
Rich Lanee4b384d2013-09-13 14:33:40 -07001340 verify_packets(self, exp_pkt, [egress_port])
Ken Chiange9a211d2012-04-20 14:52:11 -07001341
Rich Lane9a003812012-10-04 17:17:59 -07001342 logging.debug("Send tagged packet: " + str(ing_port) + " to " +
Rich Lanee4b384d2013-09-13 14:33:40 -07001343 str(egress_port))
Ken Chiange9a211d2012-04-20 14:52:11 -07001344 self.dataplane.send(ing_port, str(tagged_pkt))
Rich Lanee4b384d2013-09-13 14:33:40 -07001345 verify_packets(self, exp_pkt, [egress_port])
Ken Chiange9a211d2012-04-20 14:52:11 -07001346
Howard Pershc1199d52012-04-11 14:21:32 -07001347class ModifyVlanPcp(BaseMatchCase):
1348 """
1349 Modify the priority field of the VLAN tag of a tagged packet
1350 """
1351 def runTest(self):
1352 vid = 123
1353 old_vlan_pcp = 2
1354 new_vlan_pcp = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001355 sup_acts = self.supported_actions
Ed Swierk8c3af7f2012-04-24 14:19:17 -07001356 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_PCP):
1357 skip_message_emit(self, "Modify VLAN priority test")
Howard Pershc1199d52012-04-11 14:21:32 -07001358 return
1359
Rich Laned0478ff2013-03-11 12:46:58 -07001360 pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=vid, vlan_pcp=old_vlan_pcp)
1361 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=vid, vlan_pcp=new_vlan_pcp)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001362 vid_act = ofp.action.set_vlan_pcp()
Howard Pershc1199d52012-04-11 14:21:32 -07001363 vid_act.vlan_pcp = new_vlan_pcp
1364
Rich Lane477f4812012-10-04 22:49:00 -07001365 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Howard Pershc1199d52012-04-11 14:21:32 -07001366 action_list=[vid_act])
1367
Dan Talayco551befa2010-07-15 17:05:32 -07001368class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001369 """
1370 Strip the VLAN tag from a tagged packet
1371 """
Dan Talayco551befa2010-07-15 17:05:32 -07001372 def runTest(self):
1373 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001374 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001375 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001376 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001377 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001378
Dan Talayco551befa2010-07-15 17:05:32 -07001379 len_w_vid = 104
1380 len = 100
1381 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
Rich Laned0478ff2013-03-11 12:46:58 -07001382 vlan_vid=old_vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001383 exp_pkt = simple_tcp_packet(pktlen=len)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001384 vid_act = ofp.action.strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001385
Rich Lane477f4812012-10-04 22:49:00 -07001386 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001387 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001388
Ken Chiange9a211d2012-04-20 14:52:11 -07001389class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1390 """
1391 Strip the VLAN tag from a tagged packet.
1392 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1393 """
1394 def runTest(self):
1395 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001396 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001397 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1398 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1399 return
1400
1401 len_w_vid = 104
1402 len_untagged = 100
1403 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
Rich Laned0478ff2013-03-11 12:46:58 -07001404 vlan_vid=old_vid)
Ken Chiange9a211d2012-04-20 14:52:11 -07001405 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
Ed Swierk99a74de2012-08-22 06:40:54 -07001406 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1407 ofp.OFPFW_DL_VLAN_PCP)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001408 vid_act = ofp.action.strip_vlan()
Ken Chiange9a211d2012-04-20 14:52:11 -07001409
Rich Lane477f4812012-10-04 22:49:00 -07001410 flow_match_test(self, config["port_map"],
Ed Swierk99a74de2012-08-22 06:40:54 -07001411 wildcards=wildcards,
Ken Chiange9a211d2012-04-20 14:52:11 -07001412 pkt=pkt, exp_pkt=exp_pkt,
1413 action_list=[vid_act])
1414
Dan Talayco4b2bee62010-07-20 14:10:05 -07001415def init_pkt_args():
1416 """
1417 Pass back a dictionary with default packet arguments
1418 """
1419 args = {}
Rich Laned0478ff2013-03-11 12:46:58 -07001420 args["eth_src"] = '00:23:45:67:89:AB'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001421
1422 dl_vlan_enable=False
Rich Laned0478ff2013-03-11 12:46:58 -07001423 vlan_vid=-1
Rich Lane477f4812012-10-04 22:49:00 -07001424 if config["test-params"]["vid"]:
Dan Talayco4b2bee62010-07-20 14:10:05 -07001425 dl_vlan_enable=True
Rich Laned0478ff2013-03-11 12:46:58 -07001426 vlan_vid = config["test-params"]["vid"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001427
1428# Unpack operator is ** on a dictionary
1429
1430 return args
1431
Dan Talayco551befa2010-07-15 17:05:32 -07001432class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001433 """
1434 Modify the source MAC address (TP1)
1435 """
Dan Talayco551befa2010-07-15 17:05:32 -07001436 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001437 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001438 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001439 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001440 return
1441
Rich Laned0478ff2013-03-11 12:46:58 -07001442 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_src'],
Dan Talayco4b2bee62010-07-20 14:10:05 -07001443 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001444 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001445 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001446
Dan Talayco551befa2010-07-15 17:05:32 -07001447class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001448 """
1449 Modify the dest MAC address (TP1)
1450 """
Dan Talayco551befa2010-07-15 17:05:32 -07001451 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001452 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001453 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001454 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001455 return
1456
Rich Laned0478ff2013-03-11 12:46:58 -07001457 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_dst'],
Dan Talayco4b2bee62010-07-20 14:10:05 -07001458 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001459 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001460 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001461
Dan Talayco551befa2010-07-15 17:05:32 -07001462class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001463 """
1464 Modify the source IP address of an IP packet (TP1)
1465 """
Dan Talayco551befa2010-07-15 17:05:32 -07001466 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001467 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001468 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001469 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001470 return
1471
1472 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1473 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001474 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001475 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001476
Dan Talayco551befa2010-07-15 17:05:32 -07001477class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001478 """
1479 Modify the dest IP address of an IP packet (TP1)
1480 """
Dan Talayco551befa2010-07-15 17:05:32 -07001481 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001482 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001483 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001484 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001485 return
1486
1487 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1488 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001489 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001490 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001491
1492class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001493 """
1494 Modify the source TCP port of a TCP packet (TP1)
1495 """
Dan Talayco551befa2010-07-15 17:05:32 -07001496 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001497 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001498 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001499 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001500 return
1501
1502 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1503 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001504 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001505 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001506
Rich Lane01c2b862012-10-26 16:26:25 -07001507class ModifyL4SrcUdp(BaseMatchCase):
1508 """
1509 Modify the source UDP port of a UDP packet
1510 """
1511 def runTest(self):
1512 sup_acts = self.supported_actions
1513 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1514 skip_message_emit(self, "ModifyL4SrcUdp test")
1515 return
1516
1517 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_sport'],
1518 check_test_params=True, tp="udp")
1519 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1520 action_list=acts, max_test=2)
1521
Dan Talayco551befa2010-07-15 17:05:32 -07001522class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001523 """
1524 Modify the dest TCP port of a TCP packet (TP1)
1525 """
Dan Talayco551befa2010-07-15 17:05:32 -07001526 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001527 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001528 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001529 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001530 return
1531
1532 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1533 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001534 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001535 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001536
Rich Lane01c2b862012-10-26 16:26:25 -07001537class ModifyL4DstUdp(BaseMatchCase):
1538 """
1539 Modify the dest UDP port of a UDP packet
1540 """
1541 def runTest(self):
1542 sup_acts = self.supported_actions
1543 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1544 skip_message_emit(self, "ModifyL4DstUdp test")
1545 return
1546
1547 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_dport'],
1548 check_test_params=True, tp="udp")
1549 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1550 action_list=acts, max_test=2)
1551
Dan Talayco551befa2010-07-15 17:05:32 -07001552class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001553 """
1554 Modify the IP type of service of an IP packet (TP1)
1555 """
Dan Talayco551befa2010-07-15 17:05:32 -07001556 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001557 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001558 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001559 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001560 return
Dan Talayco551befa2010-07-15 17:05:32 -07001561
Dan Talayco4b2bee62010-07-20 14:10:05 -07001562 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1563 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001564 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001565 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001566
Dan Talaycof6e76c02012-03-23 10:56:12 -07001567class ModifyL2DstMC(BaseMatchCase):
1568 """
1569 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001570 """
1571 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001572 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001573 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001574 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001575 return
1576
Rich Laned0478ff2013-03-11 12:46:58 -07001577 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_dst'],
Dan Talaycof6e76c02012-03-23 10:56:12 -07001578 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001579 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001580 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001581
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001582class ModifyL2DstIngress(BaseMatchCase):
1583 """
1584 Modify the L2 dest and send to the ingress port
1585 """
1586 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001587 sup_acts = self.supported_actions
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001588 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001589 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001590 return
1591
Rich Laned0478ff2013-03-11 12:46:58 -07001592 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_dst'],
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001593 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001594 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001595 action_list=acts, max_test=2, egr_count=0,
1596 ing_port=True)
1597
Dan Talaycod8ae7582012-03-23 12:24:56 -07001598class ModifyL2DstIngressMC(BaseMatchCase):
1599 """
1600 Modify the L2 dest and send to the ingress port
1601 """
1602 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001603 sup_acts = self.supported_actions
Dan Talaycod8ae7582012-03-23 12:24:56 -07001604 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1605 skip_message_emit(self, "ModifyL2dstMC test")
1606 return
1607
Rich Laned0478ff2013-03-11 12:46:58 -07001608 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_dst'],
Dan Talaycod8ae7582012-03-23 12:24:56 -07001609 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001610 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001611 action_list=acts, max_test=2, egr_count=-1,
1612 ing_port=True)
1613
Dan Talaycof6e76c02012-03-23 10:56:12 -07001614class ModifyL2SrcMC(BaseMatchCase):
1615 """
1616 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001617 """
1618 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001619 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001620 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001621 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001622 return
1623
Rich Laned0478ff2013-03-11 12:46:58 -07001624 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_src'],
Dan Talaycof6e76c02012-03-23 10:56:12 -07001625 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001626 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001627 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001628
1629class ModifyL2SrcDstMC(BaseMatchCase):
1630 """
1631 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001632 """
1633 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001634 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001635 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1636 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1637 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001638 return
1639
Rich Laned0478ff2013-03-11 12:46:58 -07001640 mod_fields = ['eth_dst', 'eth_src']
Dan Talaycof6e76c02012-03-23 10:56:12 -07001641 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1642 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001643 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001644 action_list=acts, max_test=2, egr_count=-1)
1645
1646class ModifyL2DstVIDMC(BaseMatchCase):
1647 """
1648 Modify the L2 dest and send to 2 ports
1649 """
1650 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001651 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001652 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1653 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1654 skip_message_emit(self, "ModifyL2DstVIDMC test")
1655 return
1656
Rich Laned0478ff2013-03-11 12:46:58 -07001657 mod_fields = ['eth_dst', 'vlan_vid']
Dan Talaycocfa172f2012-03-23 12:03:00 -07001658 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1659 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1660 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001661 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001662 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001663
Rich Lane97e99652013-01-02 17:23:20 -08001664@group("smoke")
Rich Lane22e74c12012-11-12 15:06:06 -08001665class ModifyAll(BaseMatchCase):
1666 """
1667 Modify all supported fields and output to a port
1668 """
1669 def runTest(self):
1670 sup_acts = self.supported_actions
1671
1672 sup_map = {
Rich Laned0478ff2013-03-11 12:46:58 -07001673 "eth_dst" : ofp.OFPAT_SET_DL_DST,
1674 "eth_src" : ofp.OFPAT_SET_DL_SRC,
Rich Lane22e74c12012-11-12 15:06:06 -08001675 "dl_vlan_enable" : ofp.OFPAT_SET_VLAN_VID,
Rich Laned0478ff2013-03-11 12:46:58 -07001676 "vlan_vid" : ofp.OFPAT_SET_VLAN_VID,
1677 "vlan_pcp" : ofp.OFPAT_SET_VLAN_PCP,
Rich Lane22e74c12012-11-12 15:06:06 -08001678 "ip_src" : ofp.OFPAT_SET_NW_SRC,
1679 "ip_dst" : ofp.OFPAT_SET_NW_DST,
1680 "ip_tos" : ofp.OFPAT_SET_NW_TOS,
1681 "tcp_sport" : ofp.OFPAT_SET_TP_SRC,
1682 "tcp_dport" : ofp.OFPAT_SET_TP_DST,
1683 }
1684
1685 mod_fields = [field for (field, bit) in sup_map.items() if (sup_acts & 1 << bit)]
1686 random.shuffle(mod_fields)
1687 start_field_vals = { "dl_vlan_enable" : True }
1688 mod_field_vals = { "dl_vlan_enable" : True }
1689 logging.info("modifying fields: %s" % repr(mod_fields))
1690
1691 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1692 mod_fields=mod_fields,
1693 start_field_vals=start_field_vals,
1694 mod_field_vals=mod_field_vals,
1695 check_test_params=True)
1696 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1697 action_list=acts, max_test=2)
1698
Dan Talaycofa6454f2012-04-05 10:04:13 -07001699class FlowToggle(BaseMatchCase):
1700 """
1701 Add flows to the table and modify them repeatedly
Dan Talaycof7c41312012-07-23 12:53:19 -07001702
1703 This is done by using only "add" flow messages. Since the check overlap
1704 flag is not set, the switch is supposed to modify the existing flow if
1705 the match already exists.
1706
1707 Would probably be better to exercise more of the flow modify commands
1708 (add, modify, delete +/- strict).
Dan Talaycofa6454f2012-04-05 10:04:13 -07001709 """
1710 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001711 flow_count = test_param_get('ft_flow_count', default=20)
1712 iter_count = test_param_get('ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001713
Rich Lane9a003812012-10-04 17:17:59 -07001714 logging.info("Running flow toggle with %d flows, %d iterations" %
Dan Talaycofa6454f2012-04-05 10:04:13 -07001715 (flow_count, iter_count))
1716 acts = []
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001717 acts.append(ofp.action.output())
1718 acts.append(ofp.action.output())
Dan Talaycofa6454f2012-04-05 10:04:13 -07001719
Rich Lane477f4812012-10-04 22:49:00 -07001720 of_ports = config["port_map"].keys()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001721 if len(of_ports) < 3:
1722 self.assertTrue(False, "Too few ports for test")
1723
1724 for idx in range(2):
1725 acts[idx].port = of_ports[idx]
1726
1727 flows = []
1728 flows.append([])
1729 flows.append([])
1730
Ed Swierk99a74de2012-08-22 06:40:54 -07001731 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_SRC |
1732 ofp.OFPFW_DL_DST)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001733 # Create up the flows in an array
1734 for toggle in range(2):
1735 for f_idx in range(flow_count):
1736 pkt = simple_tcp_packet(tcp_sport=f_idx)
Rich Laneba3f0e22013-03-11 16:43:57 -07001737 msg = ofp.message.flow_add()
Ed Swierk99a74de2012-08-22 06:40:54 -07001738 match = packet_to_flow_match(self, pkt)
Shudong Zhou031373c2012-07-19 17:37:42 -07001739 match.in_port = of_ports[2]
Dan Talayco50be7672012-04-05 11:38:08 -07001740 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001741 msg.match = match
1742 msg.buffer_id = 0xffffffff
Rich Lanec495d9e2013-03-08 17:43:36 -08001743 msg.actions.append(acts[toggle])
Dan Talaycofa6454f2012-04-05 10:04:13 -07001744 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001745
1746 # Show two sample flows
Rich Lane9a003812012-10-04 17:17:59 -07001747 logging.debug(flows[0][0].show())
1748 logging.debug(flows[1][0].show())
Dan Talayco50be7672012-04-05 11:38:08 -07001749
Dan Talaycofa6454f2012-04-05 10:04:13 -07001750 # Install the first set of flows
1751 for f_idx in range(flow_count):
Rich Lane5c3151c2013-01-03 17:15:41 -08001752 self.controller.message_send(flows[0][f_idx])
Rich Lane3a261d52013-01-03 17:45:08 -08001753 do_barrier(self.controller)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001754
Rich Lane9a003812012-10-04 17:17:59 -07001755 logging.info("Installed %d flows" % flow_count)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001756
1757 # Repeatedly modify all the flows back and forth
1758 updates = 0
1759 # Report status about 5 times
1760 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001761 start = time.time()
1762 for iter_idx in range(iter_count):
1763 if not iter_idx % mod_val:
Rich Lane9a003812012-10-04 17:17:59 -07001764 logging.info("Flow Toggle: iter %d of %d. " %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001765 (iter_idx, iter_count) +
1766 "%d updates in %d secs" %
1767 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001768 for toggle in range(2):
1769 t_idx = 1 - toggle
1770 for f_idx in range(flow_count):
Rich Lane5c3151c2013-01-03 17:15:41 -08001771 self.controller.message_send(flows[t_idx][f_idx])
Dan Talaycofa6454f2012-04-05 10:04:13 -07001772 updates += 1
Rich Lane3a261d52013-01-03 17:45:08 -08001773 do_barrier(self.controller)
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001774
1775 end = time.time()
1776 divisor = end - start or (end - start + 1)
Rich Lane9a003812012-10-04 17:17:59 -07001777 logging.info("Flow toggle: %d iterations" % iter_count)
1778 logging.info(" %d flow mods in %d secs, %d mods/sec" %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001779 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001780
1781
Dan Talayco8a64e332012-03-28 14:53:20 -07001782# You can pick and choose these by commenting tests in or out
1783iter_classes = [
1784 basic.PacketIn,
1785 basic.PacketOut,
1786 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001787 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001788 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001789 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001790 AllWildcardMatch,
1791 AllWildcardMatchTagged,
1792 SingleWildcardMatch,
1793 SingleWildcardMatchTagged,
1794 ExactMatch,
1795 ExactMatchTagged,
1796 SingleWildcardMatch,
1797 ModifyL2Src,
1798 ModifyL2Dst,
1799 ModifyL2SrcMC,
1800 ModifyL2DstMC,
1801 ModifyL2SrcDstMC
1802 ]
1803
Rich Lane0a4f6372013-01-02 14:40:22 -08001804@disabled
Dan Talayco8a64e332012-03-28 14:53:20 -07001805class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001806 """
1807 Iterate over a bunch of test cases
1808
1809 The cases come from the list above
1810 """
1811
Dan Talayco8a64e332012-03-28 14:53:20 -07001812 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001813 count = test_param_get('iter_count', default=10)
Dan Talayco8a64e332012-03-28 14:53:20 -07001814 tests_done = 0
Rich Lane9a003812012-10-04 17:17:59 -07001815 logging.info("Running iteration test " + str(count) + " times")
Dan Talayco8a64e332012-03-28 14:53:20 -07001816 start = time.time()
1817 last = start
1818 for idx in range(count):
Rich Lane9a003812012-10-04 17:17:59 -07001819 logging.info("Iteration " + str(idx + 1))
Dan Talayco8a64e332012-03-28 14:53:20 -07001820 for cls in iter_classes:
1821 test = cls()
1822 test.inheritSetup(self)
1823 test.runTest()
1824 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001825 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001826 if time.time() - last > 60:
1827 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001828 logging.info(
Dan Talaycofa6454f2012-04-05 10:04:13 -07001829 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1830 (idx, count, tests_done, last - start) +
1831 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001832 stats = all_stats_get(self)
1833 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001834 logging.info("\nIterCases ran %d tests in %d seconds." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001835 (tests_done, last - start))
Rich Lane9a003812012-10-04 17:17:59 -07001836 logging.info(" flows: %d. packets: %d. bytes: %d" %
Dan Talayco8a64e332012-03-28 14:53:20 -07001837 (stats["flows"], stats["packets"], stats["bytes"]))
Rich Lane9a003812012-10-04 17:17:59 -07001838 logging.info(" active: %d. lookups: %d. matched %d." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001839 (stats["active"], stats["lookups"], stats["matched"]))
1840
Dan Talayco4b2bee62010-07-20 14:10:05 -07001841#@todo Need to implement tagged versions of the above tests
1842#
1843#@todo Implement a test case that strips tag 2, adds tag 3
1844# and modifies tag 4 to tag 5. Then verify (in addition) that
1845# tag 6 does not get modified.
1846
Rich Lane0a4f6372013-01-02 14:40:22 -08001847@disabled
Dan Talayco4b2bee62010-07-20 14:10:05 -07001848class MixedVLAN(BaseMatchCase):
1849 """
1850 Test mixture of VLAN tag actions
1851
1852 Strip tag 2 on port 1, send to port 2
1853 Add tag 3 on port 1, send to port 2
1854 Modify tag 4 to 5 on port 1, send to port 2
1855 All other traffic from port 1, send to port 3
1856 All traffic from port 2 sent to port 4
1857 Use exact matches with different packets for all mods
1858 Verify the following: (port, vid)
1859 (port 1, vid 2) => VLAN tag stripped, out port 2
1860 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1861 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1862 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1863 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1864 (port 2, no tag) => untagged packet out port 4
1865 (port 2, vid 2-6) => unmodified packet out port 4
1866
1867 Variation: Might try sending VID 5 to port 3 and check.
1868 If only VID 5 distinguishes pkt, this will fail on some platforms
1869 """
1870
Rich Lane97e99652013-01-02 17:23:20 -08001871@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -07001872class MatchEach(base_tests.SimpleDataPlane):
Rich Lane8d6ab272012-09-23 18:06:20 -07001873 """
1874 Check that each match field is actually matched on.
1875 Installs two flows that differ in one field. The flow that should not
1876 match has a higher priority, so if that field is ignored during matching
1877 the packet will be sent out the wrong port.
1878
1879 TODO test UDP, ARP, ICMP, etc.
1880 """
1881 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001882 of_ports = config["port_map"].keys()
Rich Lane8d6ab272012-09-23 18:06:20 -07001883 of_ports.sort()
1884 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1885
Rich Lane9a003812012-10-04 17:17:59 -07001886 delete_all_flows(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001887
Rich Laned0478ff2013-03-11 12:46:58 -07001888 pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2)
Rich Lane8d6ab272012-09-23 18:06:20 -07001889 ingress_port = of_ports[0]
1890 egress_port = of_ports[1]
1891
1892 def testField(field, mask):
Rich Lane9a003812012-10-04 17:17:59 -07001893 logging.info("Testing field %s" % field)
Rich Lane8d6ab272012-09-23 18:06:20 -07001894
1895 def addFlow(matching, priority, output_port):
1896 match = packet_to_flow_match(self, pkt)
1897 self.assertTrue(match is not None, "Could not generate flow match from pkt")
1898 match.wildcards &= ~ofp.OFPFW_IN_PORT
1899 match.in_port = ingress_port
1900 if not matching:
1901 # Make sure flow doesn't match
1902 orig = getattr(match, field)
1903 if isinstance(orig, list):
1904 new = map(lambda a: ~a[0] & a[1], zip(orig, mask))
1905 else:
1906 new = ~orig & mask
1907 setattr(match, field, new)
Rich Laneba3f0e22013-03-11 16:43:57 -07001908 request = ofp.message.flow_add()
Rich Lane8d6ab272012-09-23 18:06:20 -07001909 request.match = match
1910 request.buffer_id = 0xffffffff
1911 request.priority = priority
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001912 act = ofp.action.output()
Rich Lane8d6ab272012-09-23 18:06:20 -07001913 act.port = output_port
Rich Lanec495d9e2013-03-08 17:43:36 -08001914 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -07001915 logging.info("Inserting flow")
Rich Lane8d6ab272012-09-23 18:06:20 -07001916 self.controller.message_send(request)
1917
1918 # This flow should match.
1919 addFlow(matching=True, priority=0, output_port=egress_port)
1920 # This flow should not match, but it has a higher priority.
1921 addFlow(matching=False, priority=1, output_port=ofp.OFPP_IN_PORT)
1922
Rich Lane3a261d52013-01-03 17:45:08 -08001923 do_barrier(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001924
Rich Lane9a003812012-10-04 17:17:59 -07001925 logging.info("Sending packet to dp port " + str(ingress_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001926 self.dataplane.send(ingress_port, str(pkt))
1927
1928 exp_pkt_arg = None
1929 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -07001930 if config["relax"]:
Rich Lane8d6ab272012-09-23 18:06:20 -07001931 exp_pkt_arg = pkt
1932 exp_port = egress_port
1933
1934 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
1935 exp_pkt=exp_pkt_arg)
1936 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -07001937 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001938 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
1939 self.assertEqual(str(pkt), str(rcv_pkt), 'Response packet does not match send packet')
1940
Ed Swierkb603b192012-12-12 15:38:49 -08001941 wildcards = required_wildcards(self)
Rich Lane8d6ab272012-09-23 18:06:20 -07001942 # TODO in_port
Ed Swierkb603b192012-12-12 15:38:49 -08001943 if not (wildcards & ofp.OFPFW_DL_SRC):
Rich Laned0478ff2013-03-11 12:46:58 -07001944 testField("eth_src", [0xff]*6)
Ed Swierkb603b192012-12-12 15:38:49 -08001945 if not (wildcards & ofp.OFPFW_DL_DST):
Rich Laned0478ff2013-03-11 12:46:58 -07001946 testField("eth_dst", [0xff]*6)
Ed Swierkb603b192012-12-12 15:38:49 -08001947 if not (wildcards & ofp.OFPFW_DL_TYPE):
Rich Laned0478ff2013-03-11 12:46:58 -07001948 testField("eth_type", 0xffff)
Ed Swierkb603b192012-12-12 15:38:49 -08001949 if not (wildcards & ofp.OFPFW_DL_VLAN):
Rich Laned0478ff2013-03-11 12:46:58 -07001950 testField("vlan_vid", 0xfff)
1951 # TODO vlan_pcp
Ed Swierkb603b192012-12-12 15:38:49 -08001952 if not (wildcards & ofp.OFPFW_NW_SRC_ALL):
Rich Laned0478ff2013-03-11 12:46:58 -07001953 testField("ipv4_src", 0xffffffff)
Ed Swierkb603b192012-12-12 15:38:49 -08001954 if not (wildcards & ofp.OFPFW_NW_DST_ALL):
Rich Laned0478ff2013-03-11 12:46:58 -07001955 testField("ipv4_dst", 0xffffffff)
Ed Swierkb603b192012-12-12 15:38:49 -08001956 if not (wildcards & ofp.OFPFW_NW_TOS):
Rich Laned0478ff2013-03-11 12:46:58 -07001957 testField("ip_dscp", 0x3f)
Ed Swierkb603b192012-12-12 15:38:49 -08001958 if not (wildcards & ofp.OFPFW_NW_PROTO):
Rich Laned0478ff2013-03-11 12:46:58 -07001959 testField("ip_proto", 0xff)
Ed Swierkb603b192012-12-12 15:38:49 -08001960 if not (wildcards & ofp.OFPFW_TP_SRC):
Rich Laned0478ff2013-03-11 12:46:58 -07001961 testField("tcp_src", 0xffff)
Ed Swierkb603b192012-12-12 15:38:49 -08001962 if not (wildcards & ofp.OFPFW_TP_DST):
Rich Laned0478ff2013-03-11 12:46:58 -07001963 testField("tcp_dst", 0xffff)
Rich Lane8d6ab272012-09-23 18:06:20 -07001964
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07001965class DirectBadPacketBase(base_tests.SimpleDataPlane):
1966 """
1967 Base class for sending single packets with single flow table entries.
1968 Used to verify matching of unusual packets and parsing/matching of
1969 corrupted packets.
1970
1971 The idea is to generate packets that may either be totally malformed or
1972 malformed just enough to trick the flow matcher into making mistakes.
1973
1974 Generate a 'bad' packet
1975 Generate and install a matching flow
1976 Add action to direct the packet to an egress port
1977 Send the packet to ingress dataplane port
1978 Verify the packet is received at the egress port only
1979 """
1980
1981 RESULT_MATCH = "MATCH"
1982 RESULT_NOMATCH = "NO MATCH"
1983 RESULT_ANY = "ANY MATCH"
1984
1985 def runTest(self):
1986 pass
1987 # TODO:
1988 # - ICMP?
1989 # - VLAN?
1990 # - action
1991
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07001992 def createMatch(self, **kwargs):
Rich Lane0237baf2013-03-11 22:34:59 -07001993 match = ofp.match()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07001994 match.wildcards = ofp.OFPFW_ALL
1995 fields = {
Rich Laned0478ff2013-03-11 12:46:58 -07001996 'eth_dst': ofp.OFPFW_DL_DST,
1997 'eth_src': ofp.OFPFW_DL_SRC,
1998 'eth_type': ofp.OFPFW_DL_TYPE,
1999 'vlan_vid': ofp.OFPFW_DL_VLAN,
2000 'ipv4_src': ofp.OFPFW_NW_SRC_MASK,
2001 'ipv4_dst': ofp.OFPFW_NW_DST_MASK,
2002 'ip_dscp': ofp.OFPFW_NW_TOS,
2003 'ip_proto': ofp.OFPFW_NW_PROTO,
2004 'tcp_src': ofp.OFPFW_TP_SRC,
2005 'tcp_dst': ofp.OFPFW_TP_DST,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002006 }
2007 for key in kwargs:
2008 setattr(match, key, kwargs[key])
2009 match.wildcards &= ~fields[key]
2010 return match
2011
2012 def testPktsAgainstFlow(self, pkts, acts, match):
2013 if type(acts) != list:
2014 acts = [acts]
2015 for info in pkts:
2016 title, pkt, expected_result = info
2017 self.testPktAgainstFlow(title, pkt, acts, match, expected_result)
2018
2019 def testPktAgainstFlow(self, title, pkt, acts, match, expected_result):
2020 of_ports = config["port_map"].keys()
2021 of_ports.sort()
2022 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
2023
Rich Lane32bf9482013-01-03 17:26:30 -08002024 delete_all_flows(self.controller)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002025
2026 ingress_port = of_ports[0]
2027 egress_port = of_ports[1]
2028
2029 logging.info("Testing packet '%s', expect result %s" %
2030 (title, expected_result))
2031 logging.info("Ingress %s to egress %s" %
2032 (str(ingress_port), str(egress_port)))
2033 logging.info("Packet:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002034 logging.info(inspect_packet(pkt))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002035
2036 match.in_port = ingress_port
2037
Rich Laneba3f0e22013-03-11 16:43:57 -07002038 request = ofp.message.flow_add()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002039 request.match = match
Rich Lane44cf12d2012-10-15 11:10:45 -07002040 request.priority = 1
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002041
2042 request.buffer_id = 0xffffffff
2043 for act in acts:
2044 act.port = egress_port
Rich Lanec495d9e2013-03-08 17:43:36 -08002045 request.actions.append(act)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002046
2047 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08002048 self.controller.message_send(request)
Rich Lane44cf12d2012-10-15 11:10:45 -07002049
2050 # This flow speeds up negative tests
2051 logging.info("Inserting catch-all flow")
Rich Laneba3f0e22013-03-11 16:43:57 -07002052 request2 = ofp.message.flow_add()
Rich Lane44cf12d2012-10-15 11:10:45 -07002053 request2.match = self.createMatch()
Dan Talayco3bfc8222013-02-13 18:18:57 -08002054 request2.match.wildcards &= ~ofp.OFPFW_IN_PORT
2055 request2.match.in_port = ingress_port
2056
Rich Lane44cf12d2012-10-15 11:10:45 -07002057 request2.priority = 0
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002058 act = ofp.action.output()
Rich Lane44cf12d2012-10-15 11:10:45 -07002059 act.port = ofp.OFPP_IN_PORT
Rich Lanec495d9e2013-03-08 17:43:36 -08002060 request2.actions.append(act)
Rich Lane5c3151c2013-01-03 17:15:41 -08002061 self.controller.message_send(request2)
Rich Lane44cf12d2012-10-15 11:10:45 -07002062
Rich Lane3a261d52013-01-03 17:45:08 -08002063 do_barrier(self.controller)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002064
Dan Talayco3bfc8222013-02-13 18:18:57 -08002065 pkt_str = str(pkt)
2066 if config["minsize"] > len(str(pkt)):
2067 pkt_str += '0' * (config["minsize"] - len(str(pkt)))
2068
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002069 logging.info("Sending packet to dp port " +
2070 str(ingress_port))
Dan Talayco3bfc8222013-02-13 18:18:57 -08002071 self.dataplane.send(ingress_port, pkt_str)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002072
2073 exp_pkt_arg = None
2074 exp_port = None
2075 if config["relax"]:
2076 exp_pkt_arg = pkt
2077 exp_port = egress_port
2078
Rich Lane44cf12d2012-10-15 11:10:45 -07002079 if expected_result == self.RESULT_MATCH:
2080 timeout = -1 # default timeout
2081 else:
2082 timeout = 1 # short timeout for negative tests
2083
2084 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(exp_pkt=exp_pkt_arg,
2085 timeout=timeout)
2086 if rcv_port == ingress_port:
2087 logging.debug("Packet matched catch-all flow")
2088 rcv_pkt = None
2089
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002090 if expected_result == self.RESULT_MATCH:
2091 self.assertTrue(rcv_pkt is not None,
2092 "Did not receive packet, expected a match")
2093 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
2094 str(rcv_port))
2095 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
2096 str_pkt = str(pkt)
2097 str_rcv_pkt = str(rcv_pkt)
2098 str_rcv_pkt = str_rcv_pkt[0:len(str_pkt)]
2099 if str_pkt != str_rcv_pkt:
2100 logging.error("Response packet does not match send packet")
2101 logging.info("Response:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002102 logging.info(inspect_packet(scapy.Ether(rcv_pkt)))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002103 self.assertEqual(str_pkt, str_rcv_pkt,
2104 'Response packet does not match send packet')
2105 elif expected_result == self.RESULT_NOMATCH:
2106 self.assertTrue(rcv_pkt is None, "Received packet, expected drop")
2107 else:
2108 logging.debug("Match or drop accepted. Result = %s" %
2109 ("match" if rcv_pkt is not None else "drop"))
2110
2111
2112class DirectBadIpTcpPacketsBase(DirectBadPacketBase):
2113 """
2114 Base class for TCP and UDP parsing/matching verification under corruptions
2115 """
2116 def runTest(self):
2117 pass
2118
2119 def runTestWithProto(self, protoName = 'TCP'):
Rich Laned0478ff2013-03-11 12:46:58 -07002120 eth_dst='00:01:02:03:04:05'
2121 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002122 ip_src='192.168.0.1'
2123 ip_dst='192.168.0.2'
2124 ip_tos=0
2125 tcp_sport=1234
2126 tcp_dport=80
2127
2128 # Generate a proper packet for constructing a match
2129 tp = None
2130 if protoName == 'TCP':
2131 tp = scapy.TCP
2132 proto = 6
2133 elif protoName == 'UDP':
2134 tp = scapy.UDP
2135 proto = 17
2136 else:
2137 raise Exception("Passed in unknown proto name")
2138
Rich Laned0478ff2013-03-11 12:46:58 -07002139 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002140 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2141 tp(sport=tcp_sport, dport=tcp_dport)
2142 match = packet_to_flow_match(self, match_pkt)
2143 self.assertTrue(match is not None,
2144 "Could not generate flow match from pkt")
2145 match.wildcards &= ~ofp.OFPFW_IN_PORT
2146
2147 def testPacket(title, pkt, result):
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002148 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002149 pkts = [
2150 [title, pkt, result]
2151 ]
2152 self.testPktsAgainstFlow(pkts, act, match)
2153
2154 # Try incomplete IP headers
2155 testPacket("Incomplete IP header (1 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002156 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002157 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:1],
2158 self.RESULT_NOMATCH,
2159 )
2160 testPacket("Incomplete IP header (2 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002161 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002162 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:2],
2163 self.RESULT_NOMATCH,
2164 )
2165 testPacket("Incomplete IP header (3 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002166 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002167 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:3],
2168 self.RESULT_NOMATCH,
2169 )
2170 testPacket("Incomplete IP header (12 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002171 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002172 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:12],
2173 self.RESULT_NOMATCH,
2174 )
2175 testPacket("Incomplete IP header (16 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002176 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002177 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:16],
2178 self.RESULT_NOMATCH,
2179 )
2180 testPacket("Incomplete IP header (19 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002181 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002182 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:19],
2183 self.RESULT_NOMATCH,
2184 )
2185
2186 # Try variations where the TCP header is missing or incomplete. As we
2187 # saw bugs before where buffers were reused and lengths weren't honored,
2188 # we initiatlize once with a non-matching full packet and once with a
2189 # matching full packet.
2190 testPacket("Non-Matching TCP packet, warming buffer",
Rich Laned0478ff2013-03-11 12:46:58 -07002191 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002192 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2193 tp(sport=tcp_sport, dport=tcp_dport + 1),
2194 self.RESULT_NOMATCH,
2195 )
2196 testPacket("Missing TCP header, buffer warmed with non-match",
Rich Laned0478ff2013-03-11 12:46:58 -07002197 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002198 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2199 self.RESULT_NOMATCH,
2200 )
2201 testPacket("Matching TCP packet, warming buffer",
Rich Laned0478ff2013-03-11 12:46:58 -07002202 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002203 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2204 tp(sport=tcp_sport, dport=tcp_dport),
2205 self.RESULT_MATCH,
2206 )
2207 testPacket("Missing TCP header, buffer warmed with match",
Rich Laned0478ff2013-03-11 12:46:58 -07002208 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002209 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2210 self.RESULT_NOMATCH,
2211 )
2212 testPacket("Truncated TCP header: 2 bytes",
Rich Laned0478ff2013-03-11 12:46:58 -07002213 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002214 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2215 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:2]),
2216 self.RESULT_NOMATCH,
2217 )
2218
2219 # Play with IP header length values that put the start of TCP either
2220 # inside the generated TCP header or beyond. In some cases it may even
2221 # be beyond the packet boundary. Also play with IP options and more
2222 # importantly IP total length corruptions.
2223 testPacket("TCP packet, corrupt ihl (0x6)",
2224 simple_tcp_packet(ip_ihl=6),
2225 self.RESULT_NOMATCH,
2226 )
2227 testPacket("TCP packet, corrupt ihl (0xf)",
2228 simple_tcp_packet(ip_ihl=0xf), # ihl = 15 * 4 = 60
2229 self.RESULT_NOMATCH,
2230 )
2231 testPacket("TCP packet, corrupt ihl and total length",
2232 simple_tcp_packet(ip_ihl=0xf, pktlen=56), # ihl = 15 * 4 = 60,
2233 self.RESULT_NOMATCH,
2234 )
2235 testPacket("Corrupt IPoption: First 4 bytes of matching TCP header",
2236 simple_tcp_packet(
2237 ip_options=scapy.IPOption('\x04\xd2\x00\x50'),
2238 tcp_dport=2, tcp_sport=2
2239 ),
2240 self.RESULT_NOMATCH,
2241 )
2242 testPacket("Missing TCP header, corrupt ihl",
Rich Laned0478ff2013-03-11 12:46:58 -07002243 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002244 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto),
2245 self.RESULT_NOMATCH,
2246 )
2247 testPacket("Missing TCP header, corrupt total length",
Rich Laned0478ff2013-03-11 12:46:58 -07002248 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002249 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, len= 100),
2250 self.RESULT_NOMATCH,
2251 )
2252 testPacket("Missing TCP header, corrupt ihl and total length",
Rich Laned0478ff2013-03-11 12:46:58 -07002253 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002254 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto, len=43),
2255 self.RESULT_NOMATCH,
2256 )
2257 testPacket("Incomplete IP header (12 bytes), corrupt ihl and total length",
Rich Laned0478ff2013-03-11 12:46:58 -07002258 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002259 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:12],
2260 self.RESULT_NOMATCH,
2261 )
2262 testPacket("Incomplete IP header (16 bytes), corrupt ihl and total length",
Rich Laned0478ff2013-03-11 12:46:58 -07002263 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002264 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:16],
2265 self.RESULT_NOMATCH,
2266 )
2267
2268 # Try an incomplete TCP header that has enough bytes to carry source and
2269 # destination ports. As that is all we care about during matching, some
2270 # implementations may match and some may drop the packet
2271 testPacket("Incomplete TCP header: src/dst port present",
Rich Laned0478ff2013-03-11 12:46:58 -07002272 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002273 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2274 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:4]),
2275 self.RESULT_ANY,
2276 )
2277
2278 for i in range(1):
2279 for length in range(40 / 4): # IPv4 options are a maximum of 40 in length
2280 bytes = "".join([("%c" % random.randint(0, 255)) for x in range(length * 4)])
Rich Laned0478ff2013-03-11 12:46:58 -07002281 eth = scapy.Ether(dst=eth_dst, src=eth_src)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002282 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2283 tcp = tp(sport=tcp_sport, dport=tcp_dport+1)
2284 pkt = eth / ip
2285 pkt = pkt / bytes
2286 pkt = pkt / str(tcp)
2287 testPacket("Random IP options len = %d - TP match must fail" % length * 4,
2288 pkt,
2289 self.RESULT_NOMATCH
2290 )
2291
Rich Laned0478ff2013-03-11 12:46:58 -07002292 eth = scapy.Ether(dst=eth_dst, src=eth_src)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002293 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2294 tcp = tp(sport=tcp_sport, dport=tcp_dport)
2295 pkt = eth / ip
2296 pkt = pkt / bytes
2297 pkt = pkt / str(tcp)
2298
2299 testPacket("Random IP options len = %d - May match",
2300 pkt,
2301 self.RESULT_ANY
2302 )
2303
2304
2305class DirectBadIpTcpPackets(DirectBadIpTcpPacketsBase):
2306 """
2307 Verify IP/TCP parsing and matching. Focus on packet corruptions
2308 """
2309 def runTest(self):
2310 self.runTestWithProto(protoName = 'TCP')
2311
2312class DirectBadIpUdpPackets(DirectBadIpTcpPacketsBase):
2313 """
2314 Verify IP/UDP parsing and matching. Focus on packet corruptions
2315 """
2316 def runTest(self):
2317 self.runTestWithProto(protoName = 'UDP')
2318
2319class DirectBadLlcPackets(DirectBadPacketBase):
2320 """
2321 Verify LLC/SNAP parsing and matching. Focus on packet corruptions
2322 """
2323 def runTest(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002324 eth_dst='00:01:02:03:04:05'
2325 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002326 ip_src='192.168.0.1'
2327 ip_dst='192.168.0.2'
2328 ip_tos=0
2329 tcp_sport=1234
2330 tcp_dport=80
2331
2332 IS_SNAP_IP = 1
2333 IS_SNAP_IP_CORRUPT = 2
2334 IS_NOT_SNAP_IP = 3
2335
2336 def testPacketTcpMatch(title, llc):
Rich Laned0478ff2013-03-11 12:46:58 -07002337 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002338 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2339 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
2340 match = packet_to_flow_match(self, match_pkt)
2341 self.assertTrue(match is not None,
2342 "Could not generate flow match from pkt")
2343 match.wildcards &= ~ofp.OFPFW_IN_PORT
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002344 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002345
2346 self.testPktsAgainstFlow(
2347 [[
2348 "TCP match - LLC frame correct length - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002349 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002350 self.RESULT_ANY,
2351 ]],
2352 act, match
2353 )
2354
2355 # Corrupt length field
2356 ethLen = random.randint(0, 1535)
2357 self.testPktsAgainstFlow(
2358 [[
2359 "TCP match - LLC frame corrupted length - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002360 scapy.Ether(dst=eth_dst, src=eth_src, type=ethLen) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002361 self.RESULT_ANY,
2362 ]],
2363 act, match
2364 )
2365
2366 def testPacketEthSrcDstMatch(title, llc):
2367 # Matching based on Ethernet source and destination
Rich Laned0478ff2013-03-11 12:46:58 -07002368 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002369 match = packet_to_flow_match(self, match_pkt)
2370 self.assertTrue(match is not None,
2371 "Could not generate flow match from pkt")
2372 match.wildcards &= ~ofp.OFPFW_IN_PORT
2373 match.wildcards |= ofp.OFPFW_DL_TYPE
2374 self.testPktsAgainstFlow(
2375 [[
2376 "Eth addr match - LLC frame correct length- %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002377 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002378 self.RESULT_MATCH,
2379 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002380 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002381 )
2382
2383 # Corrupt length field
2384 ethLen = random.randint(0, 1535)
2385 self.testPktsAgainstFlow(
2386 [[
2387 "Eth addr match - LLC frame corrupted length- %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002388 scapy.Ether(dst=eth_dst, src=eth_src, type=ethLen) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002389 self.RESULT_ANY,
2390 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002391 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002392 )
2393
2394 def testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip):
2395 # Matching based on Ethernet source, destination and type
Rich Laned0478ff2013-03-11 12:46:58 -07002396 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=0x800)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002397 match = packet_to_flow_match(self, match_pkt)
2398 self.assertTrue(match is not None,
2399 "Could not generate flow match from pkt")
2400 match.wildcards &= ~ofp.OFPFW_IN_PORT
2401 if is_snap_ip == IS_SNAP_IP:
2402 is_match = self.RESULT_MATCH
2403 elif is_snap_ip == IS_SNAP_IP_CORRUPT:
2404 is_match = self.RESULT_ANY
2405 else:
2406 is_match = self.RESULT_NOMATCH
2407 self.testPktsAgainstFlow(
2408 [[
2409 "Eth addr+type match - LLC frame correct length - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002410 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002411 is_match,
2412 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002413 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002414 )
2415
2416 # Corrupt length field
2417 ethLen = random.randint(0, 1535)
2418 self.testPktsAgainstFlow(
2419 [[
2420 "Eth addr+type match - LLC frame corrupted length - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002421 scapy.Ether(dst=eth_dst, src=eth_src, type=ethLen) / llc,
Christian Dickmanne9b6d252012-10-08 22:56:50 -07002422 self.RESULT_ANY,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002423 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002424 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002425 )
2426
2427 def testPacket(title, llc, is_snap_ip):
2428 testPacketTcpMatch(title, llc)
2429 testPacketEthSrcDstMatch(title, llc)
2430 testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip)
2431
2432 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002433 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002434 IS_NOT_SNAP_IP,
2435 )
2436 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002437 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002438 IS_NOT_SNAP_IP,
2439 )
2440 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002441 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002442 IS_NOT_SNAP_IP,
2443 )
2444 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002445 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002446 IS_NOT_SNAP_IP,
2447 )
2448 testPacket("LLC - SNAP - Small bogus payload",
2449 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2450 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2451 IS_SNAP_IP_CORRUPT,
2452 )
2453 testPacket("LLC - SNAP - Max -1 bogus payload",
2454 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2455 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2456 IS_NOT_SNAP_IP,
2457 )
2458 testPacket("LLC - SNAP - Max bogus payload",
2459 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2460 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2461 IS_NOT_SNAP_IP,
2462 )
2463 testPacket("LLC - SNAP - IP - TCP",
2464 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2465 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2466 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2467 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2468 IS_SNAP_IP,
2469 )
2470
2471
2472class DirectLlcPackets(DirectBadPacketBase):
2473 """
2474 Verify LLC/SNAP parsing (valid and corrupted packets) and matching
2475 """
2476 def runTest(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002477 eth_dst='00:01:02:03:04:05'
2478 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002479 ip_src='192.168.0.1'
2480 ip_dst='192.168.0.2'
2481 ip_tos=0
2482 tcp_sport=1234
2483 tcp_dport=80
2484
2485 # Test ethertype in face of LLC/SNAP and OFP_DL_TYPE_NOT_ETH_TYPE
2486 IS_SNAP_NOT_IP = 1
2487 IS_SNAP_AND_IP = 2
2488 IS_NOT_SNAP = 3
2489
2490 def testPacketEthTypeIP(title, llc, is_snap):
Rich Laned0478ff2013-03-11 12:46:58 -07002491 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=0x800)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002492 match = packet_to_flow_match(self, match_pkt)
2493 self.assertTrue(match is not None,
2494 "Could not generate flow match from pkt")
2495 match.wildcards &= ~ofp.OFPFW_IN_PORT
2496 pkts = []
2497 if is_snap == IS_NOT_SNAP or is_snap == IS_SNAP_NOT_IP:
2498 result = self.RESULT_NOMATCH
2499 else:
2500 result = self.RESULT_MATCH
2501 pkts.append([
2502 "Ether type 0x800 match - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002503 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002504 result,
2505 ])
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002506 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002507 self.testPktsAgainstFlow(pkts, act, match)
2508
2509 def testPacketEthTypeNotEth(title, llc, is_snap):
Rich Laned0478ff2013-03-11 12:46:58 -07002510 match_pkt = scapy.Ether(dst = eth_dst, src = eth_src,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002511 type = ofp.OFP_DL_TYPE_NOT_ETH_TYPE)
2512 match = packet_to_flow_match(self, match_pkt)
2513 self.assertTrue(match is not None,
2514 "Could not generate flow match from pkt")
2515 match.wildcards &= ~ofp.OFPFW_IN_PORT
2516 pkts = []
2517 if is_snap == IS_NOT_SNAP:
2518 result = self.RESULT_MATCH
2519 else:
2520 result = self.RESULT_NOMATCH
2521 pkts.append([
2522 "Ether type OFP_DL_TYPE_NOT_ETH_TYPE match - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002523 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002524 result,
2525 ])
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002526 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002527 self.testPktsAgainstFlow(pkts, act, match)
2528
2529 def testPacket(title, llc, is_snap):
2530 testPacketEthTypeIP(title, llc, is_snap)
2531 testPacketEthTypeNotEth(title, llc, is_snap)
2532
2533 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002534 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
2535 IS_NOT_SNAP,
2536 )
2537 testPacket("LLC (with information field) - No SNAP - No Payload",
2538 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x12) / "S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002539 IS_NOT_SNAP,
2540 )
2541 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002542 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002543 IS_NOT_SNAP,
2544 )
2545 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002546 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002547 IS_NOT_SNAP,
2548 )
2549 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002550 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002551 IS_NOT_SNAP,
2552 )
2553 testPacket("LLC - SNAP - Non-default OUI",
2554 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2555 scapy.SNAP(OUI=0x000001, code=0x800) / ("S" * 10),
2556 IS_NOT_SNAP,
2557 )
2558 testPacket("LLC - SNAP - Default OUI",
2559 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2560 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2561 IS_SNAP_AND_IP,
2562 )
2563 testPacket("LLC - SNAP - Max -1 bogus payload",
2564 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2565 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2566 IS_SNAP_NOT_IP,
2567 )
2568 testPacket("LLC - SNAP - Max bogus payload",
2569 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2570 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2571 IS_SNAP_NOT_IP,
2572 )
2573 testPacket("LLC - SNAP - IP - TCP",
2574 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2575 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2576 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2577 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2578 IS_SNAP_AND_IP,
2579 )
2580
2581
2582class DirectArpPackets(DirectBadPacketBase):
2583 """
2584 Verify ARP parsing (valid and corrupted packets) and ARP matching
2585 """
2586 def runTest(self):
2587 self.testArpHandling()
2588
2589 def testArpHandling(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002590 eth_dst='00:01:02:03:04:05'
2591 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002592 ip_src='192.168.0.1'
2593 ip_dst='192.168.0.2'
2594 ip_src2='192.168.1.1'
2595 ip_dst2='192.168.1.2'
2596 ip_tos=0
2597 tcp_sport=1234
2598 tcp_dport=80
2599
2600 def testPacket(title, arp_match, arp_pkt, result):
2601 pkts = []
2602
Rich Laned0478ff2013-03-11 12:46:58 -07002603 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src) / arp_match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002604 match = packet_to_flow_match(self, match_pkt)
2605 self.assertTrue(match is not None,
2606 "Could not generate flow match from pkt")
2607 match.wildcards &= ~ofp.OFPFW_IN_PORT
2608
2609 pkts.append([
2610 title,
Rich Laned0478ff2013-03-11 12:46:58 -07002611 scapy.Ether(dst=eth_dst, src=eth_src) / arp_pkt,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002612 result,
2613 ])
2614
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002615 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002616 self.testPktsAgainstFlow(pkts, act, match)
2617
2618 testPacket("Basic ARP",
2619 scapy.ARP(psrc=ip_src, pdst=ip_dst, op = 1),
Rich Laned0478ff2013-03-11 12:46:58 -07002620 scapy.ARP(hwdst = '00:00:00:00:00:00', hwsrc = eth_src,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002621 psrc = ip_src, pdst = ip_dst, hwlen = 6, plen = 4,
2622 ptype = 0x800, hwtype = 1, op = 1),
2623 self.RESULT_MATCH
2624 )
2625 # More stuff:
2626 # - Non matches on any property
2627 # - Corrupted hwlen and plen
2628 # - Other hwtype, ptype
2629 # - Truncated ARP pkt
2630
2631
2632class DirectVlanPackets(DirectBadPacketBase):
2633 """
2634 Verify VLAN parsing (valid and corrupted packets) and ARP matching
2635 """
2636 def runTest(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002637 eth_dst='00:01:02:03:04:05'
2638 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002639 ip_src='192.168.0.1'
2640 ip_dst='192.168.0.2'
2641 ip_src2='192.168.1.1'
2642 ip_dst2='192.168.1.2'
2643 ip_tos=0
2644 tcp_sport=1234
2645 tcp_dport=80
2646
2647 def testPacket(title, match, pkt, result):
2648 pkts = []
2649
2650 self.assertTrue(match is not None,
2651 "Could not generate flow match from pkt")
2652 match.wildcards &= ~ofp.OFPFW_IN_PORT
2653
2654 pkts.append([
2655 "%s" % title,
2656 pkt,
2657 result,
2658 ])
2659
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002660 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002661 self.testPktsAgainstFlow(pkts, act, match)
2662
2663 testPacket("Basic MAC matching - IPv4 payload",
Rich Laned0478ff2013-03-11 12:46:58 -07002664 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2665 scapy.Ether(dst=eth_dst, src=eth_src, type=0x800) / scapy.IP(),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002666 self.RESULT_MATCH
2667 )
2668 testPacket("Basic MAC matching - VMware beacon - no payload",
Rich Laned0478ff2013-03-11 12:46:58 -07002669 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2670 scapy.Ether(dst=eth_dst, src=eth_src, type=0x8922),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002671 self.RESULT_MATCH
2672 )
2673 testPacket("Basic MAC matching - VMware beacon - with payload",
Rich Laned0478ff2013-03-11 12:46:58 -07002674 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2675 scapy.Ether(dst=eth_dst, src=eth_src, type=0x8922)/ ("X" * 1),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002676 self.RESULT_MATCH
2677 )
2678 testPacket("Basic MAC matching - IPv6 payload",
Rich Laned0478ff2013-03-11 12:46:58 -07002679 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2680 scapy.Ether(dst=eth_dst, src=eth_src) / scapy.IPv6(),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002681 self.RESULT_MATCH
2682 )
2683 testPacket("Basic MAC matching with VLAN tag present",
Rich Laned0478ff2013-03-11 12:46:58 -07002684 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2685 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002686 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002687 scapy.IP(),
2688 self.RESULT_MATCH
2689 )
2690 testPacket("Basic MAC matching with VLAN tag present",
Rich Laned0478ff2013-03-11 12:46:58 -07002691 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2692 eth_type=0x800),
2693 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002694 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002695 scapy.IP(),
2696 self.RESULT_MATCH
2697 )
2698 testPacket("Ether matching with VLAN tag present - No type match",
Rich Laned0478ff2013-03-11 12:46:58 -07002699 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2700 eth_type=0x801),
2701 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002702 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002703 scapy.IP(),
2704 self.RESULT_NOMATCH
2705 )
2706 testPacket("Ether matching with VLAN tag present - No type match 0x8100",
Rich Laned0478ff2013-03-11 12:46:58 -07002707 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2708 eth_type=0x8100),
2709 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002710 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002711 scapy.IP(),
2712 self.RESULT_NOMATCH
2713 )
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002714 testPacket("IP matching - VLAN tag",
Rich Laned0478ff2013-03-11 12:46:58 -07002715 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2716 eth_type=0x0800,
2717 ipv4_src=parse_ip(ip_src), ipv4_dst=parse_ip(ip_dst)),
2718 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002719 scapy.Dot1Q(prio=5, vlan=1000)/ \
2720 scapy.IP(src=ip_src, dst=ip_dst),
2721 self.RESULT_MATCH
2722 )
2723 # XXX:
2724 # - Matching on VLAN ID and Prio
2725 # - Actions
2726
2727@nonstandard
2728class DirectVlanPacketsDoubleTagged(DirectVlanPackets):
2729 """
2730 VLAN parsing for double tagged packets. Spec is ambiguous about
2731 the treatment of these cases, so broken out to be non-standard
2732 """
2733 def runTest(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002734 eth_dst='00:01:02:03:04:05'
2735 eth_src='00:06:07:08:09:0a'
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002736 ip_src='192.168.0.1'
2737 ip_dst='192.168.0.2'
2738 ip_src2='192.168.1.1'
2739 ip_dst2='192.168.1.2'
2740 ip_tos=0
2741 tcp_sport=1234
2742 tcp_dport=80
2743
2744 def testPacket(title, match, pkt, result):
2745 pkts = []
2746
2747 self.assertTrue(match is not None,
2748 "Could not generate flow match from pkt")
2749 match.wildcards &= ~ofp.OFPFW_IN_PORT
2750
2751 pkts.append([
2752 "%s" % title,
2753 pkt,
2754 result,
2755 ])
2756
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002757 act = ofp.action.output()
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002758 self.testPktsAgainstFlow(pkts, act, match)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002759 testPacket("Ether matching with double VLAN tag - Wrong 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=0x800),
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_NOMATCH
2767 )
2768 testPacket("Ether matching with double VLAN tag - Type match",
Rich Laned0478ff2013-03-11 12:46:58 -07002769 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2770 eth_type=0x8100),
2771 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002772 scapy.Dot1Q(prio=5, vlan=1000)/ \
2773 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002774 scapy.IP(),
2775 self.RESULT_MATCH
2776 )
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002777
2778
2779
Dan Talayco9f47f4d2010-06-03 13:54:37 -07002780if __name__ == "__main__":
2781 print "Please run through oft script: ./oft --test_spec=basic"