blob: bd3e79feafbb9bb9e5521b72093d1e94abcfff1c [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 Lane28fa9272013-03-08 16:00:25 -0800119 request = ofp.message.flow_mod()
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 Lane28fa9272013-03-08 16:00:25 -0800183 request = ofp.message.flow_mod()
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 = []
226 for qs in queue_stats.stats:
227 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 Lane28fa9272013-03-08 16:00:25 -0800270 request = ofp.message.flow_mod()
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
Ed Swierk22f59152012-04-17 16:36:47 -0700325 self.assertEqual(qs_after.stats[0].tx_packets, \
326 qs_before.stats[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 = []
348 for qs in queue_stats.stats:
349 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 Laneb8c845a2012-12-31 17:23:51 -0800375 if queue_stats.header.type == ofp.OFPT_ERROR:
376 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 Lane28fa9272013-03-08 16:00:25 -0800399 request = ofp.message.flow_mod()
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
464 self.assertEqual(qs_after.stats[0].tx_packets, \
465 qs_before.stats[0].tx_packets + 1, \
466 "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 Lane28fa9272013-03-08 16:00:25 -0800517 request = ofp.message.flow_mod()
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 Lane28fa9272013-03-08 16:00:25 -0800567 request = ofp.message.flow_mod()
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 Lane28fa9272013-03-08 16:00:25 -0800616 request = ofp.message.flow_mod()
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 Lane28fa9272013-03-08 16:00:25 -0800673 request = ofp.message.flow_mod()
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 Lane28fa9272013-03-08 16:00:25 -0800718 request = ofp.message.flow_mod()
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 Lane28fa9272013-03-08 16:00:25 -0800761 request = ofp.message.flow_mod()
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 Lane28fa9272013-03-08 16:00:25 -0800806 request = ofp.message.flow_mod()
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 Lane28fa9272013-03-08 16:00:25 -0800863 request = ofp.message.flow_mod()
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 Lane477f4812012-10-04 22:49:00 -0700927 flow_match_test(self, config["port_map"], dl_vlan=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 Lane477f4812012-10-04 22:49:00 -0700937 flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
Dan Talayco551befa2010-07-15 17:05:32 -0700938 for vid in range(100,4000,389):
Rich Lane477f4812012-10-04 22:49:00 -0700939 flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
940 flow_match_test(self, config["port_map"], dl_vlan=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):
1025 msg = self.flowMsgs[prio]
1026 msg.command = ofp.OFPFC_DELETE_STRICT
1027 # This *must* be set for DELETE
1028 msg.out_port = ofp.OFPP_NONE
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
1164 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001165 else:
1166 dl_vlan = -1
Rich Lane477f4812012-10-04 22:49:00 -07001167 flow_match_test(self, config["port_map"], wildcards=wc,
Dan Talayco4431d542012-03-21 16:42:16 -07001168 dl_vlan=dl_vlan, 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 Lane477f4812012-10-04 22:49:00 -07001178 flow_match_test(self, config["port_map"], wildcards=wc, dl_vlan=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
1198 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001199 else:
1200 dl_vlan = -1
Rich Lane477f4812012-10-04 22:49:00 -07001201 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Dan Talayco4431d542012-03-21 16:42:16 -07001202 dl_vlan=dl_vlan)
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,
Dan Talayco21381562010-07-17 00:34:47 -07001213 dl_vlan=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,
Dan Talayco21381562010-07-17 00:34:47 -07001236 dl_vlan=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,
1254 dl_vlan=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)
Dan Talayco551befa2010-07-15 17:05:32 -07001284 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=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
Dan Talayco551befa2010-07-15 17:05:32 -07001308 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1309 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=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,
1349 dl_vlan_enable=True, dl_vlan=old_vid)
1350 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1351 dl_vlan=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
1384 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1385 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_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,
1406 dl_vlan=old_vid)
1407 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,
1428 dl_vlan=old_vid)
1429 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 = {}
1444 args["dl_src"] = '00:23:45:67:89:AB'
1445
1446 dl_vlan_enable=False
1447 dl_vlan=-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 Lane477f4812012-10-04 22:49:00 -07001450 dl_vlan = 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
1466 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1467 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
1481 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1482 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
Dan Talaycof6e76c02012-03-23 10:56:12 -07001601 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1602 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
1616 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1617 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
1632 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1633 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001634 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan 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
Dan Talaycof6e76c02012-03-23 10:56:12 -07001648 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1649 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
Dan Talaycof6e76c02012-03-23 10:56:12 -07001664 mod_fields = ['dl_dst', 'dl_src']
1665 (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
1681 mod_fields = ['dl_dst', 'dl_vlan']
1682 (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 = {
1697 "dl_dst" : ofp.OFPAT_SET_DL_DST,
1698 "dl_src" : ofp.OFPAT_SET_DL_SRC,
1699 "dl_vlan_enable" : ofp.OFPAT_SET_VLAN_VID,
1700 "dl_vlan" : ofp.OFPAT_SET_VLAN_VID,
1701 "dl_vlan_pcp" : ofp.OFPAT_SET_VLAN_PCP,
1702 "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 Lane28fa9272013-03-08 16:00:25 -08001761 msg = ofp.message.flow_mod()
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
Dan Talaycof7c41312012-07-23 12:53:19 -07001767 msg.command = ofp.OFPFC_ADD
Rich Lanec495d9e2013-03-08 17:43:36 -08001768 msg.actions.append(acts[toggle])
Dan Talaycofa6454f2012-04-05 10:04:13 -07001769 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001770
1771 # Show two sample flows
Rich Lane9a003812012-10-04 17:17:59 -07001772 logging.debug(flows[0][0].show())
1773 logging.debug(flows[1][0].show())
Dan Talayco50be7672012-04-05 11:38:08 -07001774
Dan Talaycofa6454f2012-04-05 10:04:13 -07001775 # Install the first set of flows
1776 for f_idx in range(flow_count):
Rich Lane5c3151c2013-01-03 17:15:41 -08001777 self.controller.message_send(flows[0][f_idx])
Rich Lane3a261d52013-01-03 17:45:08 -08001778 do_barrier(self.controller)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001779
Rich Lane9a003812012-10-04 17:17:59 -07001780 logging.info("Installed %d flows" % flow_count)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001781
1782 # Repeatedly modify all the flows back and forth
1783 updates = 0
1784 # Report status about 5 times
1785 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001786 start = time.time()
1787 for iter_idx in range(iter_count):
1788 if not iter_idx % mod_val:
Rich Lane9a003812012-10-04 17:17:59 -07001789 logging.info("Flow Toggle: iter %d of %d. " %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001790 (iter_idx, iter_count) +
1791 "%d updates in %d secs" %
1792 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001793 for toggle in range(2):
1794 t_idx = 1 - toggle
1795 for f_idx in range(flow_count):
Rich Lane5c3151c2013-01-03 17:15:41 -08001796 self.controller.message_send(flows[t_idx][f_idx])
Dan Talaycofa6454f2012-04-05 10:04:13 -07001797 updates += 1
Rich Lane3a261d52013-01-03 17:45:08 -08001798 do_barrier(self.controller)
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001799
1800 end = time.time()
1801 divisor = end - start or (end - start + 1)
Rich Lane9a003812012-10-04 17:17:59 -07001802 logging.info("Flow toggle: %d iterations" % iter_count)
1803 logging.info(" %d flow mods in %d secs, %d mods/sec" %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001804 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001805
1806
Dan Talayco8a64e332012-03-28 14:53:20 -07001807# You can pick and choose these by commenting tests in or out
1808iter_classes = [
1809 basic.PacketIn,
1810 basic.PacketOut,
1811 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001812 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001813 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001814 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001815 AllWildcardMatch,
1816 AllWildcardMatchTagged,
1817 SingleWildcardMatch,
1818 SingleWildcardMatchTagged,
1819 ExactMatch,
1820 ExactMatchTagged,
1821 SingleWildcardMatch,
1822 ModifyL2Src,
1823 ModifyL2Dst,
1824 ModifyL2SrcMC,
1825 ModifyL2DstMC,
1826 ModifyL2SrcDstMC
1827 ]
1828
Rich Lane0a4f6372013-01-02 14:40:22 -08001829@disabled
Dan Talayco8a64e332012-03-28 14:53:20 -07001830class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001831 """
1832 Iterate over a bunch of test cases
1833
1834 The cases come from the list above
1835 """
1836
Dan Talayco8a64e332012-03-28 14:53:20 -07001837 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001838 count = test_param_get('iter_count', default=10)
Dan Talayco8a64e332012-03-28 14:53:20 -07001839 tests_done = 0
Rich Lane9a003812012-10-04 17:17:59 -07001840 logging.info("Running iteration test " + str(count) + " times")
Dan Talayco8a64e332012-03-28 14:53:20 -07001841 start = time.time()
1842 last = start
1843 for idx in range(count):
Rich Lane9a003812012-10-04 17:17:59 -07001844 logging.info("Iteration " + str(idx + 1))
Dan Talayco8a64e332012-03-28 14:53:20 -07001845 for cls in iter_classes:
1846 test = cls()
1847 test.inheritSetup(self)
1848 test.runTest()
1849 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001850 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001851 if time.time() - last > 60:
1852 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001853 logging.info(
Dan Talaycofa6454f2012-04-05 10:04:13 -07001854 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1855 (idx, count, tests_done, last - start) +
1856 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001857 stats = all_stats_get(self)
1858 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001859 logging.info("\nIterCases ran %d tests in %d seconds." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001860 (tests_done, last - start))
Rich Lane9a003812012-10-04 17:17:59 -07001861 logging.info(" flows: %d. packets: %d. bytes: %d" %
Dan Talayco8a64e332012-03-28 14:53:20 -07001862 (stats["flows"], stats["packets"], stats["bytes"]))
Rich Lane9a003812012-10-04 17:17:59 -07001863 logging.info(" active: %d. lookups: %d. matched %d." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001864 (stats["active"], stats["lookups"], stats["matched"]))
1865
Dan Talayco4b2bee62010-07-20 14:10:05 -07001866#@todo Need to implement tagged versions of the above tests
1867#
1868#@todo Implement a test case that strips tag 2, adds tag 3
1869# and modifies tag 4 to tag 5. Then verify (in addition) that
1870# tag 6 does not get modified.
1871
Rich Lane0a4f6372013-01-02 14:40:22 -08001872@disabled
Dan Talayco4b2bee62010-07-20 14:10:05 -07001873class MixedVLAN(BaseMatchCase):
1874 """
1875 Test mixture of VLAN tag actions
1876
1877 Strip tag 2 on port 1, send to port 2
1878 Add tag 3 on port 1, send to port 2
1879 Modify tag 4 to 5 on port 1, send to port 2
1880 All other traffic from port 1, send to port 3
1881 All traffic from port 2 sent to port 4
1882 Use exact matches with different packets for all mods
1883 Verify the following: (port, vid)
1884 (port 1, vid 2) => VLAN tag stripped, out port 2
1885 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1886 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1887 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1888 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1889 (port 2, no tag) => untagged packet out port 4
1890 (port 2, vid 2-6) => unmodified packet out port 4
1891
1892 Variation: Might try sending VID 5 to port 3 and check.
1893 If only VID 5 distinguishes pkt, this will fail on some platforms
1894 """
1895
Rich Lane97e99652013-01-02 17:23:20 -08001896@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -07001897class MatchEach(base_tests.SimpleDataPlane):
Rich Lane8d6ab272012-09-23 18:06:20 -07001898 """
1899 Check that each match field is actually matched on.
1900 Installs two flows that differ in one field. The flow that should not
1901 match has a higher priority, so if that field is ignored during matching
1902 the packet will be sent out the wrong port.
1903
1904 TODO test UDP, ARP, ICMP, etc.
1905 """
1906 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001907 of_ports = config["port_map"].keys()
Rich Lane8d6ab272012-09-23 18:06:20 -07001908 of_ports.sort()
1909 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1910
Rich Lane9a003812012-10-04 17:17:59 -07001911 delete_all_flows(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001912
Ed Swierk7040a8d2012-12-11 16:30:13 -08001913 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=2)
Rich Lane8d6ab272012-09-23 18:06:20 -07001914 ingress_port = of_ports[0]
1915 egress_port = of_ports[1]
1916
1917 def testField(field, mask):
Rich Lane9a003812012-10-04 17:17:59 -07001918 logging.info("Testing field %s" % field)
Rich Lane8d6ab272012-09-23 18:06:20 -07001919
1920 def addFlow(matching, priority, output_port):
1921 match = packet_to_flow_match(self, pkt)
1922 self.assertTrue(match is not None, "Could not generate flow match from pkt")
1923 match.wildcards &= ~ofp.OFPFW_IN_PORT
1924 match.in_port = ingress_port
1925 if not matching:
1926 # Make sure flow doesn't match
1927 orig = getattr(match, field)
1928 if isinstance(orig, list):
1929 new = map(lambda a: ~a[0] & a[1], zip(orig, mask))
1930 else:
1931 new = ~orig & mask
1932 setattr(match, field, new)
Rich Lane28fa9272013-03-08 16:00:25 -08001933 request = ofp.message.flow_mod()
Rich Lane8d6ab272012-09-23 18:06:20 -07001934 request.match = match
1935 request.buffer_id = 0xffffffff
1936 request.priority = priority
Rich Lane9d3cc6b2013-03-08 16:33:08 -08001937 act = ofp.action.output()
Rich Lane8d6ab272012-09-23 18:06:20 -07001938 act.port = output_port
Rich Lanec495d9e2013-03-08 17:43:36 -08001939 request.actions.append(act)
Rich Lane9a003812012-10-04 17:17:59 -07001940 logging.info("Inserting flow")
Rich Lane8d6ab272012-09-23 18:06:20 -07001941 self.controller.message_send(request)
1942
1943 # This flow should match.
1944 addFlow(matching=True, priority=0, output_port=egress_port)
1945 # This flow should not match, but it has a higher priority.
1946 addFlow(matching=False, priority=1, output_port=ofp.OFPP_IN_PORT)
1947
Rich Lane3a261d52013-01-03 17:45:08 -08001948 do_barrier(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001949
Rich Lane9a003812012-10-04 17:17:59 -07001950 logging.info("Sending packet to dp port " + str(ingress_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001951 self.dataplane.send(ingress_port, str(pkt))
1952
1953 exp_pkt_arg = None
1954 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -07001955 if config["relax"]:
Rich Lane8d6ab272012-09-23 18:06:20 -07001956 exp_pkt_arg = pkt
1957 exp_port = egress_port
1958
1959 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
1960 exp_pkt=exp_pkt_arg)
1961 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -07001962 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001963 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
1964 self.assertEqual(str(pkt), str(rcv_pkt), 'Response packet does not match send packet')
1965
Ed Swierkb603b192012-12-12 15:38:49 -08001966 wildcards = required_wildcards(self)
Rich Lane8d6ab272012-09-23 18:06:20 -07001967 # TODO in_port
Ed Swierkb603b192012-12-12 15:38:49 -08001968 if not (wildcards & ofp.OFPFW_DL_SRC):
1969 testField("dl_src", [0xff]*6)
1970 if not (wildcards & ofp.OFPFW_DL_DST):
1971 testField("dl_dst", [0xff]*6)
1972 if not (wildcards & ofp.OFPFW_DL_TYPE):
1973 testField("dl_type", 0xffff)
1974 if not (wildcards & ofp.OFPFW_DL_VLAN):
1975 testField("dl_vlan", 0xfff)
Rich Lane8d6ab272012-09-23 18:06:20 -07001976 # TODO dl_vlan_pcp
Ed Swierkb603b192012-12-12 15:38:49 -08001977 if not (wildcards & ofp.OFPFW_NW_SRC_ALL):
1978 testField("nw_src", 0xffffffff)
1979 if not (wildcards & ofp.OFPFW_NW_DST_ALL):
1980 testField("nw_dst", 0xffffffff)
1981 if not (wildcards & ofp.OFPFW_NW_TOS):
1982 testField("nw_tos", 0x3f)
1983 if not (wildcards & ofp.OFPFW_NW_PROTO):
1984 testField("nw_proto", 0xff)
1985 if not (wildcards & ofp.OFPFW_TP_SRC):
1986 testField("tp_src", 0xffff)
1987 if not (wildcards & ofp.OFPFW_TP_DST):
1988 testField("tp_dst", 0xffff)
Rich Lane8d6ab272012-09-23 18:06:20 -07001989
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07001990class DirectBadPacketBase(base_tests.SimpleDataPlane):
1991 """
1992 Base class for sending single packets with single flow table entries.
1993 Used to verify matching of unusual packets and parsing/matching of
1994 corrupted packets.
1995
1996 The idea is to generate packets that may either be totally malformed or
1997 malformed just enough to trick the flow matcher into making mistakes.
1998
1999 Generate a 'bad' packet
2000 Generate and install a matching flow
2001 Add action to direct the packet to an egress port
2002 Send the packet to ingress dataplane port
2003 Verify the packet is received at the egress port only
2004 """
2005
2006 RESULT_MATCH = "MATCH"
2007 RESULT_NOMATCH = "NO MATCH"
2008 RESULT_ANY = "ANY MATCH"
2009
2010 def runTest(self):
2011 pass
2012 # TODO:
2013 # - ICMP?
2014 # - VLAN?
2015 # - action
2016
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002017 def createMatch(self, **kwargs):
2018 match = ofp.ofp_match()
2019 match.wildcards = ofp.OFPFW_ALL
2020 fields = {
2021 'dl_dst': ofp.OFPFW_DL_DST,
2022 'dl_src': ofp.OFPFW_DL_SRC,
2023 'dl_type': ofp.OFPFW_DL_TYPE,
2024 'dl_vlan': ofp.OFPFW_DL_VLAN,
2025 'nw_src': ofp.OFPFW_NW_SRC_MASK,
2026 'nw_dst': ofp.OFPFW_NW_DST_MASK,
2027 'nw_tos': ofp.OFPFW_NW_TOS,
2028 'nw_proto': ofp.OFPFW_NW_PROTO,
2029 'tp_src': ofp.OFPFW_TP_SRC,
2030 'tp_dst': ofp.OFPFW_TP_DST,
2031 }
2032 for key in kwargs:
2033 setattr(match, key, kwargs[key])
2034 match.wildcards &= ~fields[key]
2035 return match
2036
2037 def testPktsAgainstFlow(self, pkts, acts, match):
2038 if type(acts) != list:
2039 acts = [acts]
2040 for info in pkts:
2041 title, pkt, expected_result = info
2042 self.testPktAgainstFlow(title, pkt, acts, match, expected_result)
2043
2044 def testPktAgainstFlow(self, title, pkt, acts, match, expected_result):
2045 of_ports = config["port_map"].keys()
2046 of_ports.sort()
2047 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
2048
Rich Lane32bf9482013-01-03 17:26:30 -08002049 delete_all_flows(self.controller)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002050
2051 ingress_port = of_ports[0]
2052 egress_port = of_ports[1]
2053
2054 logging.info("Testing packet '%s', expect result %s" %
2055 (title, expected_result))
2056 logging.info("Ingress %s to egress %s" %
2057 (str(ingress_port), str(egress_port)))
2058 logging.info("Packet:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002059 logging.info(inspect_packet(pkt))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002060
2061 match.in_port = ingress_port
2062
Rich Lane28fa9272013-03-08 16:00:25 -08002063 request = ofp.message.flow_mod()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002064 request.match = match
Rich Lane44cf12d2012-10-15 11:10:45 -07002065 request.priority = 1
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002066
2067 request.buffer_id = 0xffffffff
2068 for act in acts:
2069 act.port = egress_port
Rich Lanec495d9e2013-03-08 17:43:36 -08002070 request.actions.append(act)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002071
2072 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08002073 self.controller.message_send(request)
Rich Lane44cf12d2012-10-15 11:10:45 -07002074
2075 # This flow speeds up negative tests
2076 logging.info("Inserting catch-all flow")
Rich Lane28fa9272013-03-08 16:00:25 -08002077 request2 = ofp.message.flow_mod()
Rich Lane44cf12d2012-10-15 11:10:45 -07002078 request2.match = self.createMatch()
Dan Talayco3bfc8222013-02-13 18:18:57 -08002079 request2.match.wildcards &= ~ofp.OFPFW_IN_PORT
2080 request2.match.in_port = ingress_port
2081
Rich Lane44cf12d2012-10-15 11:10:45 -07002082 request2.priority = 0
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002083 act = ofp.action.output()
Rich Lane44cf12d2012-10-15 11:10:45 -07002084 act.port = ofp.OFPP_IN_PORT
Rich Lanec495d9e2013-03-08 17:43:36 -08002085 request2.actions.append(act)
Rich Lane5c3151c2013-01-03 17:15:41 -08002086 self.controller.message_send(request2)
Rich Lane44cf12d2012-10-15 11:10:45 -07002087
Rich Lane3a261d52013-01-03 17:45:08 -08002088 do_barrier(self.controller)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002089
Dan Talayco3bfc8222013-02-13 18:18:57 -08002090 pkt_str = str(pkt)
2091 if config["minsize"] > len(str(pkt)):
2092 pkt_str += '0' * (config["minsize"] - len(str(pkt)))
2093
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002094 logging.info("Sending packet to dp port " +
2095 str(ingress_port))
Dan Talayco3bfc8222013-02-13 18:18:57 -08002096 self.dataplane.send(ingress_port, pkt_str)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002097
2098 exp_pkt_arg = None
2099 exp_port = None
2100 if config["relax"]:
2101 exp_pkt_arg = pkt
2102 exp_port = egress_port
2103
Rich Lane44cf12d2012-10-15 11:10:45 -07002104 if expected_result == self.RESULT_MATCH:
2105 timeout = -1 # default timeout
2106 else:
2107 timeout = 1 # short timeout for negative tests
2108
2109 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(exp_pkt=exp_pkt_arg,
2110 timeout=timeout)
2111 if rcv_port == ingress_port:
2112 logging.debug("Packet matched catch-all flow")
2113 rcv_pkt = None
2114
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002115 if expected_result == self.RESULT_MATCH:
2116 self.assertTrue(rcv_pkt is not None,
2117 "Did not receive packet, expected a match")
2118 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
2119 str(rcv_port))
2120 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
2121 str_pkt = str(pkt)
2122 str_rcv_pkt = str(rcv_pkt)
2123 str_rcv_pkt = str_rcv_pkt[0:len(str_pkt)]
2124 if str_pkt != str_rcv_pkt:
2125 logging.error("Response packet does not match send packet")
2126 logging.info("Response:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002127 logging.info(inspect_packet(scapy.Ether(rcv_pkt)))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002128 self.assertEqual(str_pkt, str_rcv_pkt,
2129 'Response packet does not match send packet')
2130 elif expected_result == self.RESULT_NOMATCH:
2131 self.assertTrue(rcv_pkt is None, "Received packet, expected drop")
2132 else:
2133 logging.debug("Match or drop accepted. Result = %s" %
2134 ("match" if rcv_pkt is not None else "drop"))
2135
2136
2137class DirectBadIpTcpPacketsBase(DirectBadPacketBase):
2138 """
2139 Base class for TCP and UDP parsing/matching verification under corruptions
2140 """
2141 def runTest(self):
2142 pass
2143
2144 def runTestWithProto(self, protoName = 'TCP'):
2145 dl_dst='00:01:02:03:04:05'
2146 dl_src='00:06:07:08:09:0a'
2147 ip_src='192.168.0.1'
2148 ip_dst='192.168.0.2'
2149 ip_tos=0
2150 tcp_sport=1234
2151 tcp_dport=80
2152
2153 # Generate a proper packet for constructing a match
2154 tp = None
2155 if protoName == 'TCP':
2156 tp = scapy.TCP
2157 proto = 6
2158 elif protoName == 'UDP':
2159 tp = scapy.UDP
2160 proto = 17
2161 else:
2162 raise Exception("Passed in unknown proto name")
2163
2164 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
2165 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2166 tp(sport=tcp_sport, dport=tcp_dport)
2167 match = packet_to_flow_match(self, match_pkt)
2168 self.assertTrue(match is not None,
2169 "Could not generate flow match from pkt")
2170 match.wildcards &= ~ofp.OFPFW_IN_PORT
2171
2172 def testPacket(title, pkt, result):
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002173 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002174 pkts = [
2175 [title, pkt, result]
2176 ]
2177 self.testPktsAgainstFlow(pkts, act, match)
2178
2179 # Try incomplete IP headers
2180 testPacket("Incomplete IP header (1 bytes)",
2181 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2182 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:1],
2183 self.RESULT_NOMATCH,
2184 )
2185 testPacket("Incomplete IP header (2 bytes)",
2186 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2187 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:2],
2188 self.RESULT_NOMATCH,
2189 )
2190 testPacket("Incomplete IP header (3 bytes)",
2191 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2192 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:3],
2193 self.RESULT_NOMATCH,
2194 )
2195 testPacket("Incomplete IP header (12 bytes)",
2196 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2197 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:12],
2198 self.RESULT_NOMATCH,
2199 )
2200 testPacket("Incomplete IP header (16 bytes)",
2201 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2202 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:16],
2203 self.RESULT_NOMATCH,
2204 )
2205 testPacket("Incomplete IP header (19 bytes)",
2206 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2207 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:19],
2208 self.RESULT_NOMATCH,
2209 )
2210
2211 # Try variations where the TCP header is missing or incomplete. As we
2212 # saw bugs before where buffers were reused and lengths weren't honored,
2213 # we initiatlize once with a non-matching full packet and once with a
2214 # matching full packet.
2215 testPacket("Non-Matching TCP packet, warming buffer",
2216 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2217 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2218 tp(sport=tcp_sport, dport=tcp_dport + 1),
2219 self.RESULT_NOMATCH,
2220 )
2221 testPacket("Missing TCP header, buffer warmed with non-match",
2222 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2223 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2224 self.RESULT_NOMATCH,
2225 )
2226 testPacket("Matching TCP packet, warming buffer",
2227 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2228 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2229 tp(sport=tcp_sport, dport=tcp_dport),
2230 self.RESULT_MATCH,
2231 )
2232 testPacket("Missing TCP header, buffer warmed with match",
2233 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2234 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2235 self.RESULT_NOMATCH,
2236 )
2237 testPacket("Truncated TCP header: 2 bytes",
2238 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2239 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2240 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:2]),
2241 self.RESULT_NOMATCH,
2242 )
2243
2244 # Play with IP header length values that put the start of TCP either
2245 # inside the generated TCP header or beyond. In some cases it may even
2246 # be beyond the packet boundary. Also play with IP options and more
2247 # importantly IP total length corruptions.
2248 testPacket("TCP packet, corrupt ihl (0x6)",
2249 simple_tcp_packet(ip_ihl=6),
2250 self.RESULT_NOMATCH,
2251 )
2252 testPacket("TCP packet, corrupt ihl (0xf)",
2253 simple_tcp_packet(ip_ihl=0xf), # ihl = 15 * 4 = 60
2254 self.RESULT_NOMATCH,
2255 )
2256 testPacket("TCP packet, corrupt ihl and total length",
2257 simple_tcp_packet(ip_ihl=0xf, pktlen=56), # ihl = 15 * 4 = 60,
2258 self.RESULT_NOMATCH,
2259 )
2260 testPacket("Corrupt IPoption: First 4 bytes of matching TCP header",
2261 simple_tcp_packet(
2262 ip_options=scapy.IPOption('\x04\xd2\x00\x50'),
2263 tcp_dport=2, tcp_sport=2
2264 ),
2265 self.RESULT_NOMATCH,
2266 )
2267 testPacket("Missing TCP header, corrupt ihl",
2268 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2269 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto),
2270 self.RESULT_NOMATCH,
2271 )
2272 testPacket("Missing TCP header, corrupt total length",
2273 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2274 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, len= 100),
2275 self.RESULT_NOMATCH,
2276 )
2277 testPacket("Missing TCP header, corrupt ihl and total length",
2278 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2279 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto, len=43),
2280 self.RESULT_NOMATCH,
2281 )
2282 testPacket("Incomplete IP header (12 bytes), corrupt ihl and total length",
2283 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2284 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:12],
2285 self.RESULT_NOMATCH,
2286 )
2287 testPacket("Incomplete IP header (16 bytes), corrupt ihl and total length",
2288 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2289 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:16],
2290 self.RESULT_NOMATCH,
2291 )
2292
2293 # Try an incomplete TCP header that has enough bytes to carry source and
2294 # destination ports. As that is all we care about during matching, some
2295 # implementations may match and some may drop the packet
2296 testPacket("Incomplete TCP header: src/dst port present",
2297 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2298 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2299 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:4]),
2300 self.RESULT_ANY,
2301 )
2302
2303 for i in range(1):
2304 for length in range(40 / 4): # IPv4 options are a maximum of 40 in length
2305 bytes = "".join([("%c" % random.randint(0, 255)) for x in range(length * 4)])
2306 eth = scapy.Ether(dst=dl_dst, src=dl_src)
2307 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2308 tcp = tp(sport=tcp_sport, dport=tcp_dport+1)
2309 pkt = eth / ip
2310 pkt = pkt / bytes
2311 pkt = pkt / str(tcp)
2312 testPacket("Random IP options len = %d - TP match must fail" % length * 4,
2313 pkt,
2314 self.RESULT_NOMATCH
2315 )
2316
2317 eth = scapy.Ether(dst=dl_dst, src=dl_src)
2318 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2319 tcp = tp(sport=tcp_sport, dport=tcp_dport)
2320 pkt = eth / ip
2321 pkt = pkt / bytes
2322 pkt = pkt / str(tcp)
2323
2324 testPacket("Random IP options len = %d - May match",
2325 pkt,
2326 self.RESULT_ANY
2327 )
2328
2329
2330class DirectBadIpTcpPackets(DirectBadIpTcpPacketsBase):
2331 """
2332 Verify IP/TCP parsing and matching. Focus on packet corruptions
2333 """
2334 def runTest(self):
2335 self.runTestWithProto(protoName = 'TCP')
2336
2337class DirectBadIpUdpPackets(DirectBadIpTcpPacketsBase):
2338 """
2339 Verify IP/UDP parsing and matching. Focus on packet corruptions
2340 """
2341 def runTest(self):
2342 self.runTestWithProto(protoName = 'UDP')
2343
2344class DirectBadLlcPackets(DirectBadPacketBase):
2345 """
2346 Verify LLC/SNAP parsing and matching. Focus on packet corruptions
2347 """
2348 def runTest(self):
2349 dl_dst='00:01:02:03:04:05'
2350 dl_src='00:06:07:08:09:0a'
2351 ip_src='192.168.0.1'
2352 ip_dst='192.168.0.2'
2353 ip_tos=0
2354 tcp_sport=1234
2355 tcp_dport=80
2356
2357 IS_SNAP_IP = 1
2358 IS_SNAP_IP_CORRUPT = 2
2359 IS_NOT_SNAP_IP = 3
2360
2361 def testPacketTcpMatch(title, llc):
2362 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
2363 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2364 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
2365 match = packet_to_flow_match(self, match_pkt)
2366 self.assertTrue(match is not None,
2367 "Could not generate flow match from pkt")
2368 match.wildcards &= ~ofp.OFPFW_IN_PORT
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002369 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002370
2371 self.testPktsAgainstFlow(
2372 [[
2373 "TCP match - LLC frame correct length - %s" % title,
2374 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2375 self.RESULT_ANY,
2376 ]],
2377 act, match
2378 )
2379
2380 # Corrupt length field
2381 ethLen = random.randint(0, 1535)
2382 self.testPktsAgainstFlow(
2383 [[
2384 "TCP match - LLC frame corrupted length - %s" % title,
2385 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
2386 self.RESULT_ANY,
2387 ]],
2388 act, match
2389 )
2390
2391 def testPacketEthSrcDstMatch(title, llc):
2392 # Matching based on Ethernet source and destination
2393 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)
2394 match = packet_to_flow_match(self, match_pkt)
2395 self.assertTrue(match is not None,
2396 "Could not generate flow match from pkt")
2397 match.wildcards &= ~ofp.OFPFW_IN_PORT
2398 match.wildcards |= ofp.OFPFW_DL_TYPE
2399 self.testPktsAgainstFlow(
2400 [[
2401 "Eth addr match - LLC frame correct length- %s" % title,
2402 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2403 self.RESULT_MATCH,
2404 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002405 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002406 )
2407
2408 # Corrupt length field
2409 ethLen = random.randint(0, 1535)
2410 self.testPktsAgainstFlow(
2411 [[
2412 "Eth addr match - LLC frame corrupted length- %s" % title,
2413 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
2414 self.RESULT_ANY,
2415 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002416 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002417 )
2418
2419 def testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip):
2420 # Matching based on Ethernet source, destination and type
2421 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src, type=0x800)
2422 match = packet_to_flow_match(self, match_pkt)
2423 self.assertTrue(match is not None,
2424 "Could not generate flow match from pkt")
2425 match.wildcards &= ~ofp.OFPFW_IN_PORT
2426 if is_snap_ip == IS_SNAP_IP:
2427 is_match = self.RESULT_MATCH
2428 elif is_snap_ip == IS_SNAP_IP_CORRUPT:
2429 is_match = self.RESULT_ANY
2430 else:
2431 is_match = self.RESULT_NOMATCH
2432 self.testPktsAgainstFlow(
2433 [[
2434 "Eth addr+type match - LLC frame correct length - %s" % title,
2435 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2436 is_match,
2437 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002438 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002439 )
2440
2441 # Corrupt length field
2442 ethLen = random.randint(0, 1535)
2443 self.testPktsAgainstFlow(
2444 [[
2445 "Eth addr+type match - LLC frame corrupted length - %s" % title,
2446 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
Christian Dickmanne9b6d252012-10-08 22:56:50 -07002447 self.RESULT_ANY,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002448 ]],
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002449 ofp.action.output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002450 )
2451
2452 def testPacket(title, llc, is_snap_ip):
2453 testPacketTcpMatch(title, llc)
2454 testPacketEthSrcDstMatch(title, llc)
2455 testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip)
2456
2457 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002458 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002459 IS_NOT_SNAP_IP,
2460 )
2461 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002462 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002463 IS_NOT_SNAP_IP,
2464 )
2465 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002466 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002467 IS_NOT_SNAP_IP,
2468 )
2469 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002470 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002471 IS_NOT_SNAP_IP,
2472 )
2473 testPacket("LLC - SNAP - Small bogus payload",
2474 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2475 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2476 IS_SNAP_IP_CORRUPT,
2477 )
2478 testPacket("LLC - SNAP - Max -1 bogus payload",
2479 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2480 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2481 IS_NOT_SNAP_IP,
2482 )
2483 testPacket("LLC - SNAP - Max bogus payload",
2484 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2485 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2486 IS_NOT_SNAP_IP,
2487 )
2488 testPacket("LLC - SNAP - IP - TCP",
2489 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2490 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2491 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2492 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2493 IS_SNAP_IP,
2494 )
2495
2496
2497class DirectLlcPackets(DirectBadPacketBase):
2498 """
2499 Verify LLC/SNAP parsing (valid and corrupted packets) and matching
2500 """
2501 def runTest(self):
2502 dl_dst='00:01:02:03:04:05'
2503 dl_src='00:06:07:08:09:0a'
2504 ip_src='192.168.0.1'
2505 ip_dst='192.168.0.2'
2506 ip_tos=0
2507 tcp_sport=1234
2508 tcp_dport=80
2509
2510 # Test ethertype in face of LLC/SNAP and OFP_DL_TYPE_NOT_ETH_TYPE
2511 IS_SNAP_NOT_IP = 1
2512 IS_SNAP_AND_IP = 2
2513 IS_NOT_SNAP = 3
2514
2515 def testPacketEthTypeIP(title, llc, is_snap):
2516 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src, type=0x800)
2517 match = packet_to_flow_match(self, match_pkt)
2518 self.assertTrue(match is not None,
2519 "Could not generate flow match from pkt")
2520 match.wildcards &= ~ofp.OFPFW_IN_PORT
2521 pkts = []
2522 if is_snap == IS_NOT_SNAP or is_snap == IS_SNAP_NOT_IP:
2523 result = self.RESULT_NOMATCH
2524 else:
2525 result = self.RESULT_MATCH
2526 pkts.append([
2527 "Ether type 0x800 match - %s" % title,
2528 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2529 result,
2530 ])
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002531 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002532 self.testPktsAgainstFlow(pkts, act, match)
2533
2534 def testPacketEthTypeNotEth(title, llc, is_snap):
2535 match_pkt = scapy.Ether(dst = dl_dst, src = dl_src,
2536 type = ofp.OFP_DL_TYPE_NOT_ETH_TYPE)
2537 match = packet_to_flow_match(self, match_pkt)
2538 self.assertTrue(match is not None,
2539 "Could not generate flow match from pkt")
2540 match.wildcards &= ~ofp.OFPFW_IN_PORT
2541 pkts = []
2542 if is_snap == IS_NOT_SNAP:
2543 result = self.RESULT_MATCH
2544 else:
2545 result = self.RESULT_NOMATCH
2546 pkts.append([
2547 "Ether type OFP_DL_TYPE_NOT_ETH_TYPE match - %s" % title,
2548 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2549 result,
2550 ])
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002551 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002552 self.testPktsAgainstFlow(pkts, act, match)
2553
2554 def testPacket(title, llc, is_snap):
2555 testPacketEthTypeIP(title, llc, is_snap)
2556 testPacketEthTypeNotEth(title, llc, is_snap)
2557
2558 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002559 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
2560 IS_NOT_SNAP,
2561 )
2562 testPacket("LLC (with information field) - No SNAP - No Payload",
2563 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x12) / "S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002564 IS_NOT_SNAP,
2565 )
2566 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002567 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002568 IS_NOT_SNAP,
2569 )
2570 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002571 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002572 IS_NOT_SNAP,
2573 )
2574 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002575 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002576 IS_NOT_SNAP,
2577 )
2578 testPacket("LLC - SNAP - Non-default OUI",
2579 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2580 scapy.SNAP(OUI=0x000001, code=0x800) / ("S" * 10),
2581 IS_NOT_SNAP,
2582 )
2583 testPacket("LLC - SNAP - Default OUI",
2584 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2585 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2586 IS_SNAP_AND_IP,
2587 )
2588 testPacket("LLC - SNAP - Max -1 bogus payload",
2589 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2590 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2591 IS_SNAP_NOT_IP,
2592 )
2593 testPacket("LLC - SNAP - Max bogus payload",
2594 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2595 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2596 IS_SNAP_NOT_IP,
2597 )
2598 testPacket("LLC - SNAP - IP - TCP",
2599 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2600 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2601 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2602 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2603 IS_SNAP_AND_IP,
2604 )
2605
2606
2607class DirectArpPackets(DirectBadPacketBase):
2608 """
2609 Verify ARP parsing (valid and corrupted packets) and ARP matching
2610 """
2611 def runTest(self):
2612 self.testArpHandling()
2613
2614 def testArpHandling(self):
2615 dl_dst='00:01:02:03:04:05'
2616 dl_src='00:06:07:08:09:0a'
2617 ip_src='192.168.0.1'
2618 ip_dst='192.168.0.2'
2619 ip_src2='192.168.1.1'
2620 ip_dst2='192.168.1.2'
2621 ip_tos=0
2622 tcp_sport=1234
2623 tcp_dport=80
2624
2625 def testPacket(title, arp_match, arp_pkt, result):
2626 pkts = []
2627
2628 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src) / arp_match
2629 match = packet_to_flow_match(self, match_pkt)
2630 self.assertTrue(match is not None,
2631 "Could not generate flow match from pkt")
2632 match.wildcards &= ~ofp.OFPFW_IN_PORT
2633
2634 pkts.append([
2635 title,
2636 scapy.Ether(dst=dl_dst, src=dl_src) / arp_pkt,
2637 result,
2638 ])
2639
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002640 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002641 self.testPktsAgainstFlow(pkts, act, match)
2642
2643 testPacket("Basic ARP",
2644 scapy.ARP(psrc=ip_src, pdst=ip_dst, op = 1),
2645 scapy.ARP(hwdst = '00:00:00:00:00:00', hwsrc = dl_src,
2646 psrc = ip_src, pdst = ip_dst, hwlen = 6, plen = 4,
2647 ptype = 0x800, hwtype = 1, op = 1),
2648 self.RESULT_MATCH
2649 )
2650 # More stuff:
2651 # - Non matches on any property
2652 # - Corrupted hwlen and plen
2653 # - Other hwtype, ptype
2654 # - Truncated ARP pkt
2655
2656
2657class DirectVlanPackets(DirectBadPacketBase):
2658 """
2659 Verify VLAN parsing (valid and corrupted packets) and ARP matching
2660 """
2661 def runTest(self):
2662 dl_dst='00:01:02:03:04:05'
2663 dl_src='00:06:07:08:09:0a'
2664 ip_src='192.168.0.1'
2665 ip_dst='192.168.0.2'
2666 ip_src2='192.168.1.1'
2667 ip_dst2='192.168.1.2'
2668 ip_tos=0
2669 tcp_sport=1234
2670 tcp_dport=80
2671
2672 def testPacket(title, match, pkt, result):
2673 pkts = []
2674
2675 self.assertTrue(match is not None,
2676 "Could not generate flow match from pkt")
2677 match.wildcards &= ~ofp.OFPFW_IN_PORT
2678
2679 pkts.append([
2680 "%s" % title,
2681 pkt,
2682 result,
2683 ])
2684
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002685 act = ofp.action.output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002686 self.testPktsAgainstFlow(pkts, act, match)
2687
2688 testPacket("Basic MAC matching - IPv4 payload",
2689 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2690 scapy.Ether(dst=dl_dst, src=dl_src, type=0x800) / scapy.IP(),
2691 self.RESULT_MATCH
2692 )
2693 testPacket("Basic MAC matching - VMware beacon - no payload",
2694 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2695 scapy.Ether(dst=dl_dst, src=dl_src, type=0x8922),
2696 self.RESULT_MATCH
2697 )
2698 testPacket("Basic MAC matching - VMware beacon - with payload",
2699 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2700 scapy.Ether(dst=dl_dst, src=dl_src, type=0x8922)/ ("X" * 1),
2701 self.RESULT_MATCH
2702 )
2703 testPacket("Basic MAC matching - IPv6 payload",
2704 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2705 scapy.Ether(dst=dl_dst, src=dl_src) / scapy.IPv6(),
2706 self.RESULT_MATCH
2707 )
2708 testPacket("Basic MAC matching with VLAN tag present",
2709 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2710 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002711 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002712 scapy.IP(),
2713 self.RESULT_MATCH
2714 )
2715 testPacket("Basic MAC matching with VLAN tag present",
2716 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2717 dl_type=0x800),
2718 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002719 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002720 scapy.IP(),
2721 self.RESULT_MATCH
2722 )
2723 testPacket("Ether matching with VLAN tag present - No type match",
2724 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2725 dl_type=0x801),
2726 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002727 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002728 scapy.IP(),
2729 self.RESULT_NOMATCH
2730 )
2731 testPacket("Ether matching with VLAN tag present - No type match 0x8100",
2732 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2733 dl_type=0x8100),
2734 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002735 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002736 scapy.IP(),
2737 self.RESULT_NOMATCH
2738 )
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002739 testPacket("IP matching - VLAN tag",
2740 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2741 dl_type=0x0800,
2742 nw_src=parse_ip(ip_src), nw_dst=parse_ip(ip_dst)),
2743 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2744 scapy.Dot1Q(prio=5, vlan=1000)/ \
2745 scapy.IP(src=ip_src, dst=ip_dst),
2746 self.RESULT_MATCH
2747 )
2748 # XXX:
2749 # - Matching on VLAN ID and Prio
2750 # - Actions
2751
2752@nonstandard
2753class DirectVlanPacketsDoubleTagged(DirectVlanPackets):
2754 """
2755 VLAN parsing for double tagged packets. Spec is ambiguous about
2756 the treatment of these cases, so broken out to be non-standard
2757 """
2758 def runTest(self):
2759 dl_dst='00:01:02:03:04:05'
2760 dl_src='00:06:07:08:09:0a'
2761 ip_src='192.168.0.1'
2762 ip_dst='192.168.0.2'
2763 ip_src2='192.168.1.1'
2764 ip_dst2='192.168.1.2'
2765 ip_tos=0
2766 tcp_sport=1234
2767 tcp_dport=80
2768
2769 def testPacket(title, match, pkt, result):
2770 pkts = []
2771
2772 self.assertTrue(match is not None,
2773 "Could not generate flow match from pkt")
2774 match.wildcards &= ~ofp.OFPFW_IN_PORT
2775
2776 pkts.append([
2777 "%s" % title,
2778 pkt,
2779 result,
2780 ])
2781
Rich Lane9d3cc6b2013-03-08 16:33:08 -08002782 act = ofp.action.output()
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002783 self.testPktsAgainstFlow(pkts, act, match)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002784 testPacket("Ether matching with double VLAN tag - Wrong type match",
2785 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2786 dl_type=0x800),
2787 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002788 scapy.Dot1Q(prio=5, vlan=1000)/ \
2789 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002790 scapy.IP(),
2791 self.RESULT_NOMATCH
2792 )
2793 testPacket("Ether matching with double VLAN tag - Type match",
2794 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2795 dl_type=0x8100),
2796 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002797 scapy.Dot1Q(prio=5, vlan=1000)/ \
2798 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002799 scapy.IP(),
2800 self.RESULT_MATCH
2801 )
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002802
2803
2804
Dan Talayco9f47f4d2010-06-03 13:54:37 -07002805if __name__ == "__main__":
2806 print "Please run through oft script: ./oft --test_spec=basic"