blob: 940729257c1ef0fb515221dc7e2d6b2032191e69 [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 Lane28fa9272013-03-08 16:00:25 -0800107 act = ofp.action.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 Lanee30455b2013-01-03 16:24:44 -0800124 request.actions.add(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 Lane28fa9272013-03-08 16:00:25 -0800176 act = ofp.action.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 Lanee30455b2013-01-03 16:24:44 -0800189 request.actions.add(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 Lane28fa9272013-03-08 16:00:25 -0800254 act = ofp.action.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 Lanee30455b2013-01-03 16:24:44 -0800276 request.actions.add(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 Lane28fa9272013-03-08 16:00:25 -0800379 act = ofp.action.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 Lanee30455b2013-01-03 16:24:44 -0800405 request.actions.add(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")
Rich Lane28fa9272013-03-08 16:00:25 -0800504 act = ofp.action.action_output()
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700505
506 for idx in range(len(of_ports)):
Rich Lane32bf9482013-01-03 17:26:30 -0800507 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700508
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700509 ingress_port = of_ports[idx]
510 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
511 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700512 logging.info("Ingress " + str(ingress_port) +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700513 " to egress " + str(egress_port1) + " and " +
514 str(egress_port2))
515
516 match.in_port = ingress_port
517
Rich Lane28fa9272013-03-08 16:00:25 -0800518 request = ofp.message.flow_mod()
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700519 request.match = match
520 request.buffer_id = 0xffffffff
521 act.port = egress_port1
Rich Lanee30455b2013-01-03 16:24:44 -0800522 request.actions.add(act)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700523 act.port = egress_port2
Rich Lanee30455b2013-01-03 16:24:44 -0800524 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700525 # logging.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700526
Rich Lane9a003812012-10-04 17:17:59 -0700527 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800528 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800529 do_barrier(self.controller)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700530
Rich Lane9a003812012-10-04 17:17:59 -0700531 logging.info("Sending packet to dp port " +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700532 str(ingress_port))
533 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700534 yes_ports = set([egress_port1, egress_port2])
535 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700536
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700537 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Rich Lane2014f9b2012-10-05 15:29:40 -0700538 self)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700539
Rich Laneb90a1c42012-10-05 09:16:05 -0700540class DirectMCNonIngress(base_tests.SimpleDataPlane):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700541 """
542 Multicast to all non-ingress ports
543
544 Generate a packet
545 Generate and install a matching flow
546 Add action to direct the packet to all non-ingress ports
547 Send the packet to ingress dataplane port
548 Verify the packet is received at all non-ingress ports
549
550 Does not use the flood action
551 """
552 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700553 of_ports = config["port_map"].keys()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700554 of_ports.sort()
555 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
556
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700557 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700558 match = packet_to_flow_match(self, pkt)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700559 match.wildcards &= ~ofp.OFPFW_IN_PORT
560 self.assertTrue(match is not None,
561 "Could not generate flow match from pkt")
Rich Lane28fa9272013-03-08 16:00:25 -0800562 act = ofp.action.action_output()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700563
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700564 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800565 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700566
Rich Lane9a003812012-10-04 17:17:59 -0700567 logging.info("Ingress " + str(ingress_port) +
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700568 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700569 match.in_port = ingress_port
570
Rich Lane28fa9272013-03-08 16:00:25 -0800571 request = ofp.message.flow_mod()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700572 request.match = match
573 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700574 for egress_port in of_ports:
575 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700576 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700577 act.port = egress_port
Rich Lanee30455b2013-01-03 16:24:44 -0800578 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700579 logging.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700580
Rich Lane9a003812012-10-04 17:17:59 -0700581 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800582 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800583 do_barrier(self.controller)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700584
Rich Lane9a003812012-10-04 17:17:59 -0700585 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700586 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700587 yes_ports = set(of_ports).difference([ingress_port])
588 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700589 self)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700590
Dan Talayco32fa6542010-05-11 15:54:08 -0700591
Rich Laneb90a1c42012-10-05 09:16:05 -0700592class DirectMC(base_tests.SimpleDataPlane):
Dan Talayco32fa6542010-05-11 15:54:08 -0700593 """
594 Multicast to all ports including ingress
595
596 Generate a packet
597 Generate and install a matching flow
598 Add action to direct the packet to all non-ingress ports
599 Send the packet to ingress dataplane port
600 Verify the packet is received at all ports
601
602 Does not use the flood action
603 """
604 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700605 of_ports = config["port_map"].keys()
Dan Talayco32fa6542010-05-11 15:54:08 -0700606 of_ports.sort()
607 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
608
Dan Talayco32fa6542010-05-11 15:54:08 -0700609 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700610 match = packet_to_flow_match(self, pkt)
Dan Talayco32fa6542010-05-11 15:54:08 -0700611 match.wildcards &= ~ofp.OFPFW_IN_PORT
612 self.assertTrue(match is not None,
613 "Could not generate flow match from pkt")
Rich Lane28fa9272013-03-08 16:00:25 -0800614 act = ofp.action.action_output()
Dan Talayco32fa6542010-05-11 15:54:08 -0700615
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700616 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800617 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700618
Rich Lane9a003812012-10-04 17:17:59 -0700619 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700620 match.in_port = ingress_port
621
Rich Lane28fa9272013-03-08 16:00:25 -0800622 request = ofp.message.flow_mod()
Dan Talayco32fa6542010-05-11 15:54:08 -0700623 request.match = match
624 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700625 for egress_port in of_ports:
626 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700627 act.port = ofp.OFPP_IN_PORT
628 else:
629 act.port = egress_port
Rich Lanee30455b2013-01-03 16:24:44 -0800630 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700631 # logging.info(request.show())
Dan Talayco2e77a842010-05-12 15:39:46 -0700632
Rich Lane9a003812012-10-04 17:17:59 -0700633 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800634 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800635 do_barrier(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700636
Rich Lane9a003812012-10-04 17:17:59 -0700637 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700638 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700639 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco2e77a842010-05-12 15:39:46 -0700640
Rich Laneb90a1c42012-10-05 09:16:05 -0700641class Flood(base_tests.SimpleDataPlane):
Dan Talayco2e77a842010-05-12 15:39:46 -0700642 """
643 Flood to all ports except ingress
644
Dan Talaycofcc09912013-02-08 23:46:08 -0800645 Make sure noflood bit is off on all ports
Dan Talayco2e77a842010-05-12 15:39:46 -0700646 Generate a packet
647 Generate and install a matching flow
648 Add action to flood the packet
649 Send the packet to ingress dataplane port
650 Verify the packet is received at all other ports
651 """
652 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700653 of_ports = config["port_map"].keys()
Dan Talayco2e77a842010-05-12 15:39:46 -0700654 of_ports.sort()
655 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
656
657 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700658 match = packet_to_flow_match(self, pkt)
Dan Talayco2e77a842010-05-12 15:39:46 -0700659 match.wildcards &= ~ofp.OFPFW_IN_PORT
660 self.assertTrue(match is not None,
661 "Could not generate flow match from pkt")
Rich Lane28fa9272013-03-08 16:00:25 -0800662 act = ofp.action.action_output()
Dan Talayco2e77a842010-05-12 15:39:46 -0700663
Dan Talaycofcc09912013-02-08 23:46:08 -0800664 for of_port in of_ports:
665 # Clear relevant bits that might block ports
666 rv = port_config_set(self.controller, of_port, 0,
667 ofp.OFPPC_NO_FLOOD | ofp.OFPPC_NO_FWD |
668 ofp.OFPPC_PORT_DOWN)
669 self.assertTrue(rv == 0, "Did not set port config")
670 logging.debug("Enabled and cleared no-flood for port " + str(of_port))
671
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700672 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800673 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700674
Rich Lane9a003812012-10-04 17:17:59 -0700675 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700676 match.in_port = ingress_port
677
Rich Lane28fa9272013-03-08 16:00:25 -0800678 request = ofp.message.flow_mod()
Dan Talayco2e77a842010-05-12 15:39:46 -0700679 request.match = match
680 request.buffer_id = 0xffffffff
681 act.port = ofp.OFPP_FLOOD
Rich Lanee30455b2013-01-03 16:24:44 -0800682 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700683 logging.info(request.show())
Dan Talayco32fa6542010-05-11 15:54:08 -0700684
Rich Lane9a003812012-10-04 17:17:59 -0700685 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800686 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800687 do_barrier(self.controller)
Dan Talayco32fa6542010-05-11 15:54:08 -0700688
Rich Lane9a003812012-10-04 17:17:59 -0700689 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco32fa6542010-05-11 15:54:08 -0700690 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700691 yes_ports = set(of_ports).difference([ingress_port])
692 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700693 self)
Dan Talayco3be5b062010-05-12 15:46:21 -0700694
Rich Laneb90a1c42012-10-05 09:16:05 -0700695class FloodPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco3be5b062010-05-12 15:46:21 -0700696 """
697 Flood to all ports plus send to ingress port
698
699 Generate a packet
700 Generate and install a matching flow
701 Add action to flood the packet
702 Add action to send to ingress port
703 Send the packet to ingress dataplane port
704 Verify the packet is received at all other ports
705 """
706 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700707 of_ports = config["port_map"].keys()
Dan Talayco3be5b062010-05-12 15:46:21 -0700708 of_ports.sort()
709 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
710
711 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700712 match = packet_to_flow_match(self, pkt)
Dan Talayco3be5b062010-05-12 15:46:21 -0700713 match.wildcards &= ~ofp.OFPFW_IN_PORT
714 self.assertTrue(match is not None,
715 "Could not generate flow match from pkt")
Rich Lane28fa9272013-03-08 16:00:25 -0800716 act = ofp.action.action_output()
Dan Talayco3be5b062010-05-12 15:46:21 -0700717
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700718 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800719 delete_all_flows(self.controller)
Dan Talayco3be5b062010-05-12 15:46:21 -0700720
Rich Lane9a003812012-10-04 17:17:59 -0700721 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700722 match.in_port = ingress_port
723
Rich Lane28fa9272013-03-08 16:00:25 -0800724 request = ofp.message.flow_mod()
Dan Talayco3be5b062010-05-12 15:46:21 -0700725 request.match = match
726 request.buffer_id = 0xffffffff
727 act.port = ofp.OFPP_FLOOD
Rich Lanee30455b2013-01-03 16:24:44 -0800728 request.actions.add(act)
Dan Talayco4aa13122010-05-12 15:54:44 -0700729 act.port = ofp.OFPP_IN_PORT
Rich Lanee30455b2013-01-03 16:24:44 -0800730 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700731 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700732
Rich Lane9a003812012-10-04 17:17:59 -0700733 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800734 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800735 do_barrier(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700736
Rich Lane9a003812012-10-04 17:17:59 -0700737 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700738 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700739 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco4aa13122010-05-12 15:54:44 -0700740
Rich Laneb90a1c42012-10-05 09:16:05 -0700741class All(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700742 """
743 Send to OFPP_ALL port
744
745 Generate a packet
746 Generate and install a matching flow
747 Add action to forward to OFPP_ALL
748 Send the packet to ingress dataplane port
749 Verify the packet is received at all other ports
750 """
751 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700752 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700753 of_ports.sort()
754 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
755
756 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700757 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700758 match.wildcards &= ~ofp.OFPFW_IN_PORT
759 self.assertTrue(match is not None,
760 "Could not generate flow match from pkt")
Rich Lane28fa9272013-03-08 16:00:25 -0800761 act = ofp.action.action_output()
Dan Talayco4aa13122010-05-12 15:54:44 -0700762
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700763 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800764 delete_all_flows(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700765
Rich Lane9a003812012-10-04 17:17:59 -0700766 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700767 match.in_port = ingress_port
768
Rich Lane28fa9272013-03-08 16:00:25 -0800769 request = ofp.message.flow_mod()
Dan Talayco4aa13122010-05-12 15:54:44 -0700770 request.match = match
771 request.buffer_id = 0xffffffff
772 act.port = ofp.OFPP_ALL
Rich Lanee30455b2013-01-03 16:24:44 -0800773 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700774 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700775
Rich Lane9a003812012-10-04 17:17:59 -0700776 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800777 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800778 do_barrier(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700779
Rich Lane9a003812012-10-04 17:17:59 -0700780 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700781 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700782 yes_ports = set(of_ports).difference([ingress_port])
783 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700784 self)
Dan Talayco4aa13122010-05-12 15:54:44 -0700785
Rich Laneb90a1c42012-10-05 09:16:05 -0700786class AllPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700787 """
788 Send to OFPP_ALL port and ingress port
789
790 Generate a packet
791 Generate and install a matching flow
792 Add action to forward to OFPP_ALL
793 Add action to forward to ingress port
794 Send the packet to ingress dataplane port
795 Verify the packet is received at all other ports
796 """
797 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700798 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700799 of_ports.sort()
800 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
801
802 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700803 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700804 match.wildcards &= ~ofp.OFPFW_IN_PORT
805 self.assertTrue(match is not None,
806 "Could not generate flow match from pkt")
Rich Lane28fa9272013-03-08 16:00:25 -0800807 act = ofp.action.action_output()
Dan Talayco4aa13122010-05-12 15:54:44 -0700808
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700809 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800810 delete_all_flows(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700811
Rich Lane9a003812012-10-04 17:17:59 -0700812 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700813 match.in_port = ingress_port
814
Rich Lane28fa9272013-03-08 16:00:25 -0800815 request = ofp.message.flow_mod()
Dan Talayco4aa13122010-05-12 15:54:44 -0700816 request.match = match
817 request.buffer_id = 0xffffffff
818 act.port = ofp.OFPP_ALL
Rich Lanee30455b2013-01-03 16:24:44 -0800819 request.actions.add(act)
Dan Talayco3be5b062010-05-12 15:46:21 -0700820 act.port = ofp.OFPP_IN_PORT
Rich Lanee30455b2013-01-03 16:24:44 -0800821 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700822 logging.info(request.show())
Dan Talayco3be5b062010-05-12 15:46:21 -0700823
Rich Lane9a003812012-10-04 17:17:59 -0700824 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800825 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800826 do_barrier(self.controller)
Dan Talayco3be5b062010-05-12 15:46:21 -0700827
Rich Lane9a003812012-10-04 17:17:59 -0700828 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco3be5b062010-05-12 15:46:21 -0700829 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700830 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700831
Rich Laneb90a1c42012-10-05 09:16:05 -0700832class FloodMinusPort(base_tests.SimpleDataPlane):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700833 """
834 Config port with No_Flood and test Flood action
835
836 Generate a packet
837 Generate a matching flow
838 Add action to forward to OFPP_ALL
839 Set port to no-flood
840 Send the packet to ingress dataplane port
841 Verify the packet is received at all other ports except
842 the ingress port and the no_flood port
843 """
844 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700845 of_ports = config["port_map"].keys()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700846 of_ports.sort()
847 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
848
849 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700850 match = packet_to_flow_match(self, pkt)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700851 match.wildcards &= ~ofp.OFPFW_IN_PORT
852 self.assertTrue(match is not None,
853 "Could not generate flow match from pkt")
Rich Lane28fa9272013-03-08 16:00:25 -0800854 act = ofp.action.action_output()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700855
Rich Lane4b9e38c2012-12-06 16:33:20 -0800856 # Clear OFPPC_NO_FLOOD on each port
857 for of_port in of_ports:
858 rv = port_config_set(self.controller, of_port,
859 0, ofp.OFPPC_NO_FLOOD)
860 self.assertEqual(rv, 0, "Failed to set port config")
861
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700862 for idx in range(len(of_ports)):
Rich Lane32bf9482013-01-03 17:26:30 -0800863 delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700864
865 ingress_port = of_ports[idx]
866 no_flood_idx = (idx + 1) % len(of_ports)
867 no_flood_port = of_ports[no_flood_idx]
868 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700869 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700870 self.assertEqual(rv, 0, "Failed to set port config")
871
872 match.in_port = ingress_port
873
Rich Lane28fa9272013-03-08 16:00:25 -0800874 request = ofp.message.flow_mod()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700875 request.match = match
876 request.buffer_id = 0xffffffff
877 act.port = ofp.OFPP_FLOOD
Rich Lanee30455b2013-01-03 16:24:44 -0800878 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700879 logging.info(request.show())
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700880
Rich Lane9a003812012-10-04 17:17:59 -0700881 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800882 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800883 do_barrier(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700884
Rich Lane9a003812012-10-04 17:17:59 -0700885 logging.info("Sending packet to dp port " + str(ingress_port))
886 logging.info("No flood port is " + str(no_flood_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700887 self.dataplane.send(ingress_port, str(pkt))
888 no_ports = set([ingress_port, no_flood_port])
889 yes_ports = set(of_ports).difference(no_ports)
Rich Lane2014f9b2012-10-05 15:29:40 -0700890 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700891
892 # Turn no flood off again
893 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700894 0, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700895 self.assertEqual(rv, 0, "Failed to reset port config")
Rich Lane3a261d52013-01-03 17:45:08 -0800896 do_barrier(self.controller)
Rich Lane4ecc1f42012-12-06 16:35:24 -0800897
898 # Check that packets are now flooded to no_flood_port
899 logging.info("Sending packet to dp port " + str(ingress_port))
900 self.dataplane.send(ingress_port, str(pkt))
901 no_ports = set([ingress_port])
902 yes_ports = set(of_ports).difference(no_ports)
903 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700904
905 #@todo Should check no other packets received
906
Dan Talayco21381562010-07-17 00:34:47 -0700907
908
Dan Talayco551befa2010-07-15 17:05:32 -0700909################################################################
910
Rich Laneb90a1c42012-10-05 09:16:05 -0700911class BaseMatchCase(base_tests.SimpleDataPlane):
Dan Talayco551befa2010-07-15 17:05:32 -0700912 def setUp(self):
Rich Laneb90a1c42012-10-05 09:16:05 -0700913 base_tests.SimpleDataPlane.setUp(self)
Dan Talayco551befa2010-07-15 17:05:32 -0700914 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -0700915 logging.info("BaseMatchCase")
Dan Talayco551befa2010-07-15 17:05:32 -0700916
917class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700918 """
Dan Talayco551befa2010-07-15 17:05:32 -0700919 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700920
921 Generate a packet
922 Generate and install a matching flow without wildcard mask
923 Add action to forward to a port
924 Send the packet to the port
925 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700926 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700927
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700928 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700929 flow_match_test(self, config["port_map"])
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700930
Dan Talayco551befa2010-07-15 17:05:32 -0700931class ExactMatchTagged(BaseMatchCase):
932 """
933 Exact match for all port pairs with tagged pkts
934 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700935
Dan Talayco551befa2010-07-15 17:05:32 -0700936 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -0700937 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Lane477f4812012-10-04 22:49:00 -0700938 flow_match_test(self, config["port_map"], dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700939
Rich Lane0a4f6372013-01-02 14:40:22 -0800940@disabled
Dan Talayco551befa2010-07-15 17:05:32 -0700941class ExactMatchTaggedMany(BaseMatchCase):
942 """
943 ExactMatchTagged with many VLANS
944 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700945
Dan Talayco551befa2010-07-15 17:05:32 -0700946 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700947 for vid in range(2,100,10):
Rich Lane477f4812012-10-04 22:49:00 -0700948 flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
Dan Talayco551befa2010-07-15 17:05:32 -0700949 for vid in range(100,4000,389):
Rich Lane477f4812012-10-04 22:49:00 -0700950 flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
951 flow_match_test(self, config["port_map"], dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700952
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700953class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700954 """
955 SingleWildcardMatchPriority
956 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700957
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700958 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700959 self.pkt = simple_tcp_packet()
960 self.flowMsgs = {}
961
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700962 def _ClearTable(self):
Rich Lane32bf9482013-01-03 17:26:30 -0800963 delete_all_flows(self.controller)
Rich Lane3a261d52013-01-03 17:45:08 -0800964 do_barrier(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700965
966 def runTest(self):
967
968 self._Init()
Rich Lane477f4812012-10-04 22:49:00 -0700969 of_ports = config["port_map"].keys()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700970 of_ports.sort()
971
972 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700973 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700974
975 # Run several combinations, each at lower priority settings.
976 # At the end of each call to runPrioFlows(), the table should
977 # be empty. If its not, we'll catch it as the priorities decreases
978 portA = of_ports[0]
979 portB = of_ports[1]
980 portC = of_ports[2]
981
982 # TODO -- these priority numbers should be validated somehow?
983 self.runPrioFlows(portA, portB, portC, 1000, 999)
984 self.runPrioFlows(portB, portC, portA, 998, 997)
985 self.runPrioFlows(portC, portA, portB, 996, 995)
986 self.runPrioFlows(portA, portC, portB, 994, 993)
987
988
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700989
990 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
991 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700992
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700993 if clearTable:
994 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700995
996 # Sanity check flow at lower priority from pA to pB
Rich Lane9a003812012-10-04 17:17:59 -0700997 logging.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700998 % (portA, portB, portC, prioHigher, prioLower))
999
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001000 # Sanity check flow at lower priority from pA to pC
1001 self.installFlow(prioLower, portA, portC)
1002 self.verifyFlow(portA, portC)
1003 self.removeFlow(prioLower)
1004
1005 # Install and verify pA->pB @ prioLower
1006 self.installFlow(prioLower, portA, portB)
1007 self.verifyFlow(portA, portB)
1008
1009 # Install and verify pA->pC @ prioHigher, should override pA->pB
1010 self.installFlow(prioHigher, portA, portC)
1011 self.verifyFlow(portA, portC)
1012 # remove pA->pC
1013 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001014 # Old flow pA -> pB @ prioLower should still be active
1015 self.verifyFlow(portA, portB)
1016 self.removeFlow(prioLower)
1017
1018 # Table should be empty at this point, leave it alone as
1019 # an assumption for future test runs
1020
1021
1022
Ed Swierk99a74de2012-08-22 06:40:54 -07001023 def installFlow(self, prio, inp, egp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001024 wildcards=ofp.OFPFW_DL_SRC):
Ed Swierk99a74de2012-08-22 06:40:54 -07001025 wildcards |= required_wildcards(self)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001026 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001027 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001028 egr_ports=egp)
1029 request.priority = prio
Rich Lane9a003812012-10-04 17:17:59 -07001030 logging.debug("Install flow with priority " + str(prio))
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001031 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001032 self.flowMsgs[prio] = request
1033
1034 def removeFlow(self, prio):
1035 if self.flowMsgs.has_key(prio):
1036 msg = self.flowMsgs[prio]
1037 msg.command = ofp.OFPFC_DELETE_STRICT
1038 # This *must* be set for DELETE
1039 msg.out_port = ofp.OFPP_NONE
Rich Lane9a003812012-10-04 17:17:59 -07001040 logging.debug("Remove flow with priority " + str(prio))
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001041 self.controller.message_send(msg)
Rich Lane3a261d52013-01-03 17:45:08 -08001042 do_barrier(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001043 else:
1044 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001045
1046
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001047 def verifyFlow(self, inp, egp, pkt=None):
1048 if pkt == None:
1049 pkt = self.pkt
1050
Rich Lane9a003812012-10-04 17:17:59 -07001051 logging.info("Pkt match test: " + str(inp) + " to " + str(egp))
1052 logging.debug("Send packet: " + str(inp) + " to " + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001053 self.dataplane.send(inp, str(pkt))
1054 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001055
1056
1057
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001058class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
1059
1060 def runTest(self):
1061
1062 self._Init()
1063
Rich Lane477f4812012-10-04 22:49:00 -07001064 of_ports = config["port_map"].keys()
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001065 of_ports.sort()
1066
1067 # Install an entry from 0 -> 1 @ prio 1000
1068 self._ClearTable()
1069 self.installFlow(1000, of_ports[0], of_ports[1])
1070 self.verifyFlow(of_ports[0], of_ports[1])
1071 self.installFlow(1000, of_ports[1], of_ports[0])
1072 self.verifyFlow(of_ports[1], of_ports[0])
1073 self.installFlow(1001, of_ports[0], of_ports[1])
1074 self.verifyFlow(of_ports[0], of_ports[1])
1075 self.installFlow(1001, of_ports[1], of_ports[0])
1076 self.verifyFlow(of_ports[1], of_ports[0])
1077 self.removeFlow(1001)
1078 self.verifyFlow(of_ports[0], of_ports[1])
1079 self.removeFlow(1000)
1080
1081
1082
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001083class WildcardPriority(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001084 """
1085 1. Add wildcard flow, verify packet received.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001086 2. Add wildcard flow with higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001087 on port specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001088 3. Add wildcard flow with lower priority, verify packet received
Rich Laneb8392082012-11-21 15:52:54 -08001089 on port specified by the highest priority flow.
Ken Chiang38d7a152012-05-24 15:33:50 -07001090 """
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001091
1092 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001093
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001094 self._Init()
1095
Rich Lane477f4812012-10-04 22:49:00 -07001096 of_ports = config["port_map"].keys()
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001097 of_ports.sort()
1098
1099 self._ClearTable()
Ken Chiang38d7a152012-05-24 15:33:50 -07001100
1101 # Install a flow with wildcards
1102 self.installFlow(999, of_ports[0], of_ports[1],
1103 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001104 self.verifyFlow(of_ports[0], of_ports[1])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001105 # Install a flow with wildcards with higher priority
1106 self.installFlow(1000, of_ports[0], of_ports[2],
1107 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001108 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001109 # Install a flow with wildcards with lower priority
Rich Laneb8392082012-11-21 15:52:54 -08001110 self.installFlow(999, of_ports[0], of_ports[1],
1111 wildcards=ofp.OFPFW_DL_SRC)
Rich Lane0a78fbd2012-12-31 16:25:04 -08001112 self.verifyFlow(of_ports[0], of_ports[2])
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001113
1114
Rich Lane97e99652013-01-02 17:23:20 -08001115@group("smoke")
Ken Chiang3978f242012-06-13 14:14:09 -07001116class WildcardPriorityWithDelete(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001117 """
Rich Lane0a78fbd2012-12-31 16:25:04 -08001118 1. Add wildcard match flow, verify packet received.
Ken Chiang38d7a152012-05-24 15:33:50 -07001119 2. Add wildcard flow with higher priority, verify packet received on port
1120 specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001121 3. Add wildcard flow with even higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001122 on port specified by this flow.
1123 4. Delete lowest priority flow, verify packet received on port specified
1124 by highest priority flow.
1125 5. Delete highest priority flow, verify packet received on port specified
1126 by remaining flow.
1127 """
1128
1129 def runTest(self):
1130
1131 self._Init()
1132
Rich Lane477f4812012-10-04 22:49:00 -07001133 of_ports = config["port_map"].keys()
Ken Chiang38d7a152012-05-24 15:33:50 -07001134 of_ports.sort()
1135
1136 self._ClearTable()
1137
Rich Lane0a78fbd2012-12-31 16:25:04 -08001138 # Install a flow with wildcards
1139 self.installFlow(250, of_ports[0], of_ports[1],
1140 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001141 self.verifyFlow(of_ports[0], of_ports[1])
1142 # Install a flow with wildcards of higher priority
1143 self.installFlow(1250, of_ports[0], of_ports[2],
1144 wildcards=ofp.OFPFW_DL_DST)
1145 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001146 # Install a flow with wildcards with even higher priority
1147 self.installFlow(2001, of_ports[0], of_ports[3],
1148 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001149 self.verifyFlow(of_ports[0], of_ports[3])
1150 # Delete lowest priority flow
1151 self.removeFlow(250)
1152 self.verifyFlow(of_ports[0], of_ports[3])
1153 # Delete highest priority flow
1154 self.removeFlow(2001)
1155 self.verifyFlow(of_ports[0], of_ports[2])
1156
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001157
Dan Talayco551befa2010-07-15 17:05:32 -07001158class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001159 """
1160 Exercise wildcard matching for all ports
1161
1162 Generate a packet
1163 Generate and install a matching flow with wildcard mask
1164 Add action to forward to a port
1165 Send the packet to the port
1166 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001167 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001168 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001169 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001170 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001171 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001172 wc |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001173 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001174 # Set nonzero VLAN id to avoid sending priority-tagged packet
1175 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001176 else:
1177 dl_vlan = -1
Rich Lane477f4812012-10-04 22:49:00 -07001178 flow_match_test(self, config["port_map"], wildcards=wc,
Dan Talayco4431d542012-03-21 16:42:16 -07001179 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001180
Dan Talayco551befa2010-07-15 17:05:32 -07001181class SingleWildcardMatchTagged(BaseMatchCase):
1182 """
1183 SingleWildcardMatch with tagged packets
1184 """
1185 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001186 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001187 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001188 wc |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001189 flow_match_test(self, config["port_map"], wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -07001190 max_test=10)
1191
1192class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001193 """
Dan Talayco80b54ed2010-07-13 09:48:35 -07001194 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001195
1196 Generate a packet
1197 Generate and install a matching flow with wildcard all except one filed
1198 Add action to forward to a port
1199 Send the packet to the port
1200 Verify the packet is received at all other ports (one port at a time)
1201 Verify flow_expiration message is correct when command option is set
1202 """
1203 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001204 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001205 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001206 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001207 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001208 # Set nonzero VLAN id to avoid sending priority-tagged packet
1209 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001210 else:
1211 dl_vlan = -1
Rich Lane477f4812012-10-04 22:49:00 -07001212 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Dan Talayco4431d542012-03-21 16:42:16 -07001213 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001214
Dan Talayco551befa2010-07-15 17:05:32 -07001215class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1216 """
1217 Match one field with tagged packets
1218 """
1219 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001220 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001221 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001222 all_exp_one_wildcard |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001223 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Dan Talayco21381562010-07-17 00:34:47 -07001224 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001225
1226class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001227 """
1228 Create Wildcard-all flow and exercise for all ports
1229
1230 Generate a packet
1231 Generate and install a matching flow with wildcard-all
1232 Add action to forward to a port
1233 Send the packet to the port
1234 Verify the packet is received at all other ports (one port at a time)
1235 Verify flow_expiration message is correct when command option is set
1236 """
1237 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001238 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001239
Dan Talayco551befa2010-07-15 17:05:32 -07001240class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001241 """
Dan Talayco551befa2010-07-15 17:05:32 -07001242 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001243 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001244 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001245 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Lane477f4812012-10-04 22:49:00 -07001246 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL,
Dan Talayco21381562010-07-17 00:34:47 -07001247 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001248
Rich Lane97e99652013-01-02 17:23:20 -08001249@group('smoke')
Dan Talayco551befa2010-07-15 17:05:32 -07001250class AddVLANTag(BaseMatchCase):
1251 """
1252 Add a VLAN tag to an untagged packet
1253 """
1254 def runTest(self):
1255 new_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001256 sup_acts = self.supported_actions
Dan Talayco551befa2010-07-15 17:05:32 -07001257 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001258 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001259 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001260
Dan Talayco551befa2010-07-15 17:05:32 -07001261 len = 100
1262 len_w_vid = 104
1263 pkt = simple_tcp_packet(pktlen=len)
1264 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1265 dl_vlan=new_vid)
Rich Lane28fa9272013-03-08 16:00:25 -08001266 vid_act = ofp.action.action_set_vlan_vid()
Dan Talayco551befa2010-07-15 17:05:32 -07001267 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001268
Rich Lane477f4812012-10-04 22:49:00 -07001269 flow_match_test(self, config["port_map"], pkt=pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001270 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001271
Rich Lane0a4f6372013-01-02 14:40:22 -08001272@disabled
Rich Laneb90a1c42012-10-05 09:16:05 -07001273class PacketOnly(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001274 """
1275 Just send a packet thru the switch
1276 """
Rich Laned1d9c282012-10-04 22:07:10 -07001277
Dan Talayco551befa2010-07-15 17:05:32 -07001278 def runTest(self):
1279 pkt = simple_tcp_packet()
Rich Lane477f4812012-10-04 22:49:00 -07001280 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001281 of_ports.sort()
1282 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001283 logging.info("Sending packet to " + str(ing_port))
1284 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001285 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001286
Rich Lane0a4f6372013-01-02 14:40:22 -08001287@disabled
Rich Laneb90a1c42012-10-05 09:16:05 -07001288class PacketOnlyTagged(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001289 """
1290 Just send a packet thru the switch
1291 """
Rich Laned1d9c282012-10-04 22:07:10 -07001292
Dan Talayco551befa2010-07-15 17:05:32 -07001293 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001294 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001295 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
Rich Lane477f4812012-10-04 22:49:00 -07001296 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001297 of_ports.sort()
1298 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001299 logging.info("Sending packet to " + str(ing_port))
1300 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001301 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001302
Dan Talayco551befa2010-07-15 17:05:32 -07001303class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001304 """
1305 Modify the VLAN ID in the VLAN tag of a tagged packet
1306 """
Dan Talaycoaf669322012-09-12 22:51:22 -07001307 def setUp(self):
1308 BaseMatchCase.setUp(self)
1309 self.ing_port=False
1310
Dan Talayco551befa2010-07-15 17:05:32 -07001311 def runTest(self):
1312 old_vid = 2
1313 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001314 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001315 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001316 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001317 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001318
Dan Talayco551befa2010-07-15 17:05:32 -07001319 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1320 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
Rich Lane28fa9272013-03-08 16:00:25 -08001321 vid_act = ofp.action.action_set_vlan_vid()
Dan Talayco551befa2010-07-15 17:05:32 -07001322 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001323
Rich Lane477f4812012-10-04 22:49:00 -07001324 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoaf669322012-09-12 22:51:22 -07001325 action_list=[vid_act], ing_port=self.ing_port)
1326
1327class ModifyVIDToIngress(ModifyVID):
1328 """
1329 Modify the VLAN ID in the VLAN tag of a tagged packet and send to
1330 ingress port
1331 """
1332 def setUp(self):
1333 BaseMatchCase.setUp(self)
1334 self.ing_port=True
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001335
Ken Chiange9a211d2012-04-20 14:52:11 -07001336class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1337 """
Rich Lane28fa9272013-03-08 16:00:25 -08001338 With vlan ID and priority wildcarded, perform SET_VLAN_VID ofp.action.
Ken Chiange9a211d2012-04-20 14:52:11 -07001339 The same flow should match on both untagged and tagged packets.
1340 """
1341 def runTest(self):
1342 old_vid = 2
1343 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001344 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001345 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1346 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1347 return
1348
Rich Lane477f4812012-10-04 22:49:00 -07001349 of_ports = config["port_map"].keys()
Ken Chiange9a211d2012-04-20 14:52:11 -07001350 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1351 ing_port = of_ports[0]
1352 egr_ports = of_ports[1]
1353
Rich Lane32bf9482013-01-03 17:26:30 -08001354 delete_all_flows(self.controller)
Ken Chiange9a211d2012-04-20 14:52:11 -07001355
1356 len_untagged = 100
1357 len_w_vid = 104
1358 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1359 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
1360 dl_vlan_enable=True, dl_vlan=old_vid)
1361 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1362 dl_vlan=new_vid)
Ed Swierk99a74de2012-08-22 06:40:54 -07001363 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1364 ofp.OFPFW_DL_VLAN_PCP)
Rich Lane28fa9272013-03-08 16:00:25 -08001365 vid_act = ofp.action.action_set_vlan_vid()
Ken Chiange9a211d2012-04-20 14:52:11 -07001366 vid_act.vlan_vid = new_vid
1367 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
1368 wildcards=wildcards, egr_ports=egr_ports,
1369 action_list=[vid_act])
1370 flow_msg_install(self, request)
1371
Rich Lane9a003812012-10-04 17:17:59 -07001372 logging.debug("Send untagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001373 str(egr_ports))
1374 self.dataplane.send(ing_port, str(untagged_pkt))
1375 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1376
Rich Lane9a003812012-10-04 17:17:59 -07001377 logging.debug("Send tagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001378 str(egr_ports))
1379 self.dataplane.send(ing_port, str(tagged_pkt))
1380 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1381
Howard Pershc1199d52012-04-11 14:21:32 -07001382class ModifyVlanPcp(BaseMatchCase):
1383 """
1384 Modify the priority field of the VLAN tag of a tagged packet
1385 """
1386 def runTest(self):
1387 vid = 123
1388 old_vlan_pcp = 2
1389 new_vlan_pcp = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001390 sup_acts = self.supported_actions
Ed Swierk8c3af7f2012-04-24 14:19:17 -07001391 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_PCP):
1392 skip_message_emit(self, "Modify VLAN priority test")
Howard Pershc1199d52012-04-11 14:21:32 -07001393 return
1394
1395 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1396 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
Rich Lane28fa9272013-03-08 16:00:25 -08001397 vid_act = ofp.action.action_set_vlan_pcp()
Howard Pershc1199d52012-04-11 14:21:32 -07001398 vid_act.vlan_pcp = new_vlan_pcp
1399
Rich Lane477f4812012-10-04 22:49:00 -07001400 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Howard Pershc1199d52012-04-11 14:21:32 -07001401 action_list=[vid_act])
1402
Dan Talayco551befa2010-07-15 17:05:32 -07001403class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001404 """
1405 Strip the VLAN tag from a tagged packet
1406 """
Dan Talayco551befa2010-07-15 17:05:32 -07001407 def runTest(self):
1408 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001409 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001410 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001411 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001412 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001413
Dan Talayco551befa2010-07-15 17:05:32 -07001414 len_w_vid = 104
1415 len = 100
1416 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1417 dl_vlan=old_vid)
1418 exp_pkt = simple_tcp_packet(pktlen=len)
Rich Lane28fa9272013-03-08 16:00:25 -08001419 vid_act = ofp.action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001420
Rich Lane477f4812012-10-04 22:49:00 -07001421 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001422 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001423
Ken Chiange9a211d2012-04-20 14:52:11 -07001424class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1425 """
1426 Strip the VLAN tag from a tagged packet.
1427 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1428 """
1429 def runTest(self):
1430 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001431 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001432 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1433 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1434 return
1435
1436 len_w_vid = 104
1437 len_untagged = 100
1438 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1439 dl_vlan=old_vid)
1440 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
Ed Swierk99a74de2012-08-22 06:40:54 -07001441 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1442 ofp.OFPFW_DL_VLAN_PCP)
Rich Lane28fa9272013-03-08 16:00:25 -08001443 vid_act = ofp.action.action_strip_vlan()
Ken Chiange9a211d2012-04-20 14:52:11 -07001444
Rich Lane477f4812012-10-04 22:49:00 -07001445 flow_match_test(self, config["port_map"],
Ed Swierk99a74de2012-08-22 06:40:54 -07001446 wildcards=wildcards,
Ken Chiange9a211d2012-04-20 14:52:11 -07001447 pkt=pkt, exp_pkt=exp_pkt,
1448 action_list=[vid_act])
1449
Dan Talayco4b2bee62010-07-20 14:10:05 -07001450def init_pkt_args():
1451 """
1452 Pass back a dictionary with default packet arguments
1453 """
1454 args = {}
1455 args["dl_src"] = '00:23:45:67:89:AB'
1456
1457 dl_vlan_enable=False
1458 dl_vlan=-1
Rich Lane477f4812012-10-04 22:49:00 -07001459 if config["test-params"]["vid"]:
Dan Talayco4b2bee62010-07-20 14:10:05 -07001460 dl_vlan_enable=True
Rich Lane477f4812012-10-04 22:49:00 -07001461 dl_vlan = config["test-params"]["vid"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001462
1463# Unpack operator is ** on a dictionary
1464
1465 return args
1466
Dan Talayco551befa2010-07-15 17:05:32 -07001467class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001468 """
1469 Modify the source MAC address (TP1)
1470 """
Dan Talayco551befa2010-07-15 17:05:32 -07001471 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001472 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001473 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001474 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001475 return
1476
1477 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1478 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001479 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001480 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001481
Dan Talayco551befa2010-07-15 17:05:32 -07001482class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001483 """
1484 Modify the dest MAC address (TP1)
1485 """
Dan Talayco551befa2010-07-15 17:05:32 -07001486 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001487 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001488 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001489 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001490 return
1491
1492 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1493 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001494 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001495 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001496
Dan Talayco551befa2010-07-15 17:05:32 -07001497class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001498 """
1499 Modify the source IP address of an IP packet (TP1)
1500 """
Dan Talayco551befa2010-07-15 17:05:32 -07001501 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001502 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001503 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001504 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001505 return
1506
1507 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1508 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001509 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001510 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001511
Dan Talayco551befa2010-07-15 17:05:32 -07001512class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001513 """
1514 Modify the dest IP address of an IP packet (TP1)
1515 """
Dan Talayco551befa2010-07-15 17:05:32 -07001516 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001517 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001518 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001519 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001520 return
1521
1522 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1523 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001524 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001525 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001526
1527class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001528 """
1529 Modify the source TCP port of a TCP packet (TP1)
1530 """
Dan Talayco551befa2010-07-15 17:05:32 -07001531 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001532 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001533 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001534 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001535 return
1536
1537 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1538 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001539 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001540 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001541
Rich Lane01c2b862012-10-26 16:26:25 -07001542class ModifyL4SrcUdp(BaseMatchCase):
1543 """
1544 Modify the source UDP port of a UDP packet
1545 """
1546 def runTest(self):
1547 sup_acts = self.supported_actions
1548 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1549 skip_message_emit(self, "ModifyL4SrcUdp test")
1550 return
1551
1552 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_sport'],
1553 check_test_params=True, tp="udp")
1554 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1555 action_list=acts, max_test=2)
1556
Dan Talayco551befa2010-07-15 17:05:32 -07001557class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001558 """
1559 Modify the dest TCP port of a TCP packet (TP1)
1560 """
Dan Talayco551befa2010-07-15 17:05:32 -07001561 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001562 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001563 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001564 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001565 return
1566
1567 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1568 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001569 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001570 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001571
Rich Lane01c2b862012-10-26 16:26:25 -07001572class ModifyL4DstUdp(BaseMatchCase):
1573 """
1574 Modify the dest UDP port of a UDP packet
1575 """
1576 def runTest(self):
1577 sup_acts = self.supported_actions
1578 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1579 skip_message_emit(self, "ModifyL4DstUdp test")
1580 return
1581
1582 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_dport'],
1583 check_test_params=True, tp="udp")
1584 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1585 action_list=acts, max_test=2)
1586
Dan Talayco551befa2010-07-15 17:05:32 -07001587class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001588 """
1589 Modify the IP type of service of an IP packet (TP1)
1590 """
Dan Talayco551befa2010-07-15 17:05:32 -07001591 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001592 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001593 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001594 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001595 return
Dan Talayco551befa2010-07-15 17:05:32 -07001596
Dan Talayco4b2bee62010-07-20 14:10:05 -07001597 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1598 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001599 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001600 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001601
Dan Talaycof6e76c02012-03-23 10:56:12 -07001602class ModifyL2DstMC(BaseMatchCase):
1603 """
1604 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001605 """
1606 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001607 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001608 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001609 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001610 return
1611
Dan Talaycof6e76c02012-03-23 10:56:12 -07001612 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1613 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001614 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001615 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001616
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001617class ModifyL2DstIngress(BaseMatchCase):
1618 """
1619 Modify the L2 dest and send to the ingress port
1620 """
1621 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001622 sup_acts = self.supported_actions
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001623 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001624 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001625 return
1626
1627 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1628 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001629 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001630 action_list=acts, max_test=2, egr_count=0,
1631 ing_port=True)
1632
Dan Talaycod8ae7582012-03-23 12:24:56 -07001633class ModifyL2DstIngressMC(BaseMatchCase):
1634 """
1635 Modify the L2 dest and send to the ingress port
1636 """
1637 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001638 sup_acts = self.supported_actions
Dan Talaycod8ae7582012-03-23 12:24:56 -07001639 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1640 skip_message_emit(self, "ModifyL2dstMC test")
1641 return
1642
1643 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1644 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001645 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001646 action_list=acts, max_test=2, egr_count=-1,
1647 ing_port=True)
1648
Dan Talaycof6e76c02012-03-23 10:56:12 -07001649class ModifyL2SrcMC(BaseMatchCase):
1650 """
1651 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001652 """
1653 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001654 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001655 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001656 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001657 return
1658
Dan Talaycof6e76c02012-03-23 10:56:12 -07001659 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1660 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001661 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001662 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001663
1664class ModifyL2SrcDstMC(BaseMatchCase):
1665 """
1666 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001667 """
1668 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001669 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001670 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1671 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1672 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001673 return
1674
Dan Talaycof6e76c02012-03-23 10:56:12 -07001675 mod_fields = ['dl_dst', 'dl_src']
1676 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1677 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001678 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001679 action_list=acts, max_test=2, egr_count=-1)
1680
1681class ModifyL2DstVIDMC(BaseMatchCase):
1682 """
1683 Modify the L2 dest and send to 2 ports
1684 """
1685 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001686 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001687 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1688 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1689 skip_message_emit(self, "ModifyL2DstVIDMC test")
1690 return
1691
1692 mod_fields = ['dl_dst', 'dl_vlan']
1693 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1694 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1695 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001696 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001697 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001698
Rich Lane97e99652013-01-02 17:23:20 -08001699@group("smoke")
Rich Lane22e74c12012-11-12 15:06:06 -08001700class ModifyAll(BaseMatchCase):
1701 """
1702 Modify all supported fields and output to a port
1703 """
1704 def runTest(self):
1705 sup_acts = self.supported_actions
1706
1707 sup_map = {
1708 "dl_dst" : ofp.OFPAT_SET_DL_DST,
1709 "dl_src" : ofp.OFPAT_SET_DL_SRC,
1710 "dl_vlan_enable" : ofp.OFPAT_SET_VLAN_VID,
1711 "dl_vlan" : ofp.OFPAT_SET_VLAN_VID,
1712 "dl_vlan_pcp" : ofp.OFPAT_SET_VLAN_PCP,
1713 "ip_src" : ofp.OFPAT_SET_NW_SRC,
1714 "ip_dst" : ofp.OFPAT_SET_NW_DST,
1715 "ip_tos" : ofp.OFPAT_SET_NW_TOS,
1716 "tcp_sport" : ofp.OFPAT_SET_TP_SRC,
1717 "tcp_dport" : ofp.OFPAT_SET_TP_DST,
1718 }
1719
1720 mod_fields = [field for (field, bit) in sup_map.items() if (sup_acts & 1 << bit)]
1721 random.shuffle(mod_fields)
1722 start_field_vals = { "dl_vlan_enable" : True }
1723 mod_field_vals = { "dl_vlan_enable" : True }
1724 logging.info("modifying fields: %s" % repr(mod_fields))
1725
1726 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1727 mod_fields=mod_fields,
1728 start_field_vals=start_field_vals,
1729 mod_field_vals=mod_field_vals,
1730 check_test_params=True)
1731 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1732 action_list=acts, max_test=2)
1733
Dan Talaycofa6454f2012-04-05 10:04:13 -07001734class FlowToggle(BaseMatchCase):
1735 """
1736 Add flows to the table and modify them repeatedly
Dan Talaycof7c41312012-07-23 12:53:19 -07001737
1738 This is done by using only "add" flow messages. Since the check overlap
1739 flag is not set, the switch is supposed to modify the existing flow if
1740 the match already exists.
1741
1742 Would probably be better to exercise more of the flow modify commands
1743 (add, modify, delete +/- strict).
Dan Talaycofa6454f2012-04-05 10:04:13 -07001744 """
1745 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001746 flow_count = test_param_get('ft_flow_count', default=20)
1747 iter_count = test_param_get('ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001748
Rich Lane9a003812012-10-04 17:17:59 -07001749 logging.info("Running flow toggle with %d flows, %d iterations" %
Dan Talaycofa6454f2012-04-05 10:04:13 -07001750 (flow_count, iter_count))
1751 acts = []
Rich Lane28fa9272013-03-08 16:00:25 -08001752 acts.append(ofp.action.action_output())
1753 acts.append(ofp.action.action_output())
Dan Talaycofa6454f2012-04-05 10:04:13 -07001754
Rich Lane477f4812012-10-04 22:49:00 -07001755 of_ports = config["port_map"].keys()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001756 if len(of_ports) < 3:
1757 self.assertTrue(False, "Too few ports for test")
1758
1759 for idx in range(2):
1760 acts[idx].port = of_ports[idx]
1761
1762 flows = []
1763 flows.append([])
1764 flows.append([])
1765
Ed Swierk99a74de2012-08-22 06:40:54 -07001766 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_SRC |
1767 ofp.OFPFW_DL_DST)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001768 # Create up the flows in an array
1769 for toggle in range(2):
1770 for f_idx in range(flow_count):
1771 pkt = simple_tcp_packet(tcp_sport=f_idx)
Rich Lane28fa9272013-03-08 16:00:25 -08001772 msg = ofp.message.flow_mod()
Ed Swierk99a74de2012-08-22 06:40:54 -07001773 match = packet_to_flow_match(self, pkt)
Shudong Zhou031373c2012-07-19 17:37:42 -07001774 match.in_port = of_ports[2]
Dan Talayco50be7672012-04-05 11:38:08 -07001775 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001776 msg.match = match
1777 msg.buffer_id = 0xffffffff
Dan Talaycof7c41312012-07-23 12:53:19 -07001778 msg.command = ofp.OFPFC_ADD
Dan Talaycofa6454f2012-04-05 10:04:13 -07001779 msg.actions.add(acts[toggle])
1780 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001781
1782 # Show two sample flows
Rich Lane9a003812012-10-04 17:17:59 -07001783 logging.debug(flows[0][0].show())
1784 logging.debug(flows[1][0].show())
Dan Talayco50be7672012-04-05 11:38:08 -07001785
Dan Talaycofa6454f2012-04-05 10:04:13 -07001786 # Install the first set of flows
1787 for f_idx in range(flow_count):
Rich Lane5c3151c2013-01-03 17:15:41 -08001788 self.controller.message_send(flows[0][f_idx])
Rich Lane3a261d52013-01-03 17:45:08 -08001789 do_barrier(self.controller)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001790
Rich Lane9a003812012-10-04 17:17:59 -07001791 logging.info("Installed %d flows" % flow_count)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001792
1793 # Repeatedly modify all the flows back and forth
1794 updates = 0
1795 # Report status about 5 times
1796 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001797 start = time.time()
1798 for iter_idx in range(iter_count):
1799 if not iter_idx % mod_val:
Rich Lane9a003812012-10-04 17:17:59 -07001800 logging.info("Flow Toggle: iter %d of %d. " %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001801 (iter_idx, iter_count) +
1802 "%d updates in %d secs" %
1803 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001804 for toggle in range(2):
1805 t_idx = 1 - toggle
1806 for f_idx in range(flow_count):
Rich Lane5c3151c2013-01-03 17:15:41 -08001807 self.controller.message_send(flows[t_idx][f_idx])
Dan Talaycofa6454f2012-04-05 10:04:13 -07001808 updates += 1
Rich Lane3a261d52013-01-03 17:45:08 -08001809 do_barrier(self.controller)
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001810
1811 end = time.time()
1812 divisor = end - start or (end - start + 1)
Rich Lane9a003812012-10-04 17:17:59 -07001813 logging.info("Flow toggle: %d iterations" % iter_count)
1814 logging.info(" %d flow mods in %d secs, %d mods/sec" %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001815 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001816
1817
Dan Talayco8a64e332012-03-28 14:53:20 -07001818# You can pick and choose these by commenting tests in or out
1819iter_classes = [
1820 basic.PacketIn,
1821 basic.PacketOut,
1822 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001823 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001824 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001825 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001826 AllWildcardMatch,
1827 AllWildcardMatchTagged,
1828 SingleWildcardMatch,
1829 SingleWildcardMatchTagged,
1830 ExactMatch,
1831 ExactMatchTagged,
1832 SingleWildcardMatch,
1833 ModifyL2Src,
1834 ModifyL2Dst,
1835 ModifyL2SrcMC,
1836 ModifyL2DstMC,
1837 ModifyL2SrcDstMC
1838 ]
1839
Rich Lane0a4f6372013-01-02 14:40:22 -08001840@disabled
Dan Talayco8a64e332012-03-28 14:53:20 -07001841class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001842 """
1843 Iterate over a bunch of test cases
1844
1845 The cases come from the list above
1846 """
1847
Dan Talayco8a64e332012-03-28 14:53:20 -07001848 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001849 count = test_param_get('iter_count', default=10)
Dan Talayco8a64e332012-03-28 14:53:20 -07001850 tests_done = 0
Rich Lane9a003812012-10-04 17:17:59 -07001851 logging.info("Running iteration test " + str(count) + " times")
Dan Talayco8a64e332012-03-28 14:53:20 -07001852 start = time.time()
1853 last = start
1854 for idx in range(count):
Rich Lane9a003812012-10-04 17:17:59 -07001855 logging.info("Iteration " + str(idx + 1))
Dan Talayco8a64e332012-03-28 14:53:20 -07001856 for cls in iter_classes:
1857 test = cls()
1858 test.inheritSetup(self)
1859 test.runTest()
1860 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001861 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001862 if time.time() - last > 60:
1863 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001864 logging.info(
Dan Talaycofa6454f2012-04-05 10:04:13 -07001865 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1866 (idx, count, tests_done, last - start) +
1867 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001868 stats = all_stats_get(self)
1869 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001870 logging.info("\nIterCases ran %d tests in %d seconds." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001871 (tests_done, last - start))
Rich Lane9a003812012-10-04 17:17:59 -07001872 logging.info(" flows: %d. packets: %d. bytes: %d" %
Dan Talayco8a64e332012-03-28 14:53:20 -07001873 (stats["flows"], stats["packets"], stats["bytes"]))
Rich Lane9a003812012-10-04 17:17:59 -07001874 logging.info(" active: %d. lookups: %d. matched %d." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001875 (stats["active"], stats["lookups"], stats["matched"]))
1876
Dan Talayco4b2bee62010-07-20 14:10:05 -07001877#@todo Need to implement tagged versions of the above tests
1878#
1879#@todo Implement a test case that strips tag 2, adds tag 3
1880# and modifies tag 4 to tag 5. Then verify (in addition) that
1881# tag 6 does not get modified.
1882
Rich Lane0a4f6372013-01-02 14:40:22 -08001883@disabled
Dan Talayco4b2bee62010-07-20 14:10:05 -07001884class MixedVLAN(BaseMatchCase):
1885 """
1886 Test mixture of VLAN tag actions
1887
1888 Strip tag 2 on port 1, send to port 2
1889 Add tag 3 on port 1, send to port 2
1890 Modify tag 4 to 5 on port 1, send to port 2
1891 All other traffic from port 1, send to port 3
1892 All traffic from port 2 sent to port 4
1893 Use exact matches with different packets for all mods
1894 Verify the following: (port, vid)
1895 (port 1, vid 2) => VLAN tag stripped, out port 2
1896 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1897 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1898 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1899 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1900 (port 2, no tag) => untagged packet out port 4
1901 (port 2, vid 2-6) => unmodified packet out port 4
1902
1903 Variation: Might try sending VID 5 to port 3 and check.
1904 If only VID 5 distinguishes pkt, this will fail on some platforms
1905 """
1906
Rich Lane97e99652013-01-02 17:23:20 -08001907@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -07001908class MatchEach(base_tests.SimpleDataPlane):
Rich Lane8d6ab272012-09-23 18:06:20 -07001909 """
1910 Check that each match field is actually matched on.
1911 Installs two flows that differ in one field. The flow that should not
1912 match has a higher priority, so if that field is ignored during matching
1913 the packet will be sent out the wrong port.
1914
1915 TODO test UDP, ARP, ICMP, etc.
1916 """
1917 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001918 of_ports = config["port_map"].keys()
Rich Lane8d6ab272012-09-23 18:06:20 -07001919 of_ports.sort()
1920 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1921
Rich Lane9a003812012-10-04 17:17:59 -07001922 delete_all_flows(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001923
Ed Swierk7040a8d2012-12-11 16:30:13 -08001924 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=2)
Rich Lane8d6ab272012-09-23 18:06:20 -07001925 ingress_port = of_ports[0]
1926 egress_port = of_ports[1]
1927
1928 def testField(field, mask):
Rich Lane9a003812012-10-04 17:17:59 -07001929 logging.info("Testing field %s" % field)
Rich Lane8d6ab272012-09-23 18:06:20 -07001930
1931 def addFlow(matching, priority, output_port):
1932 match = packet_to_flow_match(self, pkt)
1933 self.assertTrue(match is not None, "Could not generate flow match from pkt")
1934 match.wildcards &= ~ofp.OFPFW_IN_PORT
1935 match.in_port = ingress_port
1936 if not matching:
1937 # Make sure flow doesn't match
1938 orig = getattr(match, field)
1939 if isinstance(orig, list):
1940 new = map(lambda a: ~a[0] & a[1], zip(orig, mask))
1941 else:
1942 new = ~orig & mask
1943 setattr(match, field, new)
Rich Lane28fa9272013-03-08 16:00:25 -08001944 request = ofp.message.flow_mod()
Rich Lane8d6ab272012-09-23 18:06:20 -07001945 request.match = match
1946 request.buffer_id = 0xffffffff
1947 request.priority = priority
Rich Lane28fa9272013-03-08 16:00:25 -08001948 act = ofp.action.action_output()
Rich Lane8d6ab272012-09-23 18:06:20 -07001949 act.port = output_port
Rich Lanee30455b2013-01-03 16:24:44 -08001950 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -07001951 logging.info("Inserting flow")
Rich Lane8d6ab272012-09-23 18:06:20 -07001952 self.controller.message_send(request)
1953
1954 # This flow should match.
1955 addFlow(matching=True, priority=0, output_port=egress_port)
1956 # This flow should not match, but it has a higher priority.
1957 addFlow(matching=False, priority=1, output_port=ofp.OFPP_IN_PORT)
1958
Rich Lane3a261d52013-01-03 17:45:08 -08001959 do_barrier(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001960
Rich Lane9a003812012-10-04 17:17:59 -07001961 logging.info("Sending packet to dp port " + str(ingress_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001962 self.dataplane.send(ingress_port, str(pkt))
1963
1964 exp_pkt_arg = None
1965 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -07001966 if config["relax"]:
Rich Lane8d6ab272012-09-23 18:06:20 -07001967 exp_pkt_arg = pkt
1968 exp_port = egress_port
1969
1970 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
1971 exp_pkt=exp_pkt_arg)
1972 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -07001973 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001974 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
1975 self.assertEqual(str(pkt), str(rcv_pkt), 'Response packet does not match send packet')
1976
Ed Swierkb603b192012-12-12 15:38:49 -08001977 wildcards = required_wildcards(self)
Rich Lane8d6ab272012-09-23 18:06:20 -07001978 # TODO in_port
Ed Swierkb603b192012-12-12 15:38:49 -08001979 if not (wildcards & ofp.OFPFW_DL_SRC):
1980 testField("dl_src", [0xff]*6)
1981 if not (wildcards & ofp.OFPFW_DL_DST):
1982 testField("dl_dst", [0xff]*6)
1983 if not (wildcards & ofp.OFPFW_DL_TYPE):
1984 testField("dl_type", 0xffff)
1985 if not (wildcards & ofp.OFPFW_DL_VLAN):
1986 testField("dl_vlan", 0xfff)
Rich Lane8d6ab272012-09-23 18:06:20 -07001987 # TODO dl_vlan_pcp
Ed Swierkb603b192012-12-12 15:38:49 -08001988 if not (wildcards & ofp.OFPFW_NW_SRC_ALL):
1989 testField("nw_src", 0xffffffff)
1990 if not (wildcards & ofp.OFPFW_NW_DST_ALL):
1991 testField("nw_dst", 0xffffffff)
1992 if not (wildcards & ofp.OFPFW_NW_TOS):
1993 testField("nw_tos", 0x3f)
1994 if not (wildcards & ofp.OFPFW_NW_PROTO):
1995 testField("nw_proto", 0xff)
1996 if not (wildcards & ofp.OFPFW_TP_SRC):
1997 testField("tp_src", 0xffff)
1998 if not (wildcards & ofp.OFPFW_TP_DST):
1999 testField("tp_dst", 0xffff)
Rich Lane8d6ab272012-09-23 18:06:20 -07002000
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002001class DirectBadPacketBase(base_tests.SimpleDataPlane):
2002 """
2003 Base class for sending single packets with single flow table entries.
2004 Used to verify matching of unusual packets and parsing/matching of
2005 corrupted packets.
2006
2007 The idea is to generate packets that may either be totally malformed or
2008 malformed just enough to trick the flow matcher into making mistakes.
2009
2010 Generate a 'bad' packet
2011 Generate and install a matching flow
2012 Add action to direct the packet to an egress port
2013 Send the packet to ingress dataplane port
2014 Verify the packet is received at the egress port only
2015 """
2016
2017 RESULT_MATCH = "MATCH"
2018 RESULT_NOMATCH = "NO MATCH"
2019 RESULT_ANY = "ANY MATCH"
2020
2021 def runTest(self):
2022 pass
2023 # TODO:
2024 # - ICMP?
2025 # - VLAN?
2026 # - action
2027
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002028 def createMatch(self, **kwargs):
2029 match = ofp.ofp_match()
2030 match.wildcards = ofp.OFPFW_ALL
2031 fields = {
2032 'dl_dst': ofp.OFPFW_DL_DST,
2033 'dl_src': ofp.OFPFW_DL_SRC,
2034 'dl_type': ofp.OFPFW_DL_TYPE,
2035 'dl_vlan': ofp.OFPFW_DL_VLAN,
2036 'nw_src': ofp.OFPFW_NW_SRC_MASK,
2037 'nw_dst': ofp.OFPFW_NW_DST_MASK,
2038 'nw_tos': ofp.OFPFW_NW_TOS,
2039 'nw_proto': ofp.OFPFW_NW_PROTO,
2040 'tp_src': ofp.OFPFW_TP_SRC,
2041 'tp_dst': ofp.OFPFW_TP_DST,
2042 }
2043 for key in kwargs:
2044 setattr(match, key, kwargs[key])
2045 match.wildcards &= ~fields[key]
2046 return match
2047
2048 def testPktsAgainstFlow(self, pkts, acts, match):
2049 if type(acts) != list:
2050 acts = [acts]
2051 for info in pkts:
2052 title, pkt, expected_result = info
2053 self.testPktAgainstFlow(title, pkt, acts, match, expected_result)
2054
2055 def testPktAgainstFlow(self, title, pkt, acts, match, expected_result):
2056 of_ports = config["port_map"].keys()
2057 of_ports.sort()
2058 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
2059
Rich Lane32bf9482013-01-03 17:26:30 -08002060 delete_all_flows(self.controller)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002061
2062 ingress_port = of_ports[0]
2063 egress_port = of_ports[1]
2064
2065 logging.info("Testing packet '%s', expect result %s" %
2066 (title, expected_result))
2067 logging.info("Ingress %s to egress %s" %
2068 (str(ingress_port), str(egress_port)))
2069 logging.info("Packet:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002070 logging.info(inspect_packet(pkt))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002071
2072 match.in_port = ingress_port
2073
Rich Lane28fa9272013-03-08 16:00:25 -08002074 request = ofp.message.flow_mod()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002075 request.match = match
Rich Lane44cf12d2012-10-15 11:10:45 -07002076 request.priority = 1
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002077
2078 request.buffer_id = 0xffffffff
2079 for act in acts:
2080 act.port = egress_port
Rich Lanee30455b2013-01-03 16:24:44 -08002081 request.actions.add(act)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002082
2083 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08002084 self.controller.message_send(request)
Rich Lane44cf12d2012-10-15 11:10:45 -07002085
2086 # This flow speeds up negative tests
2087 logging.info("Inserting catch-all flow")
Rich Lane28fa9272013-03-08 16:00:25 -08002088 request2 = ofp.message.flow_mod()
Rich Lane44cf12d2012-10-15 11:10:45 -07002089 request2.match = self.createMatch()
Dan Talayco3bfc8222013-02-13 18:18:57 -08002090 request2.match.wildcards &= ~ofp.OFPFW_IN_PORT
2091 request2.match.in_port = ingress_port
2092
Rich Lane44cf12d2012-10-15 11:10:45 -07002093 request2.priority = 0
Rich Lane28fa9272013-03-08 16:00:25 -08002094 act = ofp.action.action_output()
Rich Lane44cf12d2012-10-15 11:10:45 -07002095 act.port = ofp.OFPP_IN_PORT
2096 request2.actions.add(act)
Rich Lane5c3151c2013-01-03 17:15:41 -08002097 self.controller.message_send(request2)
Rich Lane44cf12d2012-10-15 11:10:45 -07002098
Rich Lane3a261d52013-01-03 17:45:08 -08002099 do_barrier(self.controller)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002100
Dan Talayco3bfc8222013-02-13 18:18:57 -08002101 pkt_str = str(pkt)
2102 if config["minsize"] > len(str(pkt)):
2103 pkt_str += '0' * (config["minsize"] - len(str(pkt)))
2104
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002105 logging.info("Sending packet to dp port " +
2106 str(ingress_port))
Dan Talayco3bfc8222013-02-13 18:18:57 -08002107 self.dataplane.send(ingress_port, pkt_str)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002108
2109 exp_pkt_arg = None
2110 exp_port = None
2111 if config["relax"]:
2112 exp_pkt_arg = pkt
2113 exp_port = egress_port
2114
Rich Lane44cf12d2012-10-15 11:10:45 -07002115 if expected_result == self.RESULT_MATCH:
2116 timeout = -1 # default timeout
2117 else:
2118 timeout = 1 # short timeout for negative tests
2119
2120 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(exp_pkt=exp_pkt_arg,
2121 timeout=timeout)
2122 if rcv_port == ingress_port:
2123 logging.debug("Packet matched catch-all flow")
2124 rcv_pkt = None
2125
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002126 if expected_result == self.RESULT_MATCH:
2127 self.assertTrue(rcv_pkt is not None,
2128 "Did not receive packet, expected a match")
2129 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
2130 str(rcv_port))
2131 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
2132 str_pkt = str(pkt)
2133 str_rcv_pkt = str(rcv_pkt)
2134 str_rcv_pkt = str_rcv_pkt[0:len(str_pkt)]
2135 if str_pkt != str_rcv_pkt:
2136 logging.error("Response packet does not match send packet")
2137 logging.info("Response:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002138 logging.info(inspect_packet(scapy.Ether(rcv_pkt)))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002139 self.assertEqual(str_pkt, str_rcv_pkt,
2140 'Response packet does not match send packet')
2141 elif expected_result == self.RESULT_NOMATCH:
2142 self.assertTrue(rcv_pkt is None, "Received packet, expected drop")
2143 else:
2144 logging.debug("Match or drop accepted. Result = %s" %
2145 ("match" if rcv_pkt is not None else "drop"))
2146
2147
2148class DirectBadIpTcpPacketsBase(DirectBadPacketBase):
2149 """
2150 Base class for TCP and UDP parsing/matching verification under corruptions
2151 """
2152 def runTest(self):
2153 pass
2154
2155 def runTestWithProto(self, protoName = 'TCP'):
2156 dl_dst='00:01:02:03:04:05'
2157 dl_src='00:06:07:08:09:0a'
2158 ip_src='192.168.0.1'
2159 ip_dst='192.168.0.2'
2160 ip_tos=0
2161 tcp_sport=1234
2162 tcp_dport=80
2163
2164 # Generate a proper packet for constructing a match
2165 tp = None
2166 if protoName == 'TCP':
2167 tp = scapy.TCP
2168 proto = 6
2169 elif protoName == 'UDP':
2170 tp = scapy.UDP
2171 proto = 17
2172 else:
2173 raise Exception("Passed in unknown proto name")
2174
2175 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
2176 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2177 tp(sport=tcp_sport, dport=tcp_dport)
2178 match = packet_to_flow_match(self, match_pkt)
2179 self.assertTrue(match is not None,
2180 "Could not generate flow match from pkt")
2181 match.wildcards &= ~ofp.OFPFW_IN_PORT
2182
2183 def testPacket(title, pkt, result):
Rich Lane28fa9272013-03-08 16:00:25 -08002184 act = ofp.action.action_output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002185 pkts = [
2186 [title, pkt, result]
2187 ]
2188 self.testPktsAgainstFlow(pkts, act, match)
2189
2190 # Try incomplete IP headers
2191 testPacket("Incomplete IP header (1 bytes)",
2192 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2193 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:1],
2194 self.RESULT_NOMATCH,
2195 )
2196 testPacket("Incomplete IP header (2 bytes)",
2197 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2198 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:2],
2199 self.RESULT_NOMATCH,
2200 )
2201 testPacket("Incomplete IP header (3 bytes)",
2202 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2203 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:3],
2204 self.RESULT_NOMATCH,
2205 )
2206 testPacket("Incomplete IP header (12 bytes)",
2207 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2208 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:12],
2209 self.RESULT_NOMATCH,
2210 )
2211 testPacket("Incomplete IP header (16 bytes)",
2212 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2213 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:16],
2214 self.RESULT_NOMATCH,
2215 )
2216 testPacket("Incomplete IP header (19 bytes)",
2217 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2218 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:19],
2219 self.RESULT_NOMATCH,
2220 )
2221
2222 # Try variations where the TCP header is missing or incomplete. As we
2223 # saw bugs before where buffers were reused and lengths weren't honored,
2224 # we initiatlize once with a non-matching full packet and once with a
2225 # matching full packet.
2226 testPacket("Non-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 + 1),
2230 self.RESULT_NOMATCH,
2231 )
2232 testPacket("Missing TCP header, buffer warmed with non-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("Matching TCP packet, warming buffer",
2238 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2239 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2240 tp(sport=tcp_sport, dport=tcp_dport),
2241 self.RESULT_MATCH,
2242 )
2243 testPacket("Missing TCP header, buffer warmed with match",
2244 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2245 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2246 self.RESULT_NOMATCH,
2247 )
2248 testPacket("Truncated TCP header: 2 bytes",
2249 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2250 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2251 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:2]),
2252 self.RESULT_NOMATCH,
2253 )
2254
2255 # Play with IP header length values that put the start of TCP either
2256 # inside the generated TCP header or beyond. In some cases it may even
2257 # be beyond the packet boundary. Also play with IP options and more
2258 # importantly IP total length corruptions.
2259 testPacket("TCP packet, corrupt ihl (0x6)",
2260 simple_tcp_packet(ip_ihl=6),
2261 self.RESULT_NOMATCH,
2262 )
2263 testPacket("TCP packet, corrupt ihl (0xf)",
2264 simple_tcp_packet(ip_ihl=0xf), # ihl = 15 * 4 = 60
2265 self.RESULT_NOMATCH,
2266 )
2267 testPacket("TCP packet, corrupt ihl and total length",
2268 simple_tcp_packet(ip_ihl=0xf, pktlen=56), # ihl = 15 * 4 = 60,
2269 self.RESULT_NOMATCH,
2270 )
2271 testPacket("Corrupt IPoption: First 4 bytes of matching TCP header",
2272 simple_tcp_packet(
2273 ip_options=scapy.IPOption('\x04\xd2\x00\x50'),
2274 tcp_dport=2, tcp_sport=2
2275 ),
2276 self.RESULT_NOMATCH,
2277 )
2278 testPacket("Missing TCP header, corrupt ihl",
2279 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2280 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto),
2281 self.RESULT_NOMATCH,
2282 )
2283 testPacket("Missing TCP header, corrupt total length",
2284 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2285 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, len= 100),
2286 self.RESULT_NOMATCH,
2287 )
2288 testPacket("Missing TCP header, corrupt ihl and total length",
2289 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2290 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto, len=43),
2291 self.RESULT_NOMATCH,
2292 )
2293 testPacket("Incomplete IP header (12 bytes), corrupt ihl and total length",
2294 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2295 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:12],
2296 self.RESULT_NOMATCH,
2297 )
2298 testPacket("Incomplete IP header (16 bytes), corrupt ihl and total length",
2299 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2300 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:16],
2301 self.RESULT_NOMATCH,
2302 )
2303
2304 # Try an incomplete TCP header that has enough bytes to carry source and
2305 # destination ports. As that is all we care about during matching, some
2306 # implementations may match and some may drop the packet
2307 testPacket("Incomplete TCP header: src/dst port present",
2308 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2309 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2310 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:4]),
2311 self.RESULT_ANY,
2312 )
2313
2314 for i in range(1):
2315 for length in range(40 / 4): # IPv4 options are a maximum of 40 in length
2316 bytes = "".join([("%c" % random.randint(0, 255)) for x in range(length * 4)])
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+1)
2320 pkt = eth / ip
2321 pkt = pkt / bytes
2322 pkt = pkt / str(tcp)
2323 testPacket("Random IP options len = %d - TP match must fail" % length * 4,
2324 pkt,
2325 self.RESULT_NOMATCH
2326 )
2327
2328 eth = scapy.Ether(dst=dl_dst, src=dl_src)
2329 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2330 tcp = tp(sport=tcp_sport, dport=tcp_dport)
2331 pkt = eth / ip
2332 pkt = pkt / bytes
2333 pkt = pkt / str(tcp)
2334
2335 testPacket("Random IP options len = %d - May match",
2336 pkt,
2337 self.RESULT_ANY
2338 )
2339
2340
2341class DirectBadIpTcpPackets(DirectBadIpTcpPacketsBase):
2342 """
2343 Verify IP/TCP parsing and matching. Focus on packet corruptions
2344 """
2345 def runTest(self):
2346 self.runTestWithProto(protoName = 'TCP')
2347
2348class DirectBadIpUdpPackets(DirectBadIpTcpPacketsBase):
2349 """
2350 Verify IP/UDP parsing and matching. Focus on packet corruptions
2351 """
2352 def runTest(self):
2353 self.runTestWithProto(protoName = 'UDP')
2354
2355class DirectBadLlcPackets(DirectBadPacketBase):
2356 """
2357 Verify LLC/SNAP parsing and matching. Focus on packet corruptions
2358 """
2359 def runTest(self):
2360 dl_dst='00:01:02:03:04:05'
2361 dl_src='00:06:07:08:09:0a'
2362 ip_src='192.168.0.1'
2363 ip_dst='192.168.0.2'
2364 ip_tos=0
2365 tcp_sport=1234
2366 tcp_dport=80
2367
2368 IS_SNAP_IP = 1
2369 IS_SNAP_IP_CORRUPT = 2
2370 IS_NOT_SNAP_IP = 3
2371
2372 def testPacketTcpMatch(title, llc):
2373 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
2374 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2375 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
2376 match = packet_to_flow_match(self, match_pkt)
2377 self.assertTrue(match is not None,
2378 "Could not generate flow match from pkt")
2379 match.wildcards &= ~ofp.OFPFW_IN_PORT
Rich Lane28fa9272013-03-08 16:00:25 -08002380 act = ofp.action.action_output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002381
2382 self.testPktsAgainstFlow(
2383 [[
2384 "TCP match - LLC frame correct length - %s" % title,
2385 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2386 self.RESULT_ANY,
2387 ]],
2388 act, match
2389 )
2390
2391 # Corrupt length field
2392 ethLen = random.randint(0, 1535)
2393 self.testPktsAgainstFlow(
2394 [[
2395 "TCP match - LLC frame corrupted length - %s" % title,
2396 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
2397 self.RESULT_ANY,
2398 ]],
2399 act, match
2400 )
2401
2402 def testPacketEthSrcDstMatch(title, llc):
2403 # Matching based on Ethernet source and destination
2404 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)
2405 match = packet_to_flow_match(self, match_pkt)
2406 self.assertTrue(match is not None,
2407 "Could not generate flow match from pkt")
2408 match.wildcards &= ~ofp.OFPFW_IN_PORT
2409 match.wildcards |= ofp.OFPFW_DL_TYPE
2410 self.testPktsAgainstFlow(
2411 [[
2412 "Eth addr match - LLC frame correct length- %s" % title,
2413 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2414 self.RESULT_MATCH,
2415 ]],
Rich Lane28fa9272013-03-08 16:00:25 -08002416 ofp.action.action_output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002417 )
2418
2419 # Corrupt length field
2420 ethLen = random.randint(0, 1535)
2421 self.testPktsAgainstFlow(
2422 [[
2423 "Eth addr match - LLC frame corrupted length- %s" % title,
2424 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
2425 self.RESULT_ANY,
2426 ]],
Rich Lane28fa9272013-03-08 16:00:25 -08002427 ofp.action.action_output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002428 )
2429
2430 def testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip):
2431 # Matching based on Ethernet source, destination and type
2432 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src, type=0x800)
2433 match = packet_to_flow_match(self, match_pkt)
2434 self.assertTrue(match is not None,
2435 "Could not generate flow match from pkt")
2436 match.wildcards &= ~ofp.OFPFW_IN_PORT
2437 if is_snap_ip == IS_SNAP_IP:
2438 is_match = self.RESULT_MATCH
2439 elif is_snap_ip == IS_SNAP_IP_CORRUPT:
2440 is_match = self.RESULT_ANY
2441 else:
2442 is_match = self.RESULT_NOMATCH
2443 self.testPktsAgainstFlow(
2444 [[
2445 "Eth addr+type match - LLC frame correct length - %s" % title,
2446 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2447 is_match,
2448 ]],
Rich Lane28fa9272013-03-08 16:00:25 -08002449 ofp.action.action_output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002450 )
2451
2452 # Corrupt length field
2453 ethLen = random.randint(0, 1535)
2454 self.testPktsAgainstFlow(
2455 [[
2456 "Eth addr+type match - LLC frame corrupted length - %s" % title,
2457 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
Christian Dickmanne9b6d252012-10-08 22:56:50 -07002458 self.RESULT_ANY,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002459 ]],
Rich Lane28fa9272013-03-08 16:00:25 -08002460 ofp.action.action_output(), match
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002461 )
2462
2463 def testPacket(title, llc, is_snap_ip):
2464 testPacketTcpMatch(title, llc)
2465 testPacketEthSrcDstMatch(title, llc)
2466 testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip)
2467
2468 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002469 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002470 IS_NOT_SNAP_IP,
2471 )
2472 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002473 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002474 IS_NOT_SNAP_IP,
2475 )
2476 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002477 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002478 IS_NOT_SNAP_IP,
2479 )
2480 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002481 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002482 IS_NOT_SNAP_IP,
2483 )
2484 testPacket("LLC - SNAP - Small bogus payload",
2485 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2486 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2487 IS_SNAP_IP_CORRUPT,
2488 )
2489 testPacket("LLC - SNAP - Max -1 bogus payload",
2490 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2491 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2492 IS_NOT_SNAP_IP,
2493 )
2494 testPacket("LLC - SNAP - Max bogus payload",
2495 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2496 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2497 IS_NOT_SNAP_IP,
2498 )
2499 testPacket("LLC - SNAP - IP - TCP",
2500 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2501 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2502 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2503 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2504 IS_SNAP_IP,
2505 )
2506
2507
2508class DirectLlcPackets(DirectBadPacketBase):
2509 """
2510 Verify LLC/SNAP parsing (valid and corrupted packets) and matching
2511 """
2512 def runTest(self):
2513 dl_dst='00:01:02:03:04:05'
2514 dl_src='00:06:07:08:09:0a'
2515 ip_src='192.168.0.1'
2516 ip_dst='192.168.0.2'
2517 ip_tos=0
2518 tcp_sport=1234
2519 tcp_dport=80
2520
2521 # Test ethertype in face of LLC/SNAP and OFP_DL_TYPE_NOT_ETH_TYPE
2522 IS_SNAP_NOT_IP = 1
2523 IS_SNAP_AND_IP = 2
2524 IS_NOT_SNAP = 3
2525
2526 def testPacketEthTypeIP(title, llc, is_snap):
2527 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src, type=0x800)
2528 match = packet_to_flow_match(self, match_pkt)
2529 self.assertTrue(match is not None,
2530 "Could not generate flow match from pkt")
2531 match.wildcards &= ~ofp.OFPFW_IN_PORT
2532 pkts = []
2533 if is_snap == IS_NOT_SNAP or is_snap == IS_SNAP_NOT_IP:
2534 result = self.RESULT_NOMATCH
2535 else:
2536 result = self.RESULT_MATCH
2537 pkts.append([
2538 "Ether type 0x800 match - %s" % title,
2539 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2540 result,
2541 ])
Rich Lane28fa9272013-03-08 16:00:25 -08002542 act = ofp.action.action_output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002543 self.testPktsAgainstFlow(pkts, act, match)
2544
2545 def testPacketEthTypeNotEth(title, llc, is_snap):
2546 match_pkt = scapy.Ether(dst = dl_dst, src = dl_src,
2547 type = ofp.OFP_DL_TYPE_NOT_ETH_TYPE)
2548 match = packet_to_flow_match(self, match_pkt)
2549 self.assertTrue(match is not None,
2550 "Could not generate flow match from pkt")
2551 match.wildcards &= ~ofp.OFPFW_IN_PORT
2552 pkts = []
2553 if is_snap == IS_NOT_SNAP:
2554 result = self.RESULT_MATCH
2555 else:
2556 result = self.RESULT_NOMATCH
2557 pkts.append([
2558 "Ether type OFP_DL_TYPE_NOT_ETH_TYPE match - %s" % title,
2559 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2560 result,
2561 ])
Rich Lane28fa9272013-03-08 16:00:25 -08002562 act = ofp.action.action_output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002563 self.testPktsAgainstFlow(pkts, act, match)
2564
2565 def testPacket(title, llc, is_snap):
2566 testPacketEthTypeIP(title, llc, is_snap)
2567 testPacketEthTypeNotEth(title, llc, is_snap)
2568
2569 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002570 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
2571 IS_NOT_SNAP,
2572 )
2573 testPacket("LLC (with information field) - No SNAP - No Payload",
2574 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x12) / "S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002575 IS_NOT_SNAP,
2576 )
2577 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002578 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002579 IS_NOT_SNAP,
2580 )
2581 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002582 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002583 IS_NOT_SNAP,
2584 )
2585 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002586 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002587 IS_NOT_SNAP,
2588 )
2589 testPacket("LLC - SNAP - Non-default OUI",
2590 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2591 scapy.SNAP(OUI=0x000001, code=0x800) / ("S" * 10),
2592 IS_NOT_SNAP,
2593 )
2594 testPacket("LLC - SNAP - Default OUI",
2595 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2596 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2597 IS_SNAP_AND_IP,
2598 )
2599 testPacket("LLC - SNAP - Max -1 bogus payload",
2600 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2601 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2602 IS_SNAP_NOT_IP,
2603 )
2604 testPacket("LLC - SNAP - Max bogus payload",
2605 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2606 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2607 IS_SNAP_NOT_IP,
2608 )
2609 testPacket("LLC - SNAP - IP - TCP",
2610 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2611 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2612 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2613 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2614 IS_SNAP_AND_IP,
2615 )
2616
2617
2618class DirectArpPackets(DirectBadPacketBase):
2619 """
2620 Verify ARP parsing (valid and corrupted packets) and ARP matching
2621 """
2622 def runTest(self):
2623 self.testArpHandling()
2624
2625 def testArpHandling(self):
2626 dl_dst='00:01:02:03:04:05'
2627 dl_src='00:06:07:08:09:0a'
2628 ip_src='192.168.0.1'
2629 ip_dst='192.168.0.2'
2630 ip_src2='192.168.1.1'
2631 ip_dst2='192.168.1.2'
2632 ip_tos=0
2633 tcp_sport=1234
2634 tcp_dport=80
2635
2636 def testPacket(title, arp_match, arp_pkt, result):
2637 pkts = []
2638
2639 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src) / arp_match
2640 match = packet_to_flow_match(self, match_pkt)
2641 self.assertTrue(match is not None,
2642 "Could not generate flow match from pkt")
2643 match.wildcards &= ~ofp.OFPFW_IN_PORT
2644
2645 pkts.append([
2646 title,
2647 scapy.Ether(dst=dl_dst, src=dl_src) / arp_pkt,
2648 result,
2649 ])
2650
Rich Lane28fa9272013-03-08 16:00:25 -08002651 act = ofp.action.action_output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002652 self.testPktsAgainstFlow(pkts, act, match)
2653
2654 testPacket("Basic ARP",
2655 scapy.ARP(psrc=ip_src, pdst=ip_dst, op = 1),
2656 scapy.ARP(hwdst = '00:00:00:00:00:00', hwsrc = dl_src,
2657 psrc = ip_src, pdst = ip_dst, hwlen = 6, plen = 4,
2658 ptype = 0x800, hwtype = 1, op = 1),
2659 self.RESULT_MATCH
2660 )
2661 # More stuff:
2662 # - Non matches on any property
2663 # - Corrupted hwlen and plen
2664 # - Other hwtype, ptype
2665 # - Truncated ARP pkt
2666
2667
2668class DirectVlanPackets(DirectBadPacketBase):
2669 """
2670 Verify VLAN parsing (valid and corrupted packets) and ARP matching
2671 """
2672 def runTest(self):
2673 dl_dst='00:01:02:03:04:05'
2674 dl_src='00:06:07:08:09:0a'
2675 ip_src='192.168.0.1'
2676 ip_dst='192.168.0.2'
2677 ip_src2='192.168.1.1'
2678 ip_dst2='192.168.1.2'
2679 ip_tos=0
2680 tcp_sport=1234
2681 tcp_dport=80
2682
2683 def testPacket(title, match, pkt, result):
2684 pkts = []
2685
2686 self.assertTrue(match is not None,
2687 "Could not generate flow match from pkt")
2688 match.wildcards &= ~ofp.OFPFW_IN_PORT
2689
2690 pkts.append([
2691 "%s" % title,
2692 pkt,
2693 result,
2694 ])
2695
Rich Lane28fa9272013-03-08 16:00:25 -08002696 act = ofp.action.action_output()
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002697 self.testPktsAgainstFlow(pkts, act, match)
2698
2699 testPacket("Basic MAC matching - IPv4 payload",
2700 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2701 scapy.Ether(dst=dl_dst, src=dl_src, type=0x800) / scapy.IP(),
2702 self.RESULT_MATCH
2703 )
2704 testPacket("Basic MAC matching - VMware beacon - no payload",
2705 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2706 scapy.Ether(dst=dl_dst, src=dl_src, type=0x8922),
2707 self.RESULT_MATCH
2708 )
2709 testPacket("Basic MAC matching - VMware beacon - with payload",
2710 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2711 scapy.Ether(dst=dl_dst, src=dl_src, type=0x8922)/ ("X" * 1),
2712 self.RESULT_MATCH
2713 )
2714 testPacket("Basic MAC matching - IPv6 payload",
2715 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2716 scapy.Ether(dst=dl_dst, src=dl_src) / scapy.IPv6(),
2717 self.RESULT_MATCH
2718 )
2719 testPacket("Basic MAC matching with VLAN tag present",
2720 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2721 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002722 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002723 scapy.IP(),
2724 self.RESULT_MATCH
2725 )
2726 testPacket("Basic MAC matching with VLAN tag present",
2727 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2728 dl_type=0x800),
2729 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002730 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002731 scapy.IP(),
2732 self.RESULT_MATCH
2733 )
2734 testPacket("Ether matching with VLAN tag present - No type match",
2735 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2736 dl_type=0x801),
2737 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002738 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002739 scapy.IP(),
2740 self.RESULT_NOMATCH
2741 )
2742 testPacket("Ether matching with VLAN tag present - No type match 0x8100",
2743 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2744 dl_type=0x8100),
2745 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002746 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002747 scapy.IP(),
2748 self.RESULT_NOMATCH
2749 )
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002750 testPacket("IP matching - VLAN tag",
2751 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2752 dl_type=0x0800,
2753 nw_src=parse_ip(ip_src), nw_dst=parse_ip(ip_dst)),
2754 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2755 scapy.Dot1Q(prio=5, vlan=1000)/ \
2756 scapy.IP(src=ip_src, dst=ip_dst),
2757 self.RESULT_MATCH
2758 )
2759 # XXX:
2760 # - Matching on VLAN ID and Prio
2761 # - Actions
2762
2763@nonstandard
2764class DirectVlanPacketsDoubleTagged(DirectVlanPackets):
2765 """
2766 VLAN parsing for double tagged packets. Spec is ambiguous about
2767 the treatment of these cases, so broken out to be non-standard
2768 """
2769 def runTest(self):
2770 dl_dst='00:01:02:03:04:05'
2771 dl_src='00:06:07:08:09:0a'
2772 ip_src='192.168.0.1'
2773 ip_dst='192.168.0.2'
2774 ip_src2='192.168.1.1'
2775 ip_dst2='192.168.1.2'
2776 ip_tos=0
2777 tcp_sport=1234
2778 tcp_dport=80
2779
2780 def testPacket(title, match, pkt, result):
2781 pkts = []
2782
2783 self.assertTrue(match is not None,
2784 "Could not generate flow match from pkt")
2785 match.wildcards &= ~ofp.OFPFW_IN_PORT
2786
2787 pkts.append([
2788 "%s" % title,
2789 pkt,
2790 result,
2791 ])
2792
Rich Lane28fa9272013-03-08 16:00:25 -08002793 act = ofp.action.action_output()
Dan Talaycoa3bf9652013-02-19 23:40:50 -08002794 self.testPktsAgainstFlow(pkts, act, match)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002795 testPacket("Ether matching with double VLAN tag - Wrong type match",
2796 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2797 dl_type=0x800),
2798 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002799 scapy.Dot1Q(prio=5, vlan=1000)/ \
2800 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002801 scapy.IP(),
2802 self.RESULT_NOMATCH
2803 )
2804 testPacket("Ether matching with double VLAN tag - Type match",
2805 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2806 dl_type=0x8100),
2807 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002808 scapy.Dot1Q(prio=5, vlan=1000)/ \
2809 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002810 scapy.IP(),
2811 self.RESULT_MATCH
2812 )
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002813
2814
2815
Dan Talayco9f47f4d2010-06-03 13:54:37 -07002816if __name__ == "__main__":
2817 print "Please run through oft script: ./oft --test_spec=basic"