blob: 829a90efffcb29a56cfc0852477f5da27bfb7ab0 [file] [log] [blame]
Dan Talayco5eba8442010-03-10 13:58:43 -08001"""
2Test cases for testing actions taken on packets
3
4See basic.py for other info.
5
6It is recommended that these definitions be kept in their own
7namespace as different groups of tests will likely define
8similar identifiers.
9
Rich Lane477f4812012-10-04 22:49:00 -070010The switch is actively attempting to contact the controller at the address
11indicated in config.
Dan Talayco5eba8442010-03-10 13:58:43 -080012
13"""
14
Dan Talayco9f47f4d2010-06-03 13:54:37 -070015import copy
Dan Talayco5eba8442010-03-10 13:58:43 -080016import logging
Rich Laneb90a1c42012-10-05 09:16:05 -070017import time
Dan Talayco5eba8442010-03-10 13:58:43 -080018import unittest
Christian Dickmann8b59b4b2012-09-23 16:48:30 -070019import random
Rich Lane3c7cf7f2013-01-11 18:04:56 -080020import scapy.all as scapy
Dan Talayco5eba8442010-03-10 13:58:43 -080021
Rich Lane477f4812012-10-04 22:49:00 -070022from oftest import config
Dan Talayco5eba8442010-03-10 13:58:43 -080023import oftest.controller as controller
Rich Laned7b0ffa2013-03-08 15:53:42 -080024import ofp
Dan Talayco5eba8442010-03-10 13:58:43 -080025import oftest.dataplane as dataplane
Dan Talayco5eba8442010-03-10 13:58:43 -080026import oftest.parse as parse
Rich Laneb90a1c42012-10-05 09:16:05 -070027import oftest.base_tests as base_tests
28import basic # for IterCases
Dan Talayco5eba8442010-03-10 13:58:43 -080029
Christian Dickmann8b59b4b2012-09-23 16:48:30 -070030from oftest.parse import parse_mac, parse_ip
31
Rich Laneda3b5ad2012-10-03 09:05:32 -070032from oftest.testutils import *
Dan Talayco5eba8442010-03-10 13:58:43 -080033
Dan Talayco551befa2010-07-15 17:05:32 -070034WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
Dan Talayco488fbc52012-04-09 16:30:41 -070035 ofp.OFPFW_DL_VLAN | ofp.OFPFW_DL_VLAN_PCP,
Dan Talayco551befa2010-07-15 17:05:32 -070036 ofp.OFPFW_DL_SRC,
37 ofp.OFPFW_DL_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070038 (ofp.OFPFW_DL_TYPE | ofp.OFPFW_NW_SRC_ALL |
39 ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS | ofp.OFPFW_NW_PROTO |
40 ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
41 (ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
Dan Talayco551befa2010-07-15 17:05:32 -070042 ofp.OFPFW_TP_SRC,
43 ofp.OFPFW_TP_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070044 ofp.OFPFW_NW_SRC_MASK,
45 ofp.OFPFW_NW_DST_MASK,
Dan Talayco551befa2010-07-15 17:05:32 -070046 ofp.OFPFW_DL_VLAN_PCP,
47 ofp.OFPFW_NW_TOS]
48
Dan Talayco488fbc52012-04-09 16:30:41 -070049NO_WILDCARD_VALUES = [(ofp.OFPFW_ALL ^ ofp.OFPFW_IN_PORT),
50 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN),
51 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_SRC),
52 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_DST),
53 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE),
54 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO),
55 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
56 ofp.OFPFW_TP_SRC),
57 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
58 ofp.OFPFW_TP_DST),
59 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
60 ofp.OFPFW_NW_SRC_MASK),
61 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
62 ofp.OFPFW_NW_DST_MASK),
63 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN ^ ofp.OFPFW_DL_VLAN_PCP),
64 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
65 ofp.OFPFW_NW_TOS)]
66
Dan Talayco551befa2010-07-15 17:05:32 -070067MODIFY_ACTION_VALUES = [ofp.OFPAT_SET_VLAN_VID,
68 ofp.OFPAT_SET_VLAN_PCP,
69 ofp.OFPAT_STRIP_VLAN,
70 ofp.OFPAT_SET_DL_SRC,
71 ofp.OFPAT_SET_DL_DST,
72 ofp.OFPAT_SET_NW_SRC,
73 ofp.OFPAT_SET_NW_DST,
74 ofp.OFPAT_SET_NW_TOS,
75 ofp.OFPAT_SET_TP_SRC,
76 ofp.OFPAT_SET_TP_DST]
77
Dan Talayco21381562010-07-17 00:34:47 -070078TEST_VID_DEFAULT = 2
79
Rich Lane97e99652013-01-02 17:23:20 -080080@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -070081class DirectPacket(base_tests.SimpleDataPlane):
Dan Talayco5eba8442010-03-10 13:58:43 -080082 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -070083 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -080084
85 Generate a packet
86 Generate and install a matching flow
87 Add action to direct the packet to an egress port
88 Send the packet to ingress dataplane port
89 Verify the packet is received at the egress port only
90 """
91 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -070092 self.handleFlow()
93
94 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -070095 of_ports = config["port_map"].keys()
Dan Talayco5eba8442010-03-10 13:58:43 -080096 of_ports.sort()
97 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
98
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -070099 if (pkttype == 'ICMP'):
100 pkt = simple_icmp_packet()
101 else:
102 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700103 match = packet_to_flow_match(self, pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700104 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800105 self.assertTrue(match is not None,
106 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800107 act = ofp.action.output()
Dan Talayco5eba8442010-03-10 13:58:43 -0800108
109 for idx in range(len(of_ports)):
Rich Lane32bf9482013-01-03 17:26:30 -0800110 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700111
Dan Talayco5eba8442010-03-10 13:58:43 -0800112 ingress_port = of_ports[idx]
113 egress_port = of_ports[(idx + 1) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700114 logging.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700115 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800116
117 match.in_port = ingress_port
118
Rich Laneba3f0e22013-03-11 16:43:57 -0700119 request = ofp.message.flow_add()
Dan Talayco5eba8442010-03-10 13:58:43 -0800120 request.match = match
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700121
Dan Talayco5eba8442010-03-10 13:58:43 -0800122 request.buffer_id = 0xffffffff
123 act.port = egress_port
Rich Lanec495d9e2013-03-08 17:43:36 -0800124 request.actions.append(act)
Dan Talayco5eba8442010-03-10 13:58:43 -0800125
Rich Lane9a003812012-10-04 17:17:59 -0700126 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800127 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800128 do_barrier(self.controller)
Dan Talayco5eba8442010-03-10 13:58:43 -0800129
Rich Lane9a003812012-10-04 17:17:59 -0700130 logging.info("Sending packet to dp port " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800131 str(ingress_port))
132 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700133
134 exp_pkt_arg = None
135 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700136 if config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700137 exp_pkt_arg = pkt
138 exp_port = egress_port
139
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700140 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700141 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800142 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700143 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800144 str(rcv_port))
145 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
146 self.assertEqual(str(pkt), str(rcv_pkt),
147 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700148
Rich Lane97e99652013-01-02 17:23:20 -0800149@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -0700150class DirectPacketController(base_tests.SimpleDataPlane):
Rich Lane51c23b32012-07-27 16:37:25 -0700151 """
152 Send packet to the controller port
153
154 Generate a packet
155 Generate and install a matching flow
156 Add action to direct the packet to the controller port
157 Send the packet to ingress dataplane port
158 Verify the packet is received at the controller port
159 """
160 def runTest(self):
161 self.handleFlow()
162
163 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700164 of_ports = config["port_map"].keys()
Rich Lane51c23b32012-07-27 16:37:25 -0700165 of_ports.sort()
166 self.assertTrue(len(of_ports) > 0, "Not enough ports for test")
167
168 if (pkttype == 'ICMP'):
169 pkt = simple_icmp_packet()
170 else:
171 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700172 match = packet_to_flow_match(self, pkt)
Rich Lane51c23b32012-07-27 16:37:25 -0700173 match.wildcards &= ~ofp.OFPFW_IN_PORT
174 self.assertTrue(match is not None,
175 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800176 act = ofp.action.output()
Rich Lane51c23b32012-07-27 16:37:25 -0700177
Rich Lane32bf9482013-01-03 17:26:30 -0800178 delete_all_flows(self.controller)
Rich Lane51c23b32012-07-27 16:37:25 -0700179
180 ingress_port = of_ports[0]
181 match.in_port = ingress_port
182
Rich Laneba3f0e22013-03-11 16:43:57 -0700183 request = ofp.message.flow_add()
Rich Lane51c23b32012-07-27 16:37:25 -0700184 request.match = match
185
186 request.buffer_id = 0xffffffff
187 act.port = ofp.OFPP_CONTROLLER
188 act.max_len = 65535
Rich Lanec495d9e2013-03-08 17:43:36 -0800189 request.actions.append(act)
Rich Lane51c23b32012-07-27 16:37:25 -0700190
Rich Lane9a003812012-10-04 17:17:59 -0700191 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800192 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800193 do_barrier(self.controller)
Rich Lane51c23b32012-07-27 16:37:25 -0700194
Rich Lane9a003812012-10-04 17:17:59 -0700195 logging.info("Sending packet to dp port " +
Rich Lane51c23b32012-07-27 16:37:25 -0700196 str(ingress_port))
197 self.dataplane.send(ingress_port, str(pkt))
198
199 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
200
201 self.assertTrue(response is not None,
202 'Packet in message not received by controller')
203 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700204 logging.debug("Sent %s" % format_packet(pkt))
205 logging.debug("Resp %s" % format_packet(response.data))
Rich Lane51c23b32012-07-27 16:37:25 -0700206 self.assertTrue(False,
207 'Response packet does not match send packet' +
208 ' for controller port')
209
Howard Pershf97840f2012-04-10 16:30:42 -0700210
Rich Laneb90a1c42012-10-05 09:16:05 -0700211class DirectPacketQueue(base_tests.SimpleDataPlane):
Howard Pershf97840f2012-04-10 16:30:42 -0700212 """
213 Send packet to single queue on single egress port
214
215 Generate a packet
216 Generate and install a matching flow
217 Add action to direct the packet to an egress port and queue
218 Send the packet to ingress dataplane port
219 Verify the packet is received at the egress port only
220 """
221 def runTest(self):
222 self.handleFlow()
223
Howard Persh670b5672012-04-13 09:08:29 -0700224 def portQueuesGet(self, queue_stats, port_num):
225 result = []
Rich Lane5fd6faf2013-03-11 13:30:20 -0700226 for qs in queue_stats.entries:
Howard Persh670b5672012-04-13 09:08:29 -0700227 if qs.port_no != port_num:
228 continue
229 result.append(qs.queue_id)
230 return result
231
Howard Pershf97840f2012-04-10 16:30:42 -0700232 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700233 of_ports = config["port_map"].keys()
Howard Pershf97840f2012-04-10 16:30:42 -0700234 of_ports.sort()
235 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
236
237 if (pkttype == 'ICMP'):
238 pkt = simple_icmp_packet()
239 else:
240 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700241 match = packet_to_flow_match(self, pkt)
Howard Pershf97840f2012-04-10 16:30:42 -0700242 match.wildcards &= ~ofp.OFPFW_IN_PORT
243 self.assertTrue(match is not None,
244 "Could not generate flow match from pkt")
245
Howard Persh670b5672012-04-13 09:08:29 -0700246 # Get queue stats from switch
247
Rich Lane28fa9272013-03-08 16:00:25 -0800248 request = ofp.message.queue_stats_request()
Howard Persh670b5672012-04-13 09:08:29 -0700249 request.port_no = ofp.OFPP_ALL
250 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700251 (queue_stats, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700252 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
253
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800254 act = ofp.action.enqueue()
Howard Pershf97840f2012-04-10 16:30:42 -0700255
256 for idx in range(len(of_ports)):
Howard Pershf97840f2012-04-10 16:30:42 -0700257 ingress_port = of_ports[idx]
258 egress_port = of_ports[(idx + 1) % len(of_ports)]
Howard Pershf97840f2012-04-10 16:30:42 -0700259
Howard Persh670b5672012-04-13 09:08:29 -0700260 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700261 logging.info("Ingress " + str(ingress_port)
Howard Persh670b5672012-04-13 09:08:29 -0700262 + " to egress " + str(egress_port)
263 + " queue " + str(egress_queue_id)
264 )
Howard Pershf97840f2012-04-10 16:30:42 -0700265
Rich Lane32bf9482013-01-03 17:26:30 -0800266 delete_all_flows(self.controller)
Howard Pershf97840f2012-04-10 16:30:42 -0700267
Howard Persh670b5672012-04-13 09:08:29 -0700268 match.in_port = ingress_port
269
Rich Laneba3f0e22013-03-11 16:43:57 -0700270 request = ofp.message.flow_add()
Howard Persh670b5672012-04-13 09:08:29 -0700271 request.match = match
Howard Pershf97840f2012-04-10 16:30:42 -0700272
Howard Persh670b5672012-04-13 09:08:29 -0700273 request.buffer_id = 0xffffffff
274 act.port = egress_port
275 act.queue_id = egress_queue_id
Rich Lanec495d9e2013-03-08 17:43:36 -0800276 request.actions.append(act)
Howard Pershf97840f2012-04-10 16:30:42 -0700277
Rich Lane9a003812012-10-04 17:17:59 -0700278 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800279 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800280 do_barrier(self.controller)
Howard Pershf97840f2012-04-10 16:30:42 -0700281
Howard Persh670b5672012-04-13 09:08:29 -0700282 # Get current stats for selected egress queue
Howard Pershf97840f2012-04-10 16:30:42 -0700283
Rich Lane28fa9272013-03-08 16:00:25 -0800284 request = ofp.message.queue_stats_request()
Howard Persh670b5672012-04-13 09:08:29 -0700285 request.port_no = egress_port
286 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700287 (qs_before, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700288 self.assertNotEqual(qs_before, None, "Queue stats request failed")
289
Rich Lane9a003812012-10-04 17:17:59 -0700290 logging.info("Sending packet to dp port " +
Howard Persh670b5672012-04-13 09:08:29 -0700291 str(ingress_port))
292 self.dataplane.send(ingress_port, str(pkt))
293
294 exp_pkt_arg = None
295 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700296 if config["relax"]:
Howard Persh670b5672012-04-13 09:08:29 -0700297 exp_pkt_arg = pkt
298 exp_port = egress_port
299
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700300 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Howard Persh670b5672012-04-13 09:08:29 -0700301 exp_pkt=exp_pkt_arg)
302 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700303 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Howard Persh670b5672012-04-13 09:08:29 -0700304 str(rcv_port))
305 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
306 self.assertEqual(str(pkt), str(rcv_pkt),
307 'Response packet does not match send packet')
308
Ed Swierkb8a86512012-04-18 18:45:58 -0700309 # FIXME: instead of sleeping, keep requesting queue stats until
310 # the expected queue counter increases or some large timeout is
311 # reached
312 time.sleep(2)
313
Howard Persh670b5672012-04-13 09:08:29 -0700314 # Get current stats for selected egress queue again
315
Rich Lane28fa9272013-03-08 16:00:25 -0800316 request = ofp.message.queue_stats_request()
Howard Persh670b5672012-04-13 09:08:29 -0700317 request.port_no = egress_port
318 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700319 (qs_after, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700320 self.assertNotEqual(qs_after, None, "Queue stats request failed")
321
322 # Make sure that tx packet counter for selected egress queue was
323 # incremented
324
Rich Lane5fd6faf2013-03-11 13:30:20 -0700325 self.assertEqual(qs_after.entries[0].tx_packets, \
326 qs_before.entries[0].tx_packets + 1, \
Howard Persh670b5672012-04-13 09:08:29 -0700327 "Verification of egress queue tx packet count failed"
328 )
329
330
Rich Laneb90a1c42012-10-05 09:16:05 -0700331class DirectPacketControllerQueue(base_tests.SimpleDataPlane):
Ken Chiang899ff8e2012-05-23 18:26:12 -0700332 """
333 Send a packet from each of the openflow ports
334 to each of the queues configured on the controller port.
335 If no queues have been configured, no packets are sent.
Howard Pershf97840f2012-04-10 16:30:42 -0700336
Ken Chiang899ff8e2012-05-23 18:26:12 -0700337 Generate a packet
338 Generate and install a matching flow
339 Add action to direct the packet to one of the controller port queues
340 Send the packet to ingress dataplane port
341 Verify the packet is received on the controller port queue
342 """
343 def runTest(self):
344 self.handleFlow()
345
346 def portQueuesGet(self, queue_stats, port_num):
347 result = []
Rich Lane5fd6faf2013-03-11 13:30:20 -0700348 for qs in queue_stats.entries:
Ken Chiang899ff8e2012-05-23 18:26:12 -0700349 if qs.port_no != port_num:
350 continue
351 result.append(qs.queue_id)
352 return result
353
354 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700355 of_ports = config["port_map"].keys()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700356 of_ports.sort()
357 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
358
359 if (pkttype == 'ICMP'):
360 pkt = simple_icmp_packet()
361 else:
362 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700363 match = packet_to_flow_match(self, pkt)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700364 match.wildcards &= ~ofp.OFPFW_IN_PORT
365 self.assertTrue(match is not None,
366 "Could not generate flow match from pkt")
367
368 # Get queue stats from switch
369
Rich Lane28fa9272013-03-08 16:00:25 -0800370 request = ofp.message.queue_stats_request()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700371 request.port_no = ofp.OFPP_CONTROLLER
372 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700373 (queue_stats, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700374 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
Rich Laneb73808c2013-03-11 15:22:23 -0700375 if queue_stats.type == ofp.OFPT_ERROR:
Rich Laneb8c845a2012-12-31 17:23:51 -0800376 skip_message_emit(self, "Enqueue packet to controller")
377 return
Ken Chiang899ff8e2012-05-23 18:26:12 -0700378
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800379 act = ofp.action.enqueue()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700380
381 for idx in range(len(of_ports)):
382 ingress_port = of_ports[idx]
383 egress_port = ofp.OFPP_CONTROLLER
384
Rich Lane9a003812012-10-04 17:17:59 -0700385 logging.info("Ingress port " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700386 + ", controller port queues "
387 + str(self.portQueuesGet(queue_stats, egress_port)))
388
389 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700390 logging.info("Ingress " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700391 + " to egress " + str(egress_port)
392 + " queue " + str(egress_queue_id)
393 )
394
Rich Lane32bf9482013-01-03 17:26:30 -0800395 delete_all_flows(self.controller)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700396
397 match.in_port = ingress_port
398
Rich Laneba3f0e22013-03-11 16:43:57 -0700399 request = ofp.message.flow_add()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700400 request.match = match
401
402 request.buffer_id = 0xffffffff
403 act.port = egress_port
404 act.queue_id = egress_queue_id
Rich Lanec495d9e2013-03-08 17:43:36 -0800405 request.actions.append(act)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700406
Rich Lane9a003812012-10-04 17:17:59 -0700407 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800408 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800409 do_barrier(self.controller)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700410
411 # Get current stats for selected egress queue
412
Rich Lane28fa9272013-03-08 16:00:25 -0800413 request = ofp.message.queue_stats_request()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700414 request.port_no = egress_port
415 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700416 (qs_before, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700417 self.assertNotEqual(qs_before, None, "Queue stats request failed")
418
Rich Lane9a003812012-10-04 17:17:59 -0700419 logging.info("Sending packet to dp port " +
Ken Chiang899ff8e2012-05-23 18:26:12 -0700420 str(ingress_port))
421 self.dataplane.send(ingress_port, str(pkt))
422
423 exp_pkt_arg = None
424 exp_port = None
425
Rich Lanee5779d32012-10-05 17:56:04 -0700426 count = 0
Ken Chiang899ff8e2012-05-23 18:26:12 -0700427 while True:
Dan Talaycoc689a792012-09-28 14:22:53 -0700428 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700429 if not response: # Timeout
430 break
431 if dataplane.match_exp_pkt(pkt, response.data): # Got match
432 break
Rich Lane477f4812012-10-04 22:49:00 -0700433 if not config["relax"]: # Only one attempt to match
Ken Chiang899ff8e2012-05-23 18:26:12 -0700434 break
435 count += 1
436 if count > 10: # Too many tries
437 break
438
439 self.assertTrue(response is not None,
440 'Packet in message not received by controller')
441 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700442 logging.debug("Sent %s" % format_packet(pkt))
443 logging.debug("Resp %s" % format_packet(response.data))
Ken Chiang899ff8e2012-05-23 18:26:12 -0700444 self.assertTrue(False,
445 'Response packet does not match send packet' +
446 ' for controller port')
447
448 # FIXME: instead of sleeping, keep requesting queue stats until
449 # the expected queue counter increases or some large timeout is
450 # reached
451 time.sleep(2)
452
453 # Get current stats for selected egress queue again
454
Rich Lane28fa9272013-03-08 16:00:25 -0800455 request = ofp.message.queue_stats_request()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700456 request.port_no = egress_port
457 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700458 (qs_after, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700459 self.assertNotEqual(qs_after, None, "Queue stats request failed")
460
461 # Make sure that tx packet counter for selected egress queue was
462 # incremented
463
Rich Lane5fd6faf2013-03-11 13:30:20 -0700464 self.assertEqual(qs_after.entries[0].tx_packets, \
465 qs_before.entries[0].tx_packets + 1, \
Ken Chiang899ff8e2012-05-23 18:26:12 -0700466 "Verification of egress queue tx packet count failed"
467 )
468
Howard Pershf97840f2012-04-10 16:30:42 -0700469
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700470class DirectPacketICMP(DirectPacket):
471 """
472 Send ICMP packet to single egress port
473
474 Generate a ICMP packet
475 Generate and install a matching flow
476 Add action to direct the packet to an egress port
477 Send the packet to ingress dataplane port
478 Verify the packet is received at the egress port only
479 Difference from DirectPacket test is that sent packet is ICMP
480 """
481 def runTest(self):
482 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700483
Rich Laneb90a1c42012-10-05 09:16:05 -0700484class DirectTwoPorts(base_tests.SimpleDataPlane):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700485 """
486 Send packet to two egress ports
487
488 Generate a packet
489 Generate and install a matching flow
490 Add action to direct the packet to two egress ports
491 Send the packet to ingress dataplane port
492 Verify the packet is received at the two egress ports
493 """
494 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700495 of_ports = config["port_map"].keys()
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700496 of_ports.sort()
497 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
498
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700499 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700500 match = packet_to_flow_match(self, pkt)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700501 match.wildcards &= ~ofp.OFPFW_IN_PORT
502 self.assertTrue(match is not None,
503 "Could not generate flow match from pkt")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700504
505 for idx in range(len(of_ports)):
Rich Lane32bf9482013-01-03 17:26:30 -0800506 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700507
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700508 ingress_port = of_ports[idx]
509 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
510 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700511 logging.info("Ingress " + str(ingress_port) +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700512 " to egress " + str(egress_port1) + " and " +
513 str(egress_port2))
514
515 match.in_port = ingress_port
516
Rich Laneba3f0e22013-03-11 16:43:57 -0700517 request = ofp.message.flow_add()
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700518 request.match = match
519 request.buffer_id = 0xffffffff
Rich Lane62e96852013-03-11 12:04:45 -0700520 request.actions.append(ofp.action.output(port=egress_port1))
521 request.actions.append(ofp.action.output(port=egress_port2))
Rich Lane9a003812012-10-04 17:17:59 -0700522 # logging.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700523
Rich Lane9a003812012-10-04 17:17:59 -0700524 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800525 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800526 do_barrier(self.controller)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700527
Rich Lane9a003812012-10-04 17:17:59 -0700528 logging.info("Sending packet to dp port " +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700529 str(ingress_port))
530 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700531 yes_ports = set([egress_port1, egress_port2])
532 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700533
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700534 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Rich Lane2014f9b2012-10-05 15:29:40 -0700535 self)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700536
Rich Laneb90a1c42012-10-05 09:16:05 -0700537class DirectMCNonIngress(base_tests.SimpleDataPlane):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700538 """
539 Multicast to all non-ingress ports
540
541 Generate a packet
542 Generate and install a matching flow
543 Add action to direct the packet to all non-ingress ports
544 Send the packet to ingress dataplane port
545 Verify the packet is received at all non-ingress ports
546
547 Does not use the flood action
548 """
549 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700550 of_ports = config["port_map"].keys()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700551 of_ports.sort()
552 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
553
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700554 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700555 match = packet_to_flow_match(self, pkt)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700556 match.wildcards &= ~ofp.OFPFW_IN_PORT
557 self.assertTrue(match is not None,
558 "Could not generate flow match from pkt")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700559
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700560 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800561 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700562
Rich Lane9a003812012-10-04 17:17:59 -0700563 logging.info("Ingress " + str(ingress_port) +
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700564 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700565 match.in_port = ingress_port
566
Rich Laneba3f0e22013-03-11 16:43:57 -0700567 request = ofp.message.flow_add()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700568 request.match = match
569 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700570 for egress_port in of_ports:
571 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700572 continue
Rich Lane62e96852013-03-11 12:04:45 -0700573 request.actions.append(ofp.action.output(port=egress_port))
Rich Lane9a003812012-10-04 17:17:59 -0700574 logging.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700575
Rich Lane9a003812012-10-04 17:17:59 -0700576 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800577 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800578 do_barrier(self.controller)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700579
Rich Lane9a003812012-10-04 17:17:59 -0700580 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700581 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700582 yes_ports = set(of_ports).difference([ingress_port])
583 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700584 self)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700585
Dan Talayco32fa6542010-05-11 15:54:08 -0700586
Rich Laneb90a1c42012-10-05 09:16:05 -0700587class DirectMC(base_tests.SimpleDataPlane):
Dan Talayco32fa6542010-05-11 15:54:08 -0700588 """
589 Multicast to all ports including ingress
590
591 Generate a packet
592 Generate and install a matching flow
593 Add action to direct the packet to all non-ingress ports
594 Send the packet to ingress dataplane port
595 Verify the packet is received at all ports
596
597 Does not use the flood action
598 """
599 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700600 of_ports = config["port_map"].keys()
Dan Talayco32fa6542010-05-11 15:54:08 -0700601 of_ports.sort()
602 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
603
Dan Talayco32fa6542010-05-11 15:54:08 -0700604 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700605 match = packet_to_flow_match(self, pkt)
Dan Talayco32fa6542010-05-11 15:54:08 -0700606 match.wildcards &= ~ofp.OFPFW_IN_PORT
607 self.assertTrue(match is not None,
608 "Could not generate flow match from pkt")
Dan Talayco32fa6542010-05-11 15:54:08 -0700609
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700610 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800611 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700612
Rich Lane9a003812012-10-04 17:17:59 -0700613 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700614 match.in_port = ingress_port
615
Rich Laneba3f0e22013-03-11 16:43:57 -0700616 request = ofp.message.flow_add()
Dan Talayco32fa6542010-05-11 15:54:08 -0700617 request.match = match
618 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700619 for egress_port in of_ports:
Rich Lane62e96852013-03-11 12:04:45 -0700620 act = ofp.action.output()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700621 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700622 act.port = ofp.OFPP_IN_PORT
623 else:
624 act.port = egress_port
Rich Lanec495d9e2013-03-08 17:43:36 -0800625 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -0700626 # logging.info(request.show())
Dan Talayco2e77a842010-05-12 15:39:46 -0700627
Rich Lane9a003812012-10-04 17:17:59 -0700628 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800629 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800630 do_barrier(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700631
Rich Lane9a003812012-10-04 17:17:59 -0700632 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700633 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700634 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco2e77a842010-05-12 15:39:46 -0700635
Rich Laneb90a1c42012-10-05 09:16:05 -0700636class Flood(base_tests.SimpleDataPlane):
Dan Talayco2e77a842010-05-12 15:39:46 -0700637 """
638 Flood to all ports except ingress
639
Dan Talaycofcc09912013-02-08 23:46:08 -0800640 Make sure noflood bit is off on all ports
Dan Talayco2e77a842010-05-12 15:39:46 -0700641 Generate a packet
642 Generate and install a matching flow
643 Add action to flood the packet
644 Send the packet to ingress dataplane port
645 Verify the packet is received at all other ports
646 """
647 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700648 of_ports = config["port_map"].keys()
Dan Talayco2e77a842010-05-12 15:39:46 -0700649 of_ports.sort()
650 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
651
652 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700653 match = packet_to_flow_match(self, pkt)
Dan Talayco2e77a842010-05-12 15:39:46 -0700654 match.wildcards &= ~ofp.OFPFW_IN_PORT
655 self.assertTrue(match is not None,
656 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800657 act = ofp.action.output()
Dan Talayco2e77a842010-05-12 15:39:46 -0700658
Dan Talaycofcc09912013-02-08 23:46:08 -0800659 for of_port in of_ports:
660 # Clear relevant bits that might block ports
661 rv = port_config_set(self.controller, of_port, 0,
662 ofp.OFPPC_NO_FLOOD | ofp.OFPPC_NO_FWD |
663 ofp.OFPPC_PORT_DOWN)
664 self.assertTrue(rv == 0, "Did not set port config")
665 logging.debug("Enabled and cleared no-flood for port " + str(of_port))
666
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700667 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800668 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700669
Rich Lane9a003812012-10-04 17:17:59 -0700670 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700671 match.in_port = ingress_port
672
Rich Laneba3f0e22013-03-11 16:43:57 -0700673 request = ofp.message.flow_add()
Dan Talayco2e77a842010-05-12 15:39:46 -0700674 request.match = match
675 request.buffer_id = 0xffffffff
676 act.port = ofp.OFPP_FLOOD
Rich Lanec495d9e2013-03-08 17:43:36 -0800677 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -0700678 logging.info(request.show())
Dan Talayco32fa6542010-05-11 15:54:08 -0700679
Rich Lane9a003812012-10-04 17:17:59 -0700680 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800681 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800682 do_barrier(self.controller)
Dan Talayco32fa6542010-05-11 15:54:08 -0700683
Rich Lane9a003812012-10-04 17:17:59 -0700684 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco32fa6542010-05-11 15:54:08 -0700685 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700686 yes_ports = set(of_ports).difference([ingress_port])
687 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700688 self)
Dan Talayco3be5b062010-05-12 15:46:21 -0700689
Rich Laneb90a1c42012-10-05 09:16:05 -0700690class FloodPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco3be5b062010-05-12 15:46:21 -0700691 """
692 Flood to all ports plus send to ingress port
693
694 Generate a packet
695 Generate and install a matching flow
696 Add action to flood the packet
697 Add action to send to ingress port
698 Send the packet to ingress dataplane port
699 Verify the packet is received at all other ports
700 """
701 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700702 of_ports = config["port_map"].keys()
Dan Talayco3be5b062010-05-12 15:46:21 -0700703 of_ports.sort()
704 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
705
706 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700707 match = packet_to_flow_match(self, pkt)
Dan Talayco3be5b062010-05-12 15:46:21 -0700708 match.wildcards &= ~ofp.OFPFW_IN_PORT
709 self.assertTrue(match is not None,
710 "Could not generate flow match from pkt")
Dan Talayco3be5b062010-05-12 15:46:21 -0700711
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700712 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800713 delete_all_flows(self.controller)
Dan Talayco3be5b062010-05-12 15:46:21 -0700714
Rich Lane9a003812012-10-04 17:17:59 -0700715 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700716 match.in_port = ingress_port
717
Rich Laneba3f0e22013-03-11 16:43:57 -0700718 request = ofp.message.flow_add()
Dan Talayco3be5b062010-05-12 15:46:21 -0700719 request.match = match
720 request.buffer_id = 0xffffffff
Rich Lane62e96852013-03-11 12:04:45 -0700721 request.actions.append(ofp.action.output(port=ofp.OFPP_FLOOD))
722 request.actions.append(ofp.action.output(port=ofp.OFPP_IN_PORT))
Rich Lane9a003812012-10-04 17:17:59 -0700723 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700724
Rich Lane9a003812012-10-04 17:17:59 -0700725 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800726 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800727 do_barrier(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700728
Rich Lane9a003812012-10-04 17:17:59 -0700729 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700730 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700731 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco4aa13122010-05-12 15:54:44 -0700732
Rich Laneb90a1c42012-10-05 09:16:05 -0700733class All(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700734 """
735 Send to OFPP_ALL port
736
737 Generate a packet
738 Generate and install a matching flow
739 Add action to forward to OFPP_ALL
740 Send the packet to ingress dataplane port
741 Verify the packet is received at all other ports
742 """
743 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700744 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700745 of_ports.sort()
746 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
747
748 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700749 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700750 match.wildcards &= ~ofp.OFPFW_IN_PORT
751 self.assertTrue(match is not None,
752 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800753 act = ofp.action.output()
Dan Talayco4aa13122010-05-12 15:54:44 -0700754
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700755 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800756 delete_all_flows(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700757
Rich Lane9a003812012-10-04 17:17:59 -0700758 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700759 match.in_port = ingress_port
760
Rich Laneba3f0e22013-03-11 16:43:57 -0700761 request = ofp.message.flow_add()
Dan Talayco4aa13122010-05-12 15:54:44 -0700762 request.match = match
763 request.buffer_id = 0xffffffff
764 act.port = ofp.OFPP_ALL
Rich Lanec495d9e2013-03-08 17:43:36 -0800765 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -0700766 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700767
Rich Lane9a003812012-10-04 17:17:59 -0700768 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800769 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800770 do_barrier(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700771
Rich Lane9a003812012-10-04 17:17:59 -0700772 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700773 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700774 yes_ports = set(of_ports).difference([ingress_port])
775 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700776 self)
Dan Talayco4aa13122010-05-12 15:54:44 -0700777
Rich Laneb90a1c42012-10-05 09:16:05 -0700778class AllPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700779 """
780 Send to OFPP_ALL port and ingress port
781
782 Generate a packet
783 Generate and install a matching flow
784 Add action to forward to OFPP_ALL
785 Add action to forward to ingress port
786 Send the packet to ingress dataplane port
787 Verify the packet is received at all other ports
788 """
789 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700790 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700791 of_ports.sort()
792 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
793
794 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700795 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700796 match.wildcards &= ~ofp.OFPFW_IN_PORT
797 self.assertTrue(match is not None,
798 "Could not generate flow match from pkt")
Dan Talayco4aa13122010-05-12 15:54:44 -0700799
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700800 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800801 delete_all_flows(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700802
Rich Lane9a003812012-10-04 17:17:59 -0700803 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700804 match.in_port = ingress_port
805
Rich Laneba3f0e22013-03-11 16:43:57 -0700806 request = ofp.message.flow_add()
Dan Talayco4aa13122010-05-12 15:54:44 -0700807 request.match = match
808 request.buffer_id = 0xffffffff
Rich Lane62e96852013-03-11 12:04:45 -0700809 request.actions.append(ofp.action.output(port=ofp.OFPP_ALL))
810 request.actions.append(ofp.action.output(port=ofp.OFPP_IN_PORT))
Rich Lane9a003812012-10-04 17:17:59 -0700811 logging.info(request.show())
Dan Talayco3be5b062010-05-12 15:46:21 -0700812
Rich Lane9a003812012-10-04 17:17:59 -0700813 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800814 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800815 do_barrier(self.controller)
Dan Talayco3be5b062010-05-12 15:46:21 -0700816
Rich Lane9a003812012-10-04 17:17:59 -0700817 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco3be5b062010-05-12 15:46:21 -0700818 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700819 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700820
Rich Laneb90a1c42012-10-05 09:16:05 -0700821class FloodMinusPort(base_tests.SimpleDataPlane):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700822 """
823 Config port with No_Flood and test Flood action
824
825 Generate a packet
826 Generate a matching flow
827 Add action to forward to OFPP_ALL
828 Set port to no-flood
829 Send the packet to ingress dataplane port
830 Verify the packet is received at all other ports except
831 the ingress port and the no_flood port
832 """
833 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700834 of_ports = config["port_map"].keys()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700835 of_ports.sort()
836 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
837
838 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700839 match = packet_to_flow_match(self, pkt)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700840 match.wildcards &= ~ofp.OFPFW_IN_PORT
841 self.assertTrue(match is not None,
842 "Could not generate flow match from pkt")
Rich Lane9d3cc6b2013-03-08 16:33:08 -0800843 act = ofp.action.output()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700844
Rich Lane4b9e38c2012-12-06 16:33:20 -0800845 # Clear OFPPC_NO_FLOOD on each port
846 for of_port in of_ports:
847 rv = port_config_set(self.controller, of_port,
848 0, ofp.OFPPC_NO_FLOOD)
849 self.assertEqual(rv, 0, "Failed to set port config")
850
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700851 for idx in range(len(of_ports)):
Rich Lane32bf9482013-01-03 17:26:30 -0800852 delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700853
854 ingress_port = of_ports[idx]
855 no_flood_idx = (idx + 1) % len(of_ports)
856 no_flood_port = of_ports[no_flood_idx]
857 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700858 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700859 self.assertEqual(rv, 0, "Failed to set port config")
860
861 match.in_port = ingress_port
862
Rich Laneba3f0e22013-03-11 16:43:57 -0700863 request = ofp.message.flow_add()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700864 request.match = match
865 request.buffer_id = 0xffffffff
866 act.port = ofp.OFPP_FLOOD
Rich Lanec495d9e2013-03-08 17:43:36 -0800867 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -0700868 logging.info(request.show())
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700869
Rich Lane9a003812012-10-04 17:17:59 -0700870 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800871 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800872 do_barrier(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700873
Rich Lane9a003812012-10-04 17:17:59 -0700874 logging.info("Sending packet to dp port " + str(ingress_port))
875 logging.info("No flood port is " + str(no_flood_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700876 self.dataplane.send(ingress_port, str(pkt))
877 no_ports = set([ingress_port, no_flood_port])
878 yes_ports = set(of_ports).difference(no_ports)
Rich Lane2014f9b2012-10-05 15:29:40 -0700879 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700880
881 # Turn no flood off again
882 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700883 0, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700884 self.assertEqual(rv, 0, "Failed to reset port config")
Rich Lane3a261d52013-01-03 17:45:08 -0800885 do_barrier(self.controller)
Rich Lane4ecc1f42012-12-06 16:35:24 -0800886
887 # Check that packets are now flooded to no_flood_port
888 logging.info("Sending packet to dp port " + str(ingress_port))
889 self.dataplane.send(ingress_port, str(pkt))
890 no_ports = set([ingress_port])
891 yes_ports = set(of_ports).difference(no_ports)
892 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700893
894 #@todo Should check no other packets received
895
Dan Talayco21381562010-07-17 00:34:47 -0700896
897
Dan Talayco551befa2010-07-15 17:05:32 -0700898################################################################
899
Rich Laneb90a1c42012-10-05 09:16:05 -0700900class BaseMatchCase(base_tests.SimpleDataPlane):
Dan Talayco551befa2010-07-15 17:05:32 -0700901 def setUp(self):
Rich Laneb90a1c42012-10-05 09:16:05 -0700902 base_tests.SimpleDataPlane.setUp(self)
Dan Talayco551befa2010-07-15 17:05:32 -0700903 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -0700904 logging.info("BaseMatchCase")
Dan Talayco551befa2010-07-15 17:05:32 -0700905
906class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700907 """
Dan Talayco551befa2010-07-15 17:05:32 -0700908 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700909
910 Generate a packet
911 Generate and install a matching flow without wildcard mask
912 Add action to forward to a port
913 Send the packet to the port
914 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700915 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700916
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700917 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700918 flow_match_test(self, config["port_map"])
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700919
Dan Talayco551befa2010-07-15 17:05:32 -0700920class ExactMatchTagged(BaseMatchCase):
921 """
922 Exact match for all port pairs with tagged pkts
923 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700924
Dan Talayco551befa2010-07-15 17:05:32 -0700925 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -0700926 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Laned0478ff2013-03-11 12:46:58 -0700927 flow_match_test(self, config["port_map"], vlan_vid=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700928
Rich Lane0a4f6372013-01-02 14:40:22 -0800929@disabled
Dan Talayco551befa2010-07-15 17:05:32 -0700930class ExactMatchTaggedMany(BaseMatchCase):
931 """
932 ExactMatchTagged with many VLANS
933 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700934
Dan Talayco551befa2010-07-15 17:05:32 -0700935 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700936 for vid in range(2,100,10):
Rich Laned0478ff2013-03-11 12:46:58 -0700937 flow_match_test(self, config["port_map"], vlan_vid=vid, max_test=5)
Dan Talayco551befa2010-07-15 17:05:32 -0700938 for vid in range(100,4000,389):
Rich Laned0478ff2013-03-11 12:46:58 -0700939 flow_match_test(self, config["port_map"], vlan_vid=vid, max_test=5)
940 flow_match_test(self, config["port_map"], vlan_vid=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700941
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700942class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700943 """
944 SingleWildcardMatchPriority
945 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700946
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700947 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700948 self.pkt = simple_tcp_packet()
949 self.flowMsgs = {}
950
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700951 def _ClearTable(self):
Rich Lane32bf9482013-01-03 17:26:30 -0800952 delete_all_flows(self.controller)
Rich Lane3a261d52013-01-03 17:45:08 -0800953 do_barrier(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700954
955 def runTest(self):
956
957 self._Init()
Rich Lane477f4812012-10-04 22:49:00 -0700958 of_ports = config["port_map"].keys()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700959 of_ports.sort()
960
961 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700962 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700963
964 # Run several combinations, each at lower priority settings.
965 # At the end of each call to runPrioFlows(), the table should
966 # be empty. If its not, we'll catch it as the priorities decreases
967 portA = of_ports[0]
968 portB = of_ports[1]
969 portC = of_ports[2]
970
971 # TODO -- these priority numbers should be validated somehow?
972 self.runPrioFlows(portA, portB, portC, 1000, 999)
973 self.runPrioFlows(portB, portC, portA, 998, 997)
974 self.runPrioFlows(portC, portA, portB, 996, 995)
975 self.runPrioFlows(portA, portC, portB, 994, 993)
976
977
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700978
979 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
980 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700981
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700982 if clearTable:
983 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700984
985 # Sanity check flow at lower priority from pA to pB
Rich Lane9a003812012-10-04 17:17:59 -0700986 logging.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700987 % (portA, portB, portC, prioHigher, prioLower))
988
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700989 # Sanity check flow at lower priority from pA to pC
990 self.installFlow(prioLower, portA, portC)
991 self.verifyFlow(portA, portC)
992 self.removeFlow(prioLower)
993
994 # Install and verify pA->pB @ prioLower
995 self.installFlow(prioLower, portA, portB)
996 self.verifyFlow(portA, portB)
997
998 # Install and verify pA->pC @ prioHigher, should override pA->pB
999 self.installFlow(prioHigher, portA, portC)
1000 self.verifyFlow(portA, portC)
1001 # remove pA->pC
1002 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001003 # Old flow pA -> pB @ prioLower should still be active
1004 self.verifyFlow(portA, portB)
1005 self.removeFlow(prioLower)
1006
1007 # Table should be empty at this point, leave it alone as
1008 # an assumption for future test runs
1009
1010
1011
Ed Swierk99a74de2012-08-22 06:40:54 -07001012 def installFlow(self, prio, inp, egp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001013 wildcards=ofp.OFPFW_DL_SRC):
Ed Swierk99a74de2012-08-22 06:40:54 -07001014 wildcards |= required_wildcards(self)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001015 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001016 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001017 egr_ports=egp)
1018 request.priority = prio
Rich Lane9a003812012-10-04 17:17:59 -07001019 logging.debug("Install flow with priority " + str(prio))
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001020 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001021 self.flowMsgs[prio] = request
1022
1023 def removeFlow(self, prio):
1024 if self.flowMsgs.has_key(prio):
Rich Laneba3f0e22013-03-11 16:43:57 -07001025 old_msg = self.flowMsgs[prio]
1026 msg = ofp.message.flow_delete_strict(out_port=ofp.OFPP_NONE,
1027 match=old_msg.match,
1028 priority=old_msg.priority)
Rich Lane9a003812012-10-04 17:17:59 -07001029 logging.debug("Remove flow with priority " + str(prio))
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001030 self.controller.message_send(msg)
Rich Lane3a261d52013-01-03 17:45:08 -08001031 do_barrier(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001032 else:
1033 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001034
1035
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001036 def verifyFlow(self, inp, egp, pkt=None):
1037 if pkt == None:
1038 pkt = self.pkt
1039
Rich Lane9a003812012-10-04 17:17:59 -07001040 logging.info("Pkt match test: " + str(inp) + " to " + str(egp))
1041 logging.debug("Send packet: " + str(inp) + " to " + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001042 self.dataplane.send(inp, str(pkt))
1043 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001044
1045
1046
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001047class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
1048
1049 def runTest(self):
1050
1051 self._Init()
1052
Rich Lane477f4812012-10-04 22:49:00 -07001053 of_ports = config["port_map"].keys()
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001054 of_ports.sort()
1055
1056 # Install an entry from 0 -> 1 @ prio 1000
1057 self._ClearTable()
1058 self.installFlow(1000, of_ports[0], of_ports[1])
1059 self.verifyFlow(of_ports[0], of_ports[1])
1060 self.installFlow(1000, of_ports[1], of_ports[0])
1061 self.verifyFlow(of_ports[1], of_ports[0])
1062 self.installFlow(1001, of_ports[0], of_ports[1])
1063 self.verifyFlow(of_ports[0], of_ports[1])
1064 self.installFlow(1001, of_ports[1], of_ports[0])
1065 self.verifyFlow(of_ports[1], of_ports[0])
1066 self.removeFlow(1001)
1067 self.verifyFlow(of_ports[0], of_ports[1])
1068 self.removeFlow(1000)
1069
1070
1071
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001072class WildcardPriority(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001073 """
1074 1. Add wildcard flow, verify packet received.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001075 2. Add wildcard flow with higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001076 on port specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001077 3. Add wildcard flow with lower priority, verify packet received
Rich Laneb8392082012-11-21 15:52:54 -08001078 on port specified by the highest priority flow.
Ken Chiang38d7a152012-05-24 15:33:50 -07001079 """
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001080
1081 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001082
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001083 self._Init()
1084
Rich Lane477f4812012-10-04 22:49:00 -07001085 of_ports = config["port_map"].keys()
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001086 of_ports.sort()
1087
1088 self._ClearTable()
Ken Chiang38d7a152012-05-24 15:33:50 -07001089
1090 # Install a flow with wildcards
1091 self.installFlow(999, of_ports[0], of_ports[1],
1092 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001093 self.verifyFlow(of_ports[0], of_ports[1])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001094 # Install a flow with wildcards with higher priority
1095 self.installFlow(1000, of_ports[0], of_ports[2],
1096 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001097 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001098 # Install a flow with wildcards with lower priority
Rich Laneb8392082012-11-21 15:52:54 -08001099 self.installFlow(999, of_ports[0], of_ports[1],
1100 wildcards=ofp.OFPFW_DL_SRC)
Rich Lane0a78fbd2012-12-31 16:25:04 -08001101 self.verifyFlow(of_ports[0], of_ports[2])
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001102
1103
Rich Lane97e99652013-01-02 17:23:20 -08001104@group("smoke")
Ken Chiang3978f242012-06-13 14:14:09 -07001105class WildcardPriorityWithDelete(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001106 """
Rich Lane0a78fbd2012-12-31 16:25:04 -08001107 1. Add wildcard match flow, verify packet received.
Ken Chiang38d7a152012-05-24 15:33:50 -07001108 2. Add wildcard flow with higher priority, verify packet received on port
1109 specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001110 3. Add wildcard flow with even higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001111 on port specified by this flow.
1112 4. Delete lowest priority flow, verify packet received on port specified
1113 by highest priority flow.
1114 5. Delete highest priority flow, verify packet received on port specified
1115 by remaining flow.
1116 """
1117
1118 def runTest(self):
1119
1120 self._Init()
1121
Rich Lane477f4812012-10-04 22:49:00 -07001122 of_ports = config["port_map"].keys()
Ken Chiang38d7a152012-05-24 15:33:50 -07001123 of_ports.sort()
1124
1125 self._ClearTable()
1126
Rich Lane0a78fbd2012-12-31 16:25:04 -08001127 # Install a flow with wildcards
1128 self.installFlow(250, of_ports[0], of_ports[1],
1129 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001130 self.verifyFlow(of_ports[0], of_ports[1])
1131 # Install a flow with wildcards of higher priority
1132 self.installFlow(1250, of_ports[0], of_ports[2],
1133 wildcards=ofp.OFPFW_DL_DST)
1134 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001135 # Install a flow with wildcards with even higher priority
1136 self.installFlow(2001, of_ports[0], of_ports[3],
1137 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001138 self.verifyFlow(of_ports[0], of_ports[3])
1139 # Delete lowest priority flow
1140 self.removeFlow(250)
1141 self.verifyFlow(of_ports[0], of_ports[3])
1142 # Delete highest priority flow
1143 self.removeFlow(2001)
1144 self.verifyFlow(of_ports[0], of_ports[2])
1145
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001146
Dan Talayco551befa2010-07-15 17:05:32 -07001147class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001148 """
1149 Exercise wildcard matching for all ports
1150
1151 Generate a packet
1152 Generate and install a matching flow with wildcard mask
1153 Add action to forward to a port
1154 Send the packet to the port
1155 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001156 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001157 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001158 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001159 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001160 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001161 wc |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001162 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001163 # Set nonzero VLAN id to avoid sending priority-tagged packet
Rich Laned0478ff2013-03-11 12:46:58 -07001164 vlan_vid = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001165 else:
Rich Laned0478ff2013-03-11 12:46:58 -07001166 vlan_vid = -1
Rich Lane477f4812012-10-04 22:49:00 -07001167 flow_match_test(self, config["port_map"], wildcards=wc,
Rich Laned0478ff2013-03-11 12:46:58 -07001168 vlan_vid=vlan_vid, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001169
Dan Talayco551befa2010-07-15 17:05:32 -07001170class SingleWildcardMatchTagged(BaseMatchCase):
1171 """
1172 SingleWildcardMatch with tagged packets
1173 """
1174 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001175 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001176 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001177 wc |= required_wildcards(self)
Rich Laned0478ff2013-03-11 12:46:58 -07001178 flow_match_test(self, config["port_map"], wildcards=wc, vlan_vid=vid,
Dan Talayco551befa2010-07-15 17:05:32 -07001179 max_test=10)
1180
1181class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001182 """
Dan Talayco80b54ed2010-07-13 09:48:35 -07001183 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001184
1185 Generate a packet
1186 Generate and install a matching flow with wildcard all except one filed
1187 Add action to forward to a port
1188 Send the packet to the port
1189 Verify the packet is received at all other ports (one port at a time)
1190 Verify flow_expiration message is correct when command option is set
1191 """
1192 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001193 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001194 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001195 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001196 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001197 # Set nonzero VLAN id to avoid sending priority-tagged packet
Rich Laned0478ff2013-03-11 12:46:58 -07001198 vlan_vid = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001199 else:
Rich Laned0478ff2013-03-11 12:46:58 -07001200 vlan_vid = -1
Rich Lane477f4812012-10-04 22:49:00 -07001201 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Rich Laned0478ff2013-03-11 12:46:58 -07001202 vlan_vid=vlan_vid)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001203
Dan Talayco551befa2010-07-15 17:05:32 -07001204class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1205 """
1206 Match one field with tagged packets
1207 """
1208 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001209 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001210 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001211 all_exp_one_wildcard |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001212 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Rich Laned0478ff2013-03-11 12:46:58 -07001213 vlan_vid=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001214
1215class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001216 """
1217 Create Wildcard-all flow and exercise for all ports
1218
1219 Generate a packet
1220 Generate and install a matching flow with wildcard-all
1221 Add action to forward to a port
1222 Send the packet to the port
1223 Verify the packet is received at all other ports (one port at a time)
1224 Verify flow_expiration message is correct when command option is set
1225 """
1226 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001227 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001228
Dan Talayco551befa2010-07-15 17:05:32 -07001229class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001230 """
Dan Talayco551befa2010-07-15 17:05:32 -07001231 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001232 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001233 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001234 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Lane477f4812012-10-04 22:49:00 -07001235 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL,
Rich Laned0478ff2013-03-11 12:46:58 -07001236 vlan_vid=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001237
Rich Lane97e99652013-01-02 17:23:20 -08001238@group('smoke')
Dan Talayco551befa2010-07-15 17:05:32 -07001239class AddVLANTag(BaseMatchCase):
1240 """
1241 Add a VLAN tag to an untagged packet
1242 """
1243 def runTest(self):
1244 new_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001245 sup_acts = self.supported_actions
Dan Talayco551befa2010-07-15 17:05:32 -07001246 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001247 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001248 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001249
Dan Talayco551befa2010-07-15 17:05:32 -07001250 len = 100
1251 len_w_vid = 104
1252 pkt = simple_tcp_packet(pktlen=len)
1253 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
Rich Laned0478ff2013-03-11 12:46:58 -07001254 vlan_vid=new_vid)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001255 vid_act = ofp.action.set_vlan_vid()
Dan Talayco551befa2010-07-15 17:05:32 -07001256 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001257
Rich Lane477f4812012-10-04 22:49:00 -07001258 flow_match_test(self, config["port_map"], pkt=pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001259 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001260
Rich Lane0a4f6372013-01-02 14:40:22 -08001261@disabled
Rich Laneb90a1c42012-10-05 09:16:05 -07001262class PacketOnly(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001263 """
1264 Just send a packet thru the switch
1265 """
Rich Laned1d9c282012-10-04 22:07:10 -07001266
Dan Talayco551befa2010-07-15 17:05:32 -07001267 def runTest(self):
1268 pkt = simple_tcp_packet()
Rich Lane477f4812012-10-04 22:49:00 -07001269 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001270 of_ports.sort()
1271 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001272 logging.info("Sending packet to " + str(ing_port))
1273 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001274 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001275
Rich Lane0a4f6372013-01-02 14:40:22 -08001276@disabled
Rich Laneb90a1c42012-10-05 09:16:05 -07001277class PacketOnlyTagged(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001278 """
1279 Just send a packet thru the switch
1280 """
Rich Laned1d9c282012-10-04 22:07:10 -07001281
Dan Talayco551befa2010-07-15 17:05:32 -07001282 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001283 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Laned0478ff2013-03-11 12:46:58 -07001284 pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=vid)
Rich Lane477f4812012-10-04 22:49:00 -07001285 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001286 of_ports.sort()
1287 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001288 logging.info("Sending packet to " + str(ing_port))
1289 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001290 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001291
Dan Talayco551befa2010-07-15 17:05:32 -07001292class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001293 """
1294 Modify the VLAN ID in the VLAN tag of a tagged packet
1295 """
Dan Talaycoaf669322012-09-12 22:51:22 -07001296 def setUp(self):
1297 BaseMatchCase.setUp(self)
1298 self.ing_port=False
1299
Dan Talayco551befa2010-07-15 17:05:32 -07001300 def runTest(self):
1301 old_vid = 2
1302 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001303 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001304 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001305 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001306 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001307
Rich Laned0478ff2013-03-11 12:46:58 -07001308 pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=old_vid)
1309 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=new_vid)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001310 vid_act = ofp.action.set_vlan_vid()
Dan Talayco551befa2010-07-15 17:05:32 -07001311 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001312
Rich Lane477f4812012-10-04 22:49:00 -07001313 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoaf669322012-09-12 22:51:22 -07001314 action_list=[vid_act], ing_port=self.ing_port)
1315
1316class ModifyVIDToIngress(ModifyVID):
1317 """
1318 Modify the VLAN ID in the VLAN tag of a tagged packet and send to
1319 ingress port
1320 """
1321 def setUp(self):
1322 BaseMatchCase.setUp(self)
1323 self.ing_port=True
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001324
Ken Chiange9a211d2012-04-20 14:52:11 -07001325class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1326 """
Rich Lane28fa9272013-03-08 16:00:25 -08001327 With vlan ID and priority wildcarded, perform SET_VLAN_VID ofp.action.
Ken Chiange9a211d2012-04-20 14:52:11 -07001328 The same flow should match on both untagged and tagged packets.
1329 """
1330 def runTest(self):
1331 old_vid = 2
1332 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001333 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001334 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1335 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1336 return
1337
Rich Lane477f4812012-10-04 22:49:00 -07001338 of_ports = config["port_map"].keys()
Ken Chiange9a211d2012-04-20 14:52:11 -07001339 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1340 ing_port = of_ports[0]
1341 egr_ports = of_ports[1]
1342
Rich Lane32bf9482013-01-03 17:26:30 -08001343 delete_all_flows(self.controller)
Ken Chiange9a211d2012-04-20 14:52:11 -07001344
1345 len_untagged = 100
1346 len_w_vid = 104
1347 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1348 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
Rich Laned0478ff2013-03-11 12:46:58 -07001349 dl_vlan_enable=True, vlan_vid=old_vid)
Ken Chiange9a211d2012-04-20 14:52:11 -07001350 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
Rich Laned0478ff2013-03-11 12:46:58 -07001351 vlan_vid=new_vid)
Ed Swierk99a74de2012-08-22 06:40:54 -07001352 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1353 ofp.OFPFW_DL_VLAN_PCP)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001354 vid_act = ofp.action.set_vlan_vid()
Ken Chiange9a211d2012-04-20 14:52:11 -07001355 vid_act.vlan_vid = new_vid
1356 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
1357 wildcards=wildcards, egr_ports=egr_ports,
1358 action_list=[vid_act])
1359 flow_msg_install(self, request)
1360
Rich Lane9a003812012-10-04 17:17:59 -07001361 logging.debug("Send untagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001362 str(egr_ports))
1363 self.dataplane.send(ing_port, str(untagged_pkt))
1364 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1365
Rich Lane9a003812012-10-04 17:17:59 -07001366 logging.debug("Send tagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001367 str(egr_ports))
1368 self.dataplane.send(ing_port, str(tagged_pkt))
1369 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1370
Howard Pershc1199d52012-04-11 14:21:32 -07001371class ModifyVlanPcp(BaseMatchCase):
1372 """
1373 Modify the priority field of the VLAN tag of a tagged packet
1374 """
1375 def runTest(self):
1376 vid = 123
1377 old_vlan_pcp = 2
1378 new_vlan_pcp = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001379 sup_acts = self.supported_actions
Ed Swierk8c3af7f2012-04-24 14:19:17 -07001380 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_PCP):
1381 skip_message_emit(self, "Modify VLAN priority test")
Howard Pershc1199d52012-04-11 14:21:32 -07001382 return
1383
Rich Laned0478ff2013-03-11 12:46:58 -07001384 pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=vid, vlan_pcp=old_vlan_pcp)
1385 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=vid, vlan_pcp=new_vlan_pcp)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001386 vid_act = ofp.action.set_vlan_pcp()
Howard Pershc1199d52012-04-11 14:21:32 -07001387 vid_act.vlan_pcp = new_vlan_pcp
1388
Rich Lane477f4812012-10-04 22:49:00 -07001389 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Howard Pershc1199d52012-04-11 14:21:32 -07001390 action_list=[vid_act])
1391
Dan Talayco551befa2010-07-15 17:05:32 -07001392class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001393 """
1394 Strip the VLAN tag from a tagged packet
1395 """
Dan Talayco551befa2010-07-15 17:05:32 -07001396 def runTest(self):
1397 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001398 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001399 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001400 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001401 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001402
Dan Talayco551befa2010-07-15 17:05:32 -07001403 len_w_vid = 104
1404 len = 100
1405 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
Rich Laned0478ff2013-03-11 12:46:58 -07001406 vlan_vid=old_vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001407 exp_pkt = simple_tcp_packet(pktlen=len)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001408 vid_act = ofp.action.strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001409
Rich Lane477f4812012-10-04 22:49:00 -07001410 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001411 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001412
Ken Chiange9a211d2012-04-20 14:52:11 -07001413class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1414 """
1415 Strip the VLAN tag from a tagged packet.
1416 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1417 """
1418 def runTest(self):
1419 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001420 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001421 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1422 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1423 return
1424
1425 len_w_vid = 104
1426 len_untagged = 100
1427 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
Rich Laned0478ff2013-03-11 12:46:58 -07001428 vlan_vid=old_vid)
Ken Chiange9a211d2012-04-20 14:52:11 -07001429 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
Ed Swierk99a74de2012-08-22 06:40:54 -07001430 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1431 ofp.OFPFW_DL_VLAN_PCP)
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001432 vid_act = ofp.action.strip_vlan()
Ken Chiange9a211d2012-04-20 14:52:11 -07001433
Rich Lane477f4812012-10-04 22:49:00 -07001434 flow_match_test(self, config["port_map"],
Ed Swierk99a74de2012-08-22 06:40:54 -07001435 wildcards=wildcards,
Ken Chiange9a211d2012-04-20 14:52:11 -07001436 pkt=pkt, exp_pkt=exp_pkt,
1437 action_list=[vid_act])
1438
Dan Talayco4b2bee62010-07-20 14:10:05 -07001439def init_pkt_args():
1440 """
1441 Pass back a dictionary with default packet arguments
1442 """
1443 args = {}
Rich Laned0478ff2013-03-11 12:46:58 -07001444 args["eth_src"] = '00:23:45:67:89:AB'
Dan Talayco4b2bee62010-07-20 14:10:05 -07001445
1446 dl_vlan_enable=False
Rich Laned0478ff2013-03-11 12:46:58 -07001447 vlan_vid=-1
Rich Lane477f4812012-10-04 22:49:00 -07001448 if config["test-params"]["vid"]:
Dan Talayco4b2bee62010-07-20 14:10:05 -07001449 dl_vlan_enable=True
Rich Laned0478ff2013-03-11 12:46:58 -07001450 vlan_vid = config["test-params"]["vid"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001451
1452# Unpack operator is ** on a dictionary
1453
1454 return args
1455
Dan Talayco551befa2010-07-15 17:05:32 -07001456class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001457 """
1458 Modify the source MAC address (TP1)
1459 """
Dan Talayco551befa2010-07-15 17:05:32 -07001460 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001461 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001462 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001463 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001464 return
1465
Rich Laned0478ff2013-03-11 12:46:58 -07001466 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_src'],
Dan Talayco4b2bee62010-07-20 14:10:05 -07001467 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001468 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001469 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001470
Dan Talayco551befa2010-07-15 17:05:32 -07001471class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001472 """
1473 Modify the dest MAC address (TP1)
1474 """
Dan Talayco551befa2010-07-15 17:05:32 -07001475 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001476 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001477 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001478 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001479 return
1480
Rich Laned0478ff2013-03-11 12:46:58 -07001481 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_dst'],
Dan Talayco4b2bee62010-07-20 14:10:05 -07001482 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001483 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001484 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001485
Dan Talayco551befa2010-07-15 17:05:32 -07001486class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001487 """
1488 Modify the source IP address of an IP packet (TP1)
1489 """
Dan Talayco551befa2010-07-15 17:05:32 -07001490 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001491 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001492 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001493 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001494 return
1495
1496 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1497 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001498 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001499 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001500
Dan Talayco551befa2010-07-15 17:05:32 -07001501class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001502 """
1503 Modify the dest IP address of an IP packet (TP1)
1504 """
Dan Talayco551befa2010-07-15 17:05:32 -07001505 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001506 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001507 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001508 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001509 return
1510
1511 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1512 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001513 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001514 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001515
1516class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001517 """
1518 Modify the source TCP port of a TCP packet (TP1)
1519 """
Dan Talayco551befa2010-07-15 17:05:32 -07001520 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001521 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001522 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001523 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001524 return
1525
1526 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1527 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001528 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001529 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001530
Rich Lane01c2b862012-10-26 16:26:25 -07001531class ModifyL4SrcUdp(BaseMatchCase):
1532 """
1533 Modify the source UDP port of a UDP packet
1534 """
1535 def runTest(self):
1536 sup_acts = self.supported_actions
1537 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1538 skip_message_emit(self, "ModifyL4SrcUdp test")
1539 return
1540
1541 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_sport'],
1542 check_test_params=True, tp="udp")
1543 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1544 action_list=acts, max_test=2)
1545
Dan Talayco551befa2010-07-15 17:05:32 -07001546class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001547 """
1548 Modify the dest TCP port of a TCP packet (TP1)
1549 """
Dan Talayco551befa2010-07-15 17:05:32 -07001550 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001551 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001552 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001553 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001554 return
1555
1556 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1557 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001558 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001559 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001560
Rich Lane01c2b862012-10-26 16:26:25 -07001561class ModifyL4DstUdp(BaseMatchCase):
1562 """
1563 Modify the dest UDP port of a UDP packet
1564 """
1565 def runTest(self):
1566 sup_acts = self.supported_actions
1567 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1568 skip_message_emit(self, "ModifyL4DstUdp test")
1569 return
1570
1571 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_dport'],
1572 check_test_params=True, tp="udp")
1573 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1574 action_list=acts, max_test=2)
1575
Dan Talayco551befa2010-07-15 17:05:32 -07001576class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001577 """
1578 Modify the IP type of service of an IP packet (TP1)
1579 """
Dan Talayco551befa2010-07-15 17:05:32 -07001580 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001581 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001582 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001583 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001584 return
Dan Talayco551befa2010-07-15 17:05:32 -07001585
Dan Talayco4b2bee62010-07-20 14:10:05 -07001586 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1587 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001588 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001589 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001590
Dan Talaycof6e76c02012-03-23 10:56:12 -07001591class ModifyL2DstMC(BaseMatchCase):
1592 """
1593 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001594 """
1595 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001596 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001597 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001598 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001599 return
1600
Rich Laned0478ff2013-03-11 12:46:58 -07001601 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_dst'],
Dan Talaycof6e76c02012-03-23 10:56:12 -07001602 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001603 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001604 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001605
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001606class ModifyL2DstIngress(BaseMatchCase):
1607 """
1608 Modify the L2 dest and send to the ingress port
1609 """
1610 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001611 sup_acts = self.supported_actions
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001612 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001613 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001614 return
1615
Rich Laned0478ff2013-03-11 12:46:58 -07001616 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_dst'],
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001617 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001618 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001619 action_list=acts, max_test=2, egr_count=0,
1620 ing_port=True)
1621
Dan Talaycod8ae7582012-03-23 12:24:56 -07001622class ModifyL2DstIngressMC(BaseMatchCase):
1623 """
1624 Modify the L2 dest and send to the ingress port
1625 """
1626 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001627 sup_acts = self.supported_actions
Dan Talaycod8ae7582012-03-23 12:24:56 -07001628 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1629 skip_message_emit(self, "ModifyL2dstMC test")
1630 return
1631
Rich Laned0478ff2013-03-11 12:46:58 -07001632 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_dst'],
Dan Talaycod8ae7582012-03-23 12:24:56 -07001633 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001634 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001635 action_list=acts, max_test=2, egr_count=-1,
1636 ing_port=True)
1637
Dan Talaycof6e76c02012-03-23 10:56:12 -07001638class ModifyL2SrcMC(BaseMatchCase):
1639 """
1640 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001641 """
1642 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001643 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001644 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001645 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001646 return
1647
Rich Laned0478ff2013-03-11 12:46:58 -07001648 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['eth_src'],
Dan Talaycof6e76c02012-03-23 10:56:12 -07001649 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001650 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001651 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001652
1653class ModifyL2SrcDstMC(BaseMatchCase):
1654 """
1655 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001656 """
1657 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001658 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001659 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1660 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1661 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001662 return
1663
Rich Laned0478ff2013-03-11 12:46:58 -07001664 mod_fields = ['eth_dst', 'eth_src']
Dan Talaycof6e76c02012-03-23 10:56:12 -07001665 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1666 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001667 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001668 action_list=acts, max_test=2, egr_count=-1)
1669
1670class ModifyL2DstVIDMC(BaseMatchCase):
1671 """
1672 Modify the L2 dest and send to 2 ports
1673 """
1674 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001675 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001676 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1677 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1678 skip_message_emit(self, "ModifyL2DstVIDMC test")
1679 return
1680
Rich Laned0478ff2013-03-11 12:46:58 -07001681 mod_fields = ['eth_dst', 'vlan_vid']
Dan Talaycocfa172f2012-03-23 12:03:00 -07001682 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1683 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1684 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001685 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001686 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001687
Rich Lane97e99652013-01-02 17:23:20 -08001688@group("smoke")
Rich Lane22e74c12012-11-12 15:06:06 -08001689class ModifyAll(BaseMatchCase):
1690 """
1691 Modify all supported fields and output to a port
1692 """
1693 def runTest(self):
1694 sup_acts = self.supported_actions
1695
1696 sup_map = {
Rich Laned0478ff2013-03-11 12:46:58 -07001697 "eth_dst" : ofp.OFPAT_SET_DL_DST,
1698 "eth_src" : ofp.OFPAT_SET_DL_SRC,
Rich Lane22e74c12012-11-12 15:06:06 -08001699 "dl_vlan_enable" : ofp.OFPAT_SET_VLAN_VID,
Rich Laned0478ff2013-03-11 12:46:58 -07001700 "vlan_vid" : ofp.OFPAT_SET_VLAN_VID,
1701 "vlan_pcp" : ofp.OFPAT_SET_VLAN_PCP,
Rich Lane22e74c12012-11-12 15:06:06 -08001702 "ip_src" : ofp.OFPAT_SET_NW_SRC,
1703 "ip_dst" : ofp.OFPAT_SET_NW_DST,
1704 "ip_tos" : ofp.OFPAT_SET_NW_TOS,
1705 "tcp_sport" : ofp.OFPAT_SET_TP_SRC,
1706 "tcp_dport" : ofp.OFPAT_SET_TP_DST,
1707 }
1708
1709 mod_fields = [field for (field, bit) in sup_map.items() if (sup_acts & 1 << bit)]
1710 random.shuffle(mod_fields)
1711 start_field_vals = { "dl_vlan_enable" : True }
1712 mod_field_vals = { "dl_vlan_enable" : True }
1713 logging.info("modifying fields: %s" % repr(mod_fields))
1714
1715 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1716 mod_fields=mod_fields,
1717 start_field_vals=start_field_vals,
1718 mod_field_vals=mod_field_vals,
1719 check_test_params=True)
1720 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1721 action_list=acts, max_test=2)
1722
Dan Talaycofa6454f2012-04-05 10:04:13 -07001723class FlowToggle(BaseMatchCase):
1724 """
1725 Add flows to the table and modify them repeatedly
Dan Talaycof7c41312012-07-23 12:53:19 -07001726
1727 This is done by using only "add" flow messages. Since the check overlap
1728 flag is not set, the switch is supposed to modify the existing flow if
1729 the match already exists.
1730
1731 Would probably be better to exercise more of the flow modify commands
1732 (add, modify, delete +/- strict).
Dan Talaycofa6454f2012-04-05 10:04:13 -07001733 """
1734 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001735 flow_count = test_param_get('ft_flow_count', default=20)
1736 iter_count = test_param_get('ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001737
Rich Lane9a003812012-10-04 17:17:59 -07001738 logging.info("Running flow toggle with %d flows, %d iterations" %
Dan Talaycofa6454f2012-04-05 10:04:13 -07001739 (flow_count, iter_count))
1740 acts = []
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001741 acts.append(ofp.action.output())
1742 acts.append(ofp.action.output())
Dan Talaycofa6454f2012-04-05 10:04:13 -07001743
Rich Lane477f4812012-10-04 22:49:00 -07001744 of_ports = config["port_map"].keys()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001745 if len(of_ports) < 3:
1746 self.assertTrue(False, "Too few ports for test")
1747
1748 for idx in range(2):
1749 acts[idx].port = of_ports[idx]
1750
1751 flows = []
1752 flows.append([])
1753 flows.append([])
1754
Ed Swierk99a74de2012-08-22 06:40:54 -07001755 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_SRC |
1756 ofp.OFPFW_DL_DST)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001757 # Create up the flows in an array
1758 for toggle in range(2):
1759 for f_idx in range(flow_count):
1760 pkt = simple_tcp_packet(tcp_sport=f_idx)
Rich Laneba3f0e22013-03-11 16:43:57 -07001761 msg = ofp.message.flow_add()
Ed Swierk99a74de2012-08-22 06:40:54 -07001762 match = packet_to_flow_match(self, pkt)
Shudong Zhou031373c2012-07-19 17:37:42 -07001763 match.in_port = of_ports[2]
Dan Talayco50be7672012-04-05 11:38:08 -07001764 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001765 msg.match = match
1766 msg.buffer_id = 0xffffffff
Rich Lanec495d9e2013-03-08 17:43:36 -08001767 msg.actions.append(acts[toggle])
Dan Talaycofa6454f2012-04-05 10:04:13 -07001768 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001769
1770 # Show two sample flows
Rich Lane9a003812012-10-04 17:17:59 -07001771 logging.debug(flows[0][0].show())
1772 logging.debug(flows[1][0].show())
Dan Talayco50be7672012-04-05 11:38:08 -07001773
Dan Talaycofa6454f2012-04-05 10:04:13 -07001774 # Install the first set of flows
1775 for f_idx in range(flow_count):
Rich Lane5c3151c2013-01-03 17:15:41 -08001776 self.controller.message_send(flows[0][f_idx])
Rich Lane3a261d52013-01-03 17:45:08 -08001777 do_barrier(self.controller)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001778
Rich Lane9a003812012-10-04 17:17:59 -07001779 logging.info("Installed %d flows" % flow_count)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001780
1781 # Repeatedly modify all the flows back and forth
1782 updates = 0
1783 # Report status about 5 times
1784 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001785 start = time.time()
1786 for iter_idx in range(iter_count):
1787 if not iter_idx % mod_val:
Rich Lane9a003812012-10-04 17:17:59 -07001788 logging.info("Flow Toggle: iter %d of %d. " %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001789 (iter_idx, iter_count) +
1790 "%d updates in %d secs" %
1791 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001792 for toggle in range(2):
1793 t_idx = 1 - toggle
1794 for f_idx in range(flow_count):
Rich Lane5c3151c2013-01-03 17:15:41 -08001795 self.controller.message_send(flows[t_idx][f_idx])
Dan Talaycofa6454f2012-04-05 10:04:13 -07001796 updates += 1
Rich Lane3a261d52013-01-03 17:45:08 -08001797 do_barrier(self.controller)
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001798
1799 end = time.time()
1800 divisor = end - start or (end - start + 1)
Rich Lane9a003812012-10-04 17:17:59 -07001801 logging.info("Flow toggle: %d iterations" % iter_count)
1802 logging.info(" %d flow mods in %d secs, %d mods/sec" %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001803 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001804
1805
Dan Talayco8a64e332012-03-28 14:53:20 -07001806# You can pick and choose these by commenting tests in or out
1807iter_classes = [
1808 basic.PacketIn,
1809 basic.PacketOut,
1810 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001811 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001812 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001813 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001814 AllWildcardMatch,
1815 AllWildcardMatchTagged,
1816 SingleWildcardMatch,
1817 SingleWildcardMatchTagged,
1818 ExactMatch,
1819 ExactMatchTagged,
1820 SingleWildcardMatch,
1821 ModifyL2Src,
1822 ModifyL2Dst,
1823 ModifyL2SrcMC,
1824 ModifyL2DstMC,
1825 ModifyL2SrcDstMC
1826 ]
1827
Rich Lane0a4f6372013-01-02 14:40:22 -08001828@disabled
Dan Talayco8a64e332012-03-28 14:53:20 -07001829class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001830 """
1831 Iterate over a bunch of test cases
1832
1833 The cases come from the list above
1834 """
1835
Dan Talayco8a64e332012-03-28 14:53:20 -07001836 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001837 count = test_param_get('iter_count', default=10)
Dan Talayco8a64e332012-03-28 14:53:20 -07001838 tests_done = 0
Rich Lane9a003812012-10-04 17:17:59 -07001839 logging.info("Running iteration test " + str(count) + " times")
Dan Talayco8a64e332012-03-28 14:53:20 -07001840 start = time.time()
1841 last = start
1842 for idx in range(count):
Rich Lane9a003812012-10-04 17:17:59 -07001843 logging.info("Iteration " + str(idx + 1))
Dan Talayco8a64e332012-03-28 14:53:20 -07001844 for cls in iter_classes:
1845 test = cls()
1846 test.inheritSetup(self)
1847 test.runTest()
1848 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001849 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001850 if time.time() - last > 60:
1851 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001852 logging.info(
Dan Talaycofa6454f2012-04-05 10:04:13 -07001853 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1854 (idx, count, tests_done, last - start) +
1855 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001856 stats = all_stats_get(self)
1857 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001858 logging.info("\nIterCases ran %d tests in %d seconds." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001859 (tests_done, last - start))
Rich Lane9a003812012-10-04 17:17:59 -07001860 logging.info(" flows: %d. packets: %d. bytes: %d" %
Dan Talayco8a64e332012-03-28 14:53:20 -07001861 (stats["flows"], stats["packets"], stats["bytes"]))
Rich Lane9a003812012-10-04 17:17:59 -07001862 logging.info(" active: %d. lookups: %d. matched %d." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001863 (stats["active"], stats["lookups"], stats["matched"]))
1864
Dan Talayco4b2bee62010-07-20 14:10:05 -07001865#@todo Need to implement tagged versions of the above tests
1866#
1867#@todo Implement a test case that strips tag 2, adds tag 3
1868# and modifies tag 4 to tag 5. Then verify (in addition) that
1869# tag 6 does not get modified.
1870
Rich Lane0a4f6372013-01-02 14:40:22 -08001871@disabled
Dan Talayco4b2bee62010-07-20 14:10:05 -07001872class MixedVLAN(BaseMatchCase):
1873 """
1874 Test mixture of VLAN tag actions
1875
1876 Strip tag 2 on port 1, send to port 2
1877 Add tag 3 on port 1, send to port 2
1878 Modify tag 4 to 5 on port 1, send to port 2
1879 All other traffic from port 1, send to port 3
1880 All traffic from port 2 sent to port 4
1881 Use exact matches with different packets for all mods
1882 Verify the following: (port, vid)
1883 (port 1, vid 2) => VLAN tag stripped, out port 2
1884 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1885 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1886 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1887 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1888 (port 2, no tag) => untagged packet out port 4
1889 (port 2, vid 2-6) => unmodified packet out port 4
1890
1891 Variation: Might try sending VID 5 to port 3 and check.
1892 If only VID 5 distinguishes pkt, this will fail on some platforms
1893 """
1894
Rich Lane97e99652013-01-02 17:23:20 -08001895@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -07001896class MatchEach(base_tests.SimpleDataPlane):
Rich Lane8d6ab272012-09-23 18:06:20 -07001897 """
1898 Check that each match field is actually matched on.
1899 Installs two flows that differ in one field. The flow that should not
1900 match has a higher priority, so if that field is ignored during matching
1901 the packet will be sent out the wrong port.
1902
1903 TODO test UDP, ARP, ICMP, etc.
1904 """
1905 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001906 of_ports = config["port_map"].keys()
Rich Lane8d6ab272012-09-23 18:06:20 -07001907 of_ports.sort()
1908 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1909
Rich Lane9a003812012-10-04 17:17:59 -07001910 delete_all_flows(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001911
Rich Laned0478ff2013-03-11 12:46:58 -07001912 pkt = simple_tcp_packet(dl_vlan_enable=True, vlan_vid=2)
Rich Lane8d6ab272012-09-23 18:06:20 -07001913 ingress_port = of_ports[0]
1914 egress_port = of_ports[1]
1915
1916 def testField(field, mask):
Rich Lane9a003812012-10-04 17:17:59 -07001917 logging.info("Testing field %s" % field)
Rich Lane8d6ab272012-09-23 18:06:20 -07001918
1919 def addFlow(matching, priority, output_port):
1920 match = packet_to_flow_match(self, pkt)
1921 self.assertTrue(match is not None, "Could not generate flow match from pkt")
1922 match.wildcards &= ~ofp.OFPFW_IN_PORT
1923 match.in_port = ingress_port
1924 if not matching:
1925 # Make sure flow doesn't match
1926 orig = getattr(match, field)
1927 if isinstance(orig, list):
1928 new = map(lambda a: ~a[0] & a[1], zip(orig, mask))
1929 else:
1930 new = ~orig & mask
1931 setattr(match, field, new)
Rich Laneba3f0e22013-03-11 16:43:57 -07001932 request = ofp.message.flow_add()
Rich Lane8d6ab272012-09-23 18:06:20 -07001933 request.match = match
1934 request.buffer_id = 0xffffffff
1935 request.priority = priority
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001936 act = ofp.action.output()
Rich Lane8d6ab272012-09-23 18:06:20 -07001937 act.port = output_port
Rich Lanec495d9e2013-03-08 17:43:36 -08001938 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -07001939 logging.info("Inserting flow")
Rich Lane8d6ab272012-09-23 18:06:20 -07001940 self.controller.message_send(request)
1941
1942 # This flow should match.
1943 addFlow(matching=True, priority=0, output_port=egress_port)
1944 # This flow should not match, but it has a higher priority.
1945 addFlow(matching=False, priority=1, output_port=ofp.OFPP_IN_PORT)
1946
Rich Lane3a261d52013-01-03 17:45:08 -08001947 do_barrier(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001948
Rich Lane9a003812012-10-04 17:17:59 -07001949 logging.info("Sending packet to dp port " + str(ingress_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001950 self.dataplane.send(ingress_port, str(pkt))
1951
1952 exp_pkt_arg = None
1953 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -07001954 if config["relax"]:
Rich Lane8d6ab272012-09-23 18:06:20 -07001955 exp_pkt_arg = pkt
1956 exp_port = egress_port
1957
1958 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
1959 exp_pkt=exp_pkt_arg)
1960 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -07001961 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001962 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
1963 self.assertEqual(str(pkt), str(rcv_pkt), 'Response packet does not match send packet')
1964
Ed Swierkb603b192012-12-12 15:38:49 -08001965 wildcards = required_wildcards(self)
Rich Lane8d6ab272012-09-23 18:06:20 -07001966 # TODO in_port
Ed Swierkb603b192012-12-12 15:38:49 -08001967 if not (wildcards & ofp.OFPFW_DL_SRC):
Rich Laned0478ff2013-03-11 12:46:58 -07001968 testField("eth_src", [0xff]*6)
Ed Swierkb603b192012-12-12 15:38:49 -08001969 if not (wildcards & ofp.OFPFW_DL_DST):
Rich Laned0478ff2013-03-11 12:46:58 -07001970 testField("eth_dst", [0xff]*6)
Ed Swierkb603b192012-12-12 15:38:49 -08001971 if not (wildcards & ofp.OFPFW_DL_TYPE):
Rich Laned0478ff2013-03-11 12:46:58 -07001972 testField("eth_type", 0xffff)
Ed Swierkb603b192012-12-12 15:38:49 -08001973 if not (wildcards & ofp.OFPFW_DL_VLAN):
Rich Laned0478ff2013-03-11 12:46:58 -07001974 testField("vlan_vid", 0xfff)
1975 # TODO vlan_pcp
Ed Swierkb603b192012-12-12 15:38:49 -08001976 if not (wildcards & ofp.OFPFW_NW_SRC_ALL):
Rich Laned0478ff2013-03-11 12:46:58 -07001977 testField("ipv4_src", 0xffffffff)
Ed Swierkb603b192012-12-12 15:38:49 -08001978 if not (wildcards & ofp.OFPFW_NW_DST_ALL):
Rich Laned0478ff2013-03-11 12:46:58 -07001979 testField("ipv4_dst", 0xffffffff)
Ed Swierkb603b192012-12-12 15:38:49 -08001980 if not (wildcards & ofp.OFPFW_NW_TOS):
Rich Laned0478ff2013-03-11 12:46:58 -07001981 testField("ip_dscp", 0x3f)
Ed Swierkb603b192012-12-12 15:38:49 -08001982 if not (wildcards & ofp.OFPFW_NW_PROTO):
Rich Laned0478ff2013-03-11 12:46:58 -07001983 testField("ip_proto", 0xff)
Ed Swierkb603b192012-12-12 15:38:49 -08001984 if not (wildcards & ofp.OFPFW_TP_SRC):
Rich Laned0478ff2013-03-11 12:46:58 -07001985 testField("tcp_src", 0xffff)
Ed Swierkb603b192012-12-12 15:38:49 -08001986 if not (wildcards & ofp.OFPFW_TP_DST):
Rich Laned0478ff2013-03-11 12:46:58 -07001987 testField("tcp_dst", 0xffff)
Rich Lane8d6ab272012-09-23 18:06:20 -07001988
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07001989class DirectBadPacketBase(base_tests.SimpleDataPlane):
1990 """
1991 Base class for sending single packets with single flow table entries.
1992 Used to verify matching of unusual packets and parsing/matching of
1993 corrupted packets.
1994
1995 The idea is to generate packets that may either be totally malformed or
1996 malformed just enough to trick the flow matcher into making mistakes.
1997
1998 Generate a 'bad' packet
1999 Generate and install a matching flow
2000 Add action to direct the packet to an egress port
2001 Send the packet to ingress dataplane port
2002 Verify the packet is received at the egress port only
2003 """
2004
2005 RESULT_MATCH = "MATCH"
2006 RESULT_NOMATCH = "NO MATCH"
2007 RESULT_ANY = "ANY MATCH"
2008
2009 def runTest(self):
2010 pass
2011 # TODO:
2012 # - ICMP?
2013 # - VLAN?
2014 # - action
2015
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002016 def createMatch(self, **kwargs):
Rich Lane0237baf2013-03-11 22:34:59 -07002017 match = ofp.match()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002018 match.wildcards = ofp.OFPFW_ALL
2019 fields = {
Rich Laned0478ff2013-03-11 12:46:58 -07002020 'eth_dst': ofp.OFPFW_DL_DST,
2021 'eth_src': ofp.OFPFW_DL_SRC,
2022 'eth_type': ofp.OFPFW_DL_TYPE,
2023 'vlan_vid': ofp.OFPFW_DL_VLAN,
2024 'ipv4_src': ofp.OFPFW_NW_SRC_MASK,
2025 'ipv4_dst': ofp.OFPFW_NW_DST_MASK,
2026 'ip_dscp': ofp.OFPFW_NW_TOS,
2027 'ip_proto': ofp.OFPFW_NW_PROTO,
2028 'tcp_src': ofp.OFPFW_TP_SRC,
2029 'tcp_dst': ofp.OFPFW_TP_DST,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002030 }
2031 for key in kwargs:
2032 setattr(match, key, kwargs[key])
2033 match.wildcards &= ~fields[key]
2034 return match
2035
2036 def testPktsAgainstFlow(self, pkts, acts, match):
2037 if type(acts) != list:
2038 acts = [acts]
2039 for info in pkts:
2040 title, pkt, expected_result = info
2041 self.testPktAgainstFlow(title, pkt, acts, match, expected_result)
2042
2043 def testPktAgainstFlow(self, title, pkt, acts, match, expected_result):
2044 of_ports = config["port_map"].keys()
2045 of_ports.sort()
2046 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
2047
Rich Lane32bf9482013-01-03 17:26:30 -08002048 delete_all_flows(self.controller)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002049
2050 ingress_port = of_ports[0]
2051 egress_port = of_ports[1]
2052
2053 logging.info("Testing packet '%s', expect result %s" %
2054 (title, expected_result))
2055 logging.info("Ingress %s to egress %s" %
2056 (str(ingress_port), str(egress_port)))
2057 logging.info("Packet:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002058 logging.info(inspect_packet(pkt))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002059
2060 match.in_port = ingress_port
2061
Rich Laneba3f0e22013-03-11 16:43:57 -07002062 request = ofp.message.flow_add()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002063 request.match = match
Rich Lane44cf12d2012-10-15 11:10:45 -07002064 request.priority = 1
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002065
2066 request.buffer_id = 0xffffffff
2067 for act in acts:
2068 act.port = egress_port
Rich Lanec495d9e2013-03-08 17:43:36 -08002069 request.actions.append(act)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002070
2071 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08002072 self.controller.message_send(request)
Rich Lane44cf12d2012-10-15 11:10:45 -07002073
2074 # This flow speeds up negative tests
2075 logging.info("Inserting catch-all flow")
Rich Laneba3f0e22013-03-11 16:43:57 -07002076 request2 = ofp.message.flow_add()
Rich Lane44cf12d2012-10-15 11:10:45 -07002077 request2.match = self.createMatch()
Dan Talayco3bfc8222013-02-13 18:18:57 -08002078 request2.match.wildcards &= ~ofp.OFPFW_IN_PORT
2079 request2.match.in_port = ingress_port
2080
Rich Lane44cf12d2012-10-15 11:10:45 -07002081 request2.priority = 0
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002082 act = ofp.action.output()
Rich Lane44cf12d2012-10-15 11:10:45 -07002083 act.port = ofp.OFPP_IN_PORT
Rich Lanec495d9e2013-03-08 17:43:36 -08002084 request2.actions.append(act)
Rich Lane5c3151c2013-01-03 17:15:41 -08002085 self.controller.message_send(request2)
Rich Lane44cf12d2012-10-15 11:10:45 -07002086
Rich Lane3a261d52013-01-03 17:45:08 -08002087 do_barrier(self.controller)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002088
Dan Talayco3bfc8222013-02-13 18:18:57 -08002089 pkt_str = str(pkt)
2090 if config["minsize"] > len(str(pkt)):
2091 pkt_str += '0' * (config["minsize"] - len(str(pkt)))
2092
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002093 logging.info("Sending packet to dp port " +
2094 str(ingress_port))
Dan Talayco3bfc8222013-02-13 18:18:57 -08002095 self.dataplane.send(ingress_port, pkt_str)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002096
2097 exp_pkt_arg = None
2098 exp_port = None
2099 if config["relax"]:
2100 exp_pkt_arg = pkt
2101 exp_port = egress_port
2102
Rich Lane44cf12d2012-10-15 11:10:45 -07002103 if expected_result == self.RESULT_MATCH:
2104 timeout = -1 # default timeout
2105 else:
2106 timeout = 1 # short timeout for negative tests
2107
2108 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(exp_pkt=exp_pkt_arg,
2109 timeout=timeout)
2110 if rcv_port == ingress_port:
2111 logging.debug("Packet matched catch-all flow")
2112 rcv_pkt = None
2113
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002114 if expected_result == self.RESULT_MATCH:
2115 self.assertTrue(rcv_pkt is not None,
2116 "Did not receive packet, expected a match")
2117 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
2118 str(rcv_port))
2119 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
2120 str_pkt = str(pkt)
2121 str_rcv_pkt = str(rcv_pkt)
2122 str_rcv_pkt = str_rcv_pkt[0:len(str_pkt)]
2123 if str_pkt != str_rcv_pkt:
2124 logging.error("Response packet does not match send packet")
2125 logging.info("Response:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002126 logging.info(inspect_packet(scapy.Ether(rcv_pkt)))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002127 self.assertEqual(str_pkt, str_rcv_pkt,
2128 'Response packet does not match send packet')
2129 elif expected_result == self.RESULT_NOMATCH:
2130 self.assertTrue(rcv_pkt is None, "Received packet, expected drop")
2131 else:
2132 logging.debug("Match or drop accepted. Result = %s" %
2133 ("match" if rcv_pkt is not None else "drop"))
2134
2135
2136class DirectBadIpTcpPacketsBase(DirectBadPacketBase):
2137 """
2138 Base class for TCP and UDP parsing/matching verification under corruptions
2139 """
2140 def runTest(self):
2141 pass
2142
2143 def runTestWithProto(self, protoName = 'TCP'):
Rich Laned0478ff2013-03-11 12:46:58 -07002144 eth_dst='00:01:02:03:04:05'
2145 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002146 ip_src='192.168.0.1'
2147 ip_dst='192.168.0.2'
2148 ip_tos=0
2149 tcp_sport=1234
2150 tcp_dport=80
2151
2152 # Generate a proper packet for constructing a match
2153 tp = None
2154 if protoName == 'TCP':
2155 tp = scapy.TCP
2156 proto = 6
2157 elif protoName == 'UDP':
2158 tp = scapy.UDP
2159 proto = 17
2160 else:
2161 raise Exception("Passed in unknown proto name")
2162
Rich Laned0478ff2013-03-11 12:46:58 -07002163 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002164 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2165 tp(sport=tcp_sport, dport=tcp_dport)
2166 match = packet_to_flow_match(self, match_pkt)
2167 self.assertTrue(match is not None,
2168 "Could not generate flow match from pkt")
2169 match.wildcards &= ~ofp.OFPFW_IN_PORT
2170
2171 def testPacket(title, pkt, result):
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002172 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002173 pkts = [
2174 [title, pkt, result]
2175 ]
2176 self.testPktsAgainstFlow(pkts, act, match)
2177
2178 # Try incomplete IP headers
2179 testPacket("Incomplete IP header (1 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002180 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002181 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:1],
2182 self.RESULT_NOMATCH,
2183 )
2184 testPacket("Incomplete IP header (2 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002185 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002186 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:2],
2187 self.RESULT_NOMATCH,
2188 )
2189 testPacket("Incomplete IP header (3 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002190 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002191 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:3],
2192 self.RESULT_NOMATCH,
2193 )
2194 testPacket("Incomplete IP header (12 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002195 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002196 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:12],
2197 self.RESULT_NOMATCH,
2198 )
2199 testPacket("Incomplete IP header (16 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002200 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002201 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:16],
2202 self.RESULT_NOMATCH,
2203 )
2204 testPacket("Incomplete IP header (19 bytes)",
Rich Laned0478ff2013-03-11 12:46:58 -07002205 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002206 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:19],
2207 self.RESULT_NOMATCH,
2208 )
2209
2210 # Try variations where the TCP header is missing or incomplete. As we
2211 # saw bugs before where buffers were reused and lengths weren't honored,
2212 # we initiatlize once with a non-matching full packet and once with a
2213 # matching full packet.
2214 testPacket("Non-Matching TCP packet, warming buffer",
Rich Laned0478ff2013-03-11 12:46:58 -07002215 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002216 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2217 tp(sport=tcp_sport, dport=tcp_dport + 1),
2218 self.RESULT_NOMATCH,
2219 )
2220 testPacket("Missing TCP header, buffer warmed with non-match",
Rich Laned0478ff2013-03-11 12:46:58 -07002221 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002222 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2223 self.RESULT_NOMATCH,
2224 )
2225 testPacket("Matching TCP packet, warming buffer",
Rich Laned0478ff2013-03-11 12:46:58 -07002226 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002227 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2228 tp(sport=tcp_sport, dport=tcp_dport),
2229 self.RESULT_MATCH,
2230 )
2231 testPacket("Missing TCP header, buffer warmed with match",
Rich Laned0478ff2013-03-11 12:46:58 -07002232 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002233 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2234 self.RESULT_NOMATCH,
2235 )
2236 testPacket("Truncated TCP header: 2 bytes",
Rich Laned0478ff2013-03-11 12:46:58 -07002237 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002238 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2239 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:2]),
2240 self.RESULT_NOMATCH,
2241 )
2242
2243 # Play with IP header length values that put the start of TCP either
2244 # inside the generated TCP header or beyond. In some cases it may even
2245 # be beyond the packet boundary. Also play with IP options and more
2246 # importantly IP total length corruptions.
2247 testPacket("TCP packet, corrupt ihl (0x6)",
2248 simple_tcp_packet(ip_ihl=6),
2249 self.RESULT_NOMATCH,
2250 )
2251 testPacket("TCP packet, corrupt ihl (0xf)",
2252 simple_tcp_packet(ip_ihl=0xf), # ihl = 15 * 4 = 60
2253 self.RESULT_NOMATCH,
2254 )
2255 testPacket("TCP packet, corrupt ihl and total length",
2256 simple_tcp_packet(ip_ihl=0xf, pktlen=56), # ihl = 15 * 4 = 60,
2257 self.RESULT_NOMATCH,
2258 )
2259 testPacket("Corrupt IPoption: First 4 bytes of matching TCP header",
2260 simple_tcp_packet(
2261 ip_options=scapy.IPOption('\x04\xd2\x00\x50'),
2262 tcp_dport=2, tcp_sport=2
2263 ),
2264 self.RESULT_NOMATCH,
2265 )
2266 testPacket("Missing TCP header, corrupt ihl",
Rich Laned0478ff2013-03-11 12:46:58 -07002267 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002268 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto),
2269 self.RESULT_NOMATCH,
2270 )
2271 testPacket("Missing TCP header, corrupt total length",
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, len= 100),
2274 self.RESULT_NOMATCH,
2275 )
2276 testPacket("Missing TCP header, corrupt ihl and total length",
Rich Laned0478ff2013-03-11 12:46:58 -07002277 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002278 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto, len=43),
2279 self.RESULT_NOMATCH,
2280 )
2281 testPacket("Incomplete IP header (12 bytes), corrupt ihl and total length",
Rich Laned0478ff2013-03-11 12:46:58 -07002282 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002283 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:12],
2284 self.RESULT_NOMATCH,
2285 )
2286 testPacket("Incomplete IP header (16 bytes), corrupt ihl and total length",
Rich Laned0478ff2013-03-11 12:46:58 -07002287 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002288 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:16],
2289 self.RESULT_NOMATCH,
2290 )
2291
2292 # Try an incomplete TCP header that has enough bytes to carry source and
2293 # destination ports. As that is all we care about during matching, some
2294 # implementations may match and some may drop the packet
2295 testPacket("Incomplete TCP header: src/dst port present",
Rich Laned0478ff2013-03-11 12:46:58 -07002296 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002297 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2298 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:4]),
2299 self.RESULT_ANY,
2300 )
2301
2302 for i in range(1):
2303 for length in range(40 / 4): # IPv4 options are a maximum of 40 in length
2304 bytes = "".join([("%c" % random.randint(0, 255)) for x in range(length * 4)])
Rich Laned0478ff2013-03-11 12:46:58 -07002305 eth = scapy.Ether(dst=eth_dst, src=eth_src)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002306 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2307 tcp = tp(sport=tcp_sport, dport=tcp_dport+1)
2308 pkt = eth / ip
2309 pkt = pkt / bytes
2310 pkt = pkt / str(tcp)
2311 testPacket("Random IP options len = %d - TP match must fail" % length * 4,
2312 pkt,
2313 self.RESULT_NOMATCH
2314 )
2315
Rich Laned0478ff2013-03-11 12:46:58 -07002316 eth = scapy.Ether(dst=eth_dst, src=eth_src)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002317 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2318 tcp = tp(sport=tcp_sport, dport=tcp_dport)
2319 pkt = eth / ip
2320 pkt = pkt / bytes
2321 pkt = pkt / str(tcp)
2322
2323 testPacket("Random IP options len = %d - May match",
2324 pkt,
2325 self.RESULT_ANY
2326 )
2327
2328
2329class DirectBadIpTcpPackets(DirectBadIpTcpPacketsBase):
2330 """
2331 Verify IP/TCP parsing and matching. Focus on packet corruptions
2332 """
2333 def runTest(self):
2334 self.runTestWithProto(protoName = 'TCP')
2335
2336class DirectBadIpUdpPackets(DirectBadIpTcpPacketsBase):
2337 """
2338 Verify IP/UDP parsing and matching. Focus on packet corruptions
2339 """
2340 def runTest(self):
2341 self.runTestWithProto(protoName = 'UDP')
2342
2343class DirectBadLlcPackets(DirectBadPacketBase):
2344 """
2345 Verify LLC/SNAP parsing and matching. Focus on packet corruptions
2346 """
2347 def runTest(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002348 eth_dst='00:01:02:03:04:05'
2349 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002350 ip_src='192.168.0.1'
2351 ip_dst='192.168.0.2'
2352 ip_tos=0
2353 tcp_sport=1234
2354 tcp_dport=80
2355
2356 IS_SNAP_IP = 1
2357 IS_SNAP_IP_CORRUPT = 2
2358 IS_NOT_SNAP_IP = 3
2359
2360 def testPacketTcpMatch(title, llc):
Rich Laned0478ff2013-03-11 12:46:58 -07002361 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002362 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2363 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
2364 match = packet_to_flow_match(self, match_pkt)
2365 self.assertTrue(match is not None,
2366 "Could not generate flow match from pkt")
2367 match.wildcards &= ~ofp.OFPFW_IN_PORT
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002368 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002369
2370 self.testPktsAgainstFlow(
2371 [[
2372 "TCP match - LLC frame correct length - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002373 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002374 self.RESULT_ANY,
2375 ]],
2376 act, match
2377 )
2378
2379 # Corrupt length field
2380 ethLen = random.randint(0, 1535)
2381 self.testPktsAgainstFlow(
2382 [[
2383 "TCP match - LLC frame corrupted length - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002384 scapy.Ether(dst=eth_dst, src=eth_src, type=ethLen) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002385 self.RESULT_ANY,
2386 ]],
2387 act, match
2388 )
2389
2390 def testPacketEthSrcDstMatch(title, llc):
2391 # Matching based on Ethernet source and destination
Rich Laned0478ff2013-03-11 12:46:58 -07002392 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002393 match = packet_to_flow_match(self, match_pkt)
2394 self.assertTrue(match is not None,
2395 "Could not generate flow match from pkt")
2396 match.wildcards &= ~ofp.OFPFW_IN_PORT
2397 match.wildcards |= ofp.OFPFW_DL_TYPE
2398 self.testPktsAgainstFlow(
2399 [[
2400 "Eth addr match - LLC frame correct length- %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002401 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002402 self.RESULT_MATCH,
2403 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002404 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002405 )
2406
2407 # Corrupt length field
2408 ethLen = random.randint(0, 1535)
2409 self.testPktsAgainstFlow(
2410 [[
2411 "Eth addr match - LLC frame corrupted length- %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002412 scapy.Ether(dst=eth_dst, src=eth_src, type=ethLen) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002413 self.RESULT_ANY,
2414 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002415 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002416 )
2417
2418 def testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip):
2419 # Matching based on Ethernet source, destination and type
Rich Laned0478ff2013-03-11 12:46:58 -07002420 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=0x800)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002421 match = packet_to_flow_match(self, match_pkt)
2422 self.assertTrue(match is not None,
2423 "Could not generate flow match from pkt")
2424 match.wildcards &= ~ofp.OFPFW_IN_PORT
2425 if is_snap_ip == IS_SNAP_IP:
2426 is_match = self.RESULT_MATCH
2427 elif is_snap_ip == IS_SNAP_IP_CORRUPT:
2428 is_match = self.RESULT_ANY
2429 else:
2430 is_match = self.RESULT_NOMATCH
2431 self.testPktsAgainstFlow(
2432 [[
2433 "Eth addr+type match - LLC frame correct length - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002434 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002435 is_match,
2436 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002437 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002438 )
2439
2440 # Corrupt length field
2441 ethLen = random.randint(0, 1535)
2442 self.testPktsAgainstFlow(
2443 [[
2444 "Eth addr+type match - LLC frame corrupted length - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002445 scapy.Ether(dst=eth_dst, src=eth_src, type=ethLen) / llc,
Christian Dickmanne9b6d252012-10-08 22:56:50 -07002446 self.RESULT_ANY,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002447 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002448 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002449 )
2450
2451 def testPacket(title, llc, is_snap_ip):
2452 testPacketTcpMatch(title, llc)
2453 testPacketEthSrcDstMatch(title, llc)
2454 testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip)
2455
2456 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002457 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002458 IS_NOT_SNAP_IP,
2459 )
2460 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002461 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002462 IS_NOT_SNAP_IP,
2463 )
2464 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002465 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002466 IS_NOT_SNAP_IP,
2467 )
2468 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002469 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002470 IS_NOT_SNAP_IP,
2471 )
2472 testPacket("LLC - SNAP - Small bogus payload",
2473 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2474 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2475 IS_SNAP_IP_CORRUPT,
2476 )
2477 testPacket("LLC - SNAP - Max -1 bogus payload",
2478 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2479 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2480 IS_NOT_SNAP_IP,
2481 )
2482 testPacket("LLC - SNAP - Max bogus payload",
2483 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2484 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2485 IS_NOT_SNAP_IP,
2486 )
2487 testPacket("LLC - SNAP - IP - TCP",
2488 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2489 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2490 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2491 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2492 IS_SNAP_IP,
2493 )
2494
2495
2496class DirectLlcPackets(DirectBadPacketBase):
2497 """
2498 Verify LLC/SNAP parsing (valid and corrupted packets) and matching
2499 """
2500 def runTest(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002501 eth_dst='00:01:02:03:04:05'
2502 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002503 ip_src='192.168.0.1'
2504 ip_dst='192.168.0.2'
2505 ip_tos=0
2506 tcp_sport=1234
2507 tcp_dport=80
2508
2509 # Test ethertype in face of LLC/SNAP and OFP_DL_TYPE_NOT_ETH_TYPE
2510 IS_SNAP_NOT_IP = 1
2511 IS_SNAP_AND_IP = 2
2512 IS_NOT_SNAP = 3
2513
2514 def testPacketEthTypeIP(title, llc, is_snap):
Rich Laned0478ff2013-03-11 12:46:58 -07002515 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src, type=0x800)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002516 match = packet_to_flow_match(self, match_pkt)
2517 self.assertTrue(match is not None,
2518 "Could not generate flow match from pkt")
2519 match.wildcards &= ~ofp.OFPFW_IN_PORT
2520 pkts = []
2521 if is_snap == IS_NOT_SNAP or is_snap == IS_SNAP_NOT_IP:
2522 result = self.RESULT_NOMATCH
2523 else:
2524 result = self.RESULT_MATCH
2525 pkts.append([
2526 "Ether type 0x800 match - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002527 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002528 result,
2529 ])
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002530 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002531 self.testPktsAgainstFlow(pkts, act, match)
2532
2533 def testPacketEthTypeNotEth(title, llc, is_snap):
Rich Laned0478ff2013-03-11 12:46:58 -07002534 match_pkt = scapy.Ether(dst = eth_dst, src = eth_src,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002535 type = ofp.OFP_DL_TYPE_NOT_ETH_TYPE)
2536 match = packet_to_flow_match(self, match_pkt)
2537 self.assertTrue(match is not None,
2538 "Could not generate flow match from pkt")
2539 match.wildcards &= ~ofp.OFPFW_IN_PORT
2540 pkts = []
2541 if is_snap == IS_NOT_SNAP:
2542 result = self.RESULT_MATCH
2543 else:
2544 result = self.RESULT_NOMATCH
2545 pkts.append([
2546 "Ether type OFP_DL_TYPE_NOT_ETH_TYPE match - %s" % title,
Rich Laned0478ff2013-03-11 12:46:58 -07002547 scapy.Ether(dst=eth_dst, src=eth_src, type=len(llc)) / llc,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002548 result,
2549 ])
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002550 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002551 self.testPktsAgainstFlow(pkts, act, match)
2552
2553 def testPacket(title, llc, is_snap):
2554 testPacketEthTypeIP(title, llc, is_snap)
2555 testPacketEthTypeNotEth(title, llc, is_snap)
2556
2557 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002558 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
2559 IS_NOT_SNAP,
2560 )
2561 testPacket("LLC (with information field) - No SNAP - No Payload",
2562 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x12) / "S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002563 IS_NOT_SNAP,
2564 )
2565 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002566 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002567 IS_NOT_SNAP,
2568 )
2569 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002570 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002571 IS_NOT_SNAP,
2572 )
2573 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002574 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002575 IS_NOT_SNAP,
2576 )
2577 testPacket("LLC - SNAP - Non-default OUI",
2578 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2579 scapy.SNAP(OUI=0x000001, code=0x800) / ("S" * 10),
2580 IS_NOT_SNAP,
2581 )
2582 testPacket("LLC - SNAP - Default OUI",
2583 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2584 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2585 IS_SNAP_AND_IP,
2586 )
2587 testPacket("LLC - SNAP - Max -1 bogus payload",
2588 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2589 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2590 IS_SNAP_NOT_IP,
2591 )
2592 testPacket("LLC - SNAP - Max bogus payload",
2593 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2594 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2595 IS_SNAP_NOT_IP,
2596 )
2597 testPacket("LLC - SNAP - IP - TCP",
2598 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2599 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2600 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2601 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2602 IS_SNAP_AND_IP,
2603 )
2604
2605
2606class DirectArpPackets(DirectBadPacketBase):
2607 """
2608 Verify ARP parsing (valid and corrupted packets) and ARP matching
2609 """
2610 def runTest(self):
2611 self.testArpHandling()
2612
2613 def testArpHandling(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002614 eth_dst='00:01:02:03:04:05'
2615 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002616 ip_src='192.168.0.1'
2617 ip_dst='192.168.0.2'
2618 ip_src2='192.168.1.1'
2619 ip_dst2='192.168.1.2'
2620 ip_tos=0
2621 tcp_sport=1234
2622 tcp_dport=80
2623
2624 def testPacket(title, arp_match, arp_pkt, result):
2625 pkts = []
2626
Rich Laned0478ff2013-03-11 12:46:58 -07002627 match_pkt = scapy.Ether(dst=eth_dst, src=eth_src) / arp_match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002628 match = packet_to_flow_match(self, match_pkt)
2629 self.assertTrue(match is not None,
2630 "Could not generate flow match from pkt")
2631 match.wildcards &= ~ofp.OFPFW_IN_PORT
2632
2633 pkts.append([
2634 title,
Rich Laned0478ff2013-03-11 12:46:58 -07002635 scapy.Ether(dst=eth_dst, src=eth_src) / arp_pkt,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002636 result,
2637 ])
2638
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002639 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002640 self.testPktsAgainstFlow(pkts, act, match)
2641
2642 testPacket("Basic ARP",
2643 scapy.ARP(psrc=ip_src, pdst=ip_dst, op = 1),
Rich Laned0478ff2013-03-11 12:46:58 -07002644 scapy.ARP(hwdst = '00:00:00:00:00:00', hwsrc = eth_src,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002645 psrc = ip_src, pdst = ip_dst, hwlen = 6, plen = 4,
2646 ptype = 0x800, hwtype = 1, op = 1),
2647 self.RESULT_MATCH
2648 )
2649 # More stuff:
2650 # - Non matches on any property
2651 # - Corrupted hwlen and plen
2652 # - Other hwtype, ptype
2653 # - Truncated ARP pkt
2654
2655
2656class DirectVlanPackets(DirectBadPacketBase):
2657 """
2658 Verify VLAN parsing (valid and corrupted packets) and ARP matching
2659 """
2660 def runTest(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002661 eth_dst='00:01:02:03:04:05'
2662 eth_src='00:06:07:08:09:0a'
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002663 ip_src='192.168.0.1'
2664 ip_dst='192.168.0.2'
2665 ip_src2='192.168.1.1'
2666 ip_dst2='192.168.1.2'
2667 ip_tos=0
2668 tcp_sport=1234
2669 tcp_dport=80
2670
2671 def testPacket(title, match, pkt, result):
2672 pkts = []
2673
2674 self.assertTrue(match is not None,
2675 "Could not generate flow match from pkt")
2676 match.wildcards &= ~ofp.OFPFW_IN_PORT
2677
2678 pkts.append([
2679 "%s" % title,
2680 pkt,
2681 result,
2682 ])
2683
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002684 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002685 self.testPktsAgainstFlow(pkts, act, match)
2686
2687 testPacket("Basic MAC matching - IPv4 payload",
Rich Laned0478ff2013-03-11 12:46:58 -07002688 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2689 scapy.Ether(dst=eth_dst, src=eth_src, type=0x800) / scapy.IP(),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002690 self.RESULT_MATCH
2691 )
2692 testPacket("Basic MAC matching - VMware beacon - no payload",
Rich Laned0478ff2013-03-11 12:46:58 -07002693 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2694 scapy.Ether(dst=eth_dst, src=eth_src, type=0x8922),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002695 self.RESULT_MATCH
2696 )
2697 testPacket("Basic MAC matching - VMware beacon - with payload",
Rich Laned0478ff2013-03-11 12:46:58 -07002698 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2699 scapy.Ether(dst=eth_dst, src=eth_src, type=0x8922)/ ("X" * 1),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002700 self.RESULT_MATCH
2701 )
2702 testPacket("Basic MAC matching - IPv6 payload",
Rich Laned0478ff2013-03-11 12:46:58 -07002703 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
2704 scapy.Ether(dst=eth_dst, src=eth_src) / scapy.IPv6(),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002705 self.RESULT_MATCH
2706 )
2707 testPacket("Basic MAC matching with VLAN tag present",
Rich Laned0478ff2013-03-11 12:46:58 -07002708 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src)),
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_MATCH
2713 )
2714 testPacket("Basic MAC matching with VLAN tag present",
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=0x800),
2717 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002718 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002719 scapy.IP(),
2720 self.RESULT_MATCH
2721 )
2722 testPacket("Ether matching with VLAN tag present - No type match",
Rich Laned0478ff2013-03-11 12:46:58 -07002723 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2724 eth_type=0x801),
2725 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002726 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002727 scapy.IP(),
2728 self.RESULT_NOMATCH
2729 )
2730 testPacket("Ether matching with VLAN tag present - No type match 0x8100",
Rich Laned0478ff2013-03-11 12:46:58 -07002731 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2732 eth_type=0x8100),
2733 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002734 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002735 scapy.IP(),
2736 self.RESULT_NOMATCH
2737 )
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002738 testPacket("IP matching - VLAN tag",
Rich Laned0478ff2013-03-11 12:46:58 -07002739 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2740 eth_type=0x0800,
2741 ipv4_src=parse_ip(ip_src), ipv4_dst=parse_ip(ip_dst)),
2742 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002743 scapy.Dot1Q(prio=5, vlan=1000)/ \
2744 scapy.IP(src=ip_src, dst=ip_dst),
2745 self.RESULT_MATCH
2746 )
2747 # XXX:
2748 # - Matching on VLAN ID and Prio
2749 # - Actions
2750
2751@nonstandard
2752class DirectVlanPacketsDoubleTagged(DirectVlanPackets):
2753 """
2754 VLAN parsing for double tagged packets. Spec is ambiguous about
2755 the treatment of these cases, so broken out to be non-standard
2756 """
2757 def runTest(self):
Rich Laned0478ff2013-03-11 12:46:58 -07002758 eth_dst='00:01:02:03:04:05'
2759 eth_src='00:06:07:08:09:0a'
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002760 ip_src='192.168.0.1'
2761 ip_dst='192.168.0.2'
2762 ip_src2='192.168.1.1'
2763 ip_dst2='192.168.1.2'
2764 ip_tos=0
2765 tcp_sport=1234
2766 tcp_dport=80
2767
2768 def testPacket(title, match, pkt, result):
2769 pkts = []
2770
2771 self.assertTrue(match is not None,
2772 "Could not generate flow match from pkt")
2773 match.wildcards &= ~ofp.OFPFW_IN_PORT
2774
2775 pkts.append([
2776 "%s" % title,
2777 pkt,
2778 result,
2779 ])
2780
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002781 act = ofp.action.output()
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002782 self.testPktsAgainstFlow(pkts, act, match)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002783 testPacket("Ether matching with double VLAN tag - Wrong type match",
Rich Laned0478ff2013-03-11 12:46:58 -07002784 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2785 eth_type=0x800),
2786 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002787 scapy.Dot1Q(prio=5, vlan=1000)/ \
2788 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002789 scapy.IP(),
2790 self.RESULT_NOMATCH
2791 )
2792 testPacket("Ether matching with double VLAN tag - Type match",
Rich Laned0478ff2013-03-11 12:46:58 -07002793 self.createMatch(eth_dst=parse_mac(eth_dst), eth_src=parse_mac(eth_src),
2794 eth_type=0x8100),
2795 scapy.Ether(dst=eth_dst, src=eth_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002796 scapy.Dot1Q(prio=5, vlan=1000)/ \
2797 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002798 scapy.IP(),
2799 self.RESULT_MATCH
2800 )
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002801
2802
2803
Dan Talayco9f47f4d2010-06-03 13:54:37 -07002804if __name__ == "__main__":
2805 print "Please run through oft script: ./oft --test_spec=basic"