blob: 6e2e573d53c96ee84d35d34abbc597c8a5ecc542 [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
24import oftest.cstruct as ofp
25import oftest.message as message
26import oftest.dataplane as dataplane
27import oftest.action as action
28import oftest.parse as parse
Rich Laneb90a1c42012-10-05 09:16:05 -070029import oftest.base_tests as base_tests
30import basic # for IterCases
Dan Talayco5eba8442010-03-10 13:58:43 -080031
Christian Dickmann8b59b4b2012-09-23 16:48:30 -070032from oftest.parse import parse_mac, parse_ip
33
Rich Laneda3b5ad2012-10-03 09:05:32 -070034from oftest.testutils import *
Dan Talayco5eba8442010-03-10 13:58:43 -080035
Dan Talayco551befa2010-07-15 17:05:32 -070036WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
Dan Talayco488fbc52012-04-09 16:30:41 -070037 ofp.OFPFW_DL_VLAN | ofp.OFPFW_DL_VLAN_PCP,
Dan Talayco551befa2010-07-15 17:05:32 -070038 ofp.OFPFW_DL_SRC,
39 ofp.OFPFW_DL_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070040 (ofp.OFPFW_DL_TYPE | ofp.OFPFW_NW_SRC_ALL |
41 ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS | ofp.OFPFW_NW_PROTO |
42 ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
43 (ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
Dan Talayco551befa2010-07-15 17:05:32 -070044 ofp.OFPFW_TP_SRC,
45 ofp.OFPFW_TP_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070046 ofp.OFPFW_NW_SRC_MASK,
47 ofp.OFPFW_NW_DST_MASK,
Dan Talayco551befa2010-07-15 17:05:32 -070048 ofp.OFPFW_DL_VLAN_PCP,
49 ofp.OFPFW_NW_TOS]
50
Dan Talayco488fbc52012-04-09 16:30:41 -070051NO_WILDCARD_VALUES = [(ofp.OFPFW_ALL ^ ofp.OFPFW_IN_PORT),
52 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN),
53 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_SRC),
54 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_DST),
55 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE),
56 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO),
57 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
58 ofp.OFPFW_TP_SRC),
59 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
60 ofp.OFPFW_TP_DST),
61 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
62 ofp.OFPFW_NW_SRC_MASK),
63 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
64 ofp.OFPFW_NW_DST_MASK),
65 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN ^ ofp.OFPFW_DL_VLAN_PCP),
66 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
67 ofp.OFPFW_NW_TOS)]
68
Dan Talayco551befa2010-07-15 17:05:32 -070069MODIFY_ACTION_VALUES = [ofp.OFPAT_SET_VLAN_VID,
70 ofp.OFPAT_SET_VLAN_PCP,
71 ofp.OFPAT_STRIP_VLAN,
72 ofp.OFPAT_SET_DL_SRC,
73 ofp.OFPAT_SET_DL_DST,
74 ofp.OFPAT_SET_NW_SRC,
75 ofp.OFPAT_SET_NW_DST,
76 ofp.OFPAT_SET_NW_TOS,
77 ofp.OFPAT_SET_TP_SRC,
78 ofp.OFPAT_SET_TP_DST]
79
Dan Talayco21381562010-07-17 00:34:47 -070080TEST_VID_DEFAULT = 2
81
Rich Lane97e99652013-01-02 17:23:20 -080082@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -070083class DirectPacket(base_tests.SimpleDataPlane):
Dan Talayco5eba8442010-03-10 13:58:43 -080084 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -070085 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -080086
87 Generate a packet
88 Generate and install a matching flow
89 Add action to direct the packet to an egress port
90 Send the packet to ingress dataplane port
91 Verify the packet is received at the egress port only
92 """
93 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -070094 self.handleFlow()
95
96 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -070097 of_ports = config["port_map"].keys()
Dan Talayco5eba8442010-03-10 13:58:43 -080098 of_ports.sort()
99 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
100
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700101 if (pkttype == 'ICMP'):
102 pkt = simple_icmp_packet()
103 else:
104 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700105 match = packet_to_flow_match(self, pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700106 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800107 self.assertTrue(match is not None,
108 "Could not generate flow match from pkt")
109 act = action.action_output()
110
111 for idx in range(len(of_ports)):
Rich Lane32bf9482013-01-03 17:26:30 -0800112 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700113
Dan Talayco5eba8442010-03-10 13:58:43 -0800114 ingress_port = of_ports[idx]
115 egress_port = of_ports[(idx + 1) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700116 logging.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700117 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800118
119 match.in_port = ingress_port
120
121 request = message.flow_mod()
122 request.match = match
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700123
Dan Talayco5eba8442010-03-10 13:58:43 -0800124 request.buffer_id = 0xffffffff
125 act.port = egress_port
Rich Lanee30455b2013-01-03 16:24:44 -0800126 request.actions.add(act)
Dan Talayco5eba8442010-03-10 13:58:43 -0800127
Rich Lane9a003812012-10-04 17:17:59 -0700128 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800129 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800130 do_barrier(self.controller)
Dan Talayco5eba8442010-03-10 13:58:43 -0800131
Rich Lane9a003812012-10-04 17:17:59 -0700132 logging.info("Sending packet to dp port " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800133 str(ingress_port))
134 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700135
136 exp_pkt_arg = None
137 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700138 if config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700139 exp_pkt_arg = pkt
140 exp_port = egress_port
141
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700142 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700143 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800144 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700145 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800146 str(rcv_port))
147 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
148 self.assertEqual(str(pkt), str(rcv_pkt),
149 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700150
Rich Lane97e99652013-01-02 17:23:20 -0800151@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -0700152class DirectPacketController(base_tests.SimpleDataPlane):
Rich Lane51c23b32012-07-27 16:37:25 -0700153 """
154 Send packet to the controller port
155
156 Generate a packet
157 Generate and install a matching flow
158 Add action to direct the packet to the controller port
159 Send the packet to ingress dataplane port
160 Verify the packet is received at the controller port
161 """
162 def runTest(self):
163 self.handleFlow()
164
165 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700166 of_ports = config["port_map"].keys()
Rich Lane51c23b32012-07-27 16:37:25 -0700167 of_ports.sort()
168 self.assertTrue(len(of_ports) > 0, "Not enough ports for test")
169
170 if (pkttype == 'ICMP'):
171 pkt = simple_icmp_packet()
172 else:
173 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700174 match = packet_to_flow_match(self, pkt)
Rich Lane51c23b32012-07-27 16:37:25 -0700175 match.wildcards &= ~ofp.OFPFW_IN_PORT
176 self.assertTrue(match is not None,
177 "Could not generate flow match from pkt")
178 act = action.action_output()
179
Rich Lane32bf9482013-01-03 17:26:30 -0800180 delete_all_flows(self.controller)
Rich Lane51c23b32012-07-27 16:37:25 -0700181
182 ingress_port = of_ports[0]
183 match.in_port = ingress_port
184
185 request = message.flow_mod()
186 request.match = match
187
188 request.buffer_id = 0xffffffff
189 act.port = ofp.OFPP_CONTROLLER
190 act.max_len = 65535
Rich Lanee30455b2013-01-03 16:24:44 -0800191 request.actions.add(act)
Rich Lane51c23b32012-07-27 16:37:25 -0700192
Rich Lane9a003812012-10-04 17:17:59 -0700193 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800194 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800195 do_barrier(self.controller)
Rich Lane51c23b32012-07-27 16:37:25 -0700196
Rich Lane9a003812012-10-04 17:17:59 -0700197 logging.info("Sending packet to dp port " +
Rich Lane51c23b32012-07-27 16:37:25 -0700198 str(ingress_port))
199 self.dataplane.send(ingress_port, str(pkt))
200
201 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
202
203 self.assertTrue(response is not None,
204 'Packet in message not received by controller')
205 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700206 logging.debug("Sent %s" % format_packet(pkt))
207 logging.debug("Resp %s" % format_packet(response.data))
Rich Lane51c23b32012-07-27 16:37:25 -0700208 self.assertTrue(False,
209 'Response packet does not match send packet' +
210 ' for controller port')
211
Howard Pershf97840f2012-04-10 16:30:42 -0700212
Rich Laneb90a1c42012-10-05 09:16:05 -0700213class DirectPacketQueue(base_tests.SimpleDataPlane):
Howard Pershf97840f2012-04-10 16:30:42 -0700214 """
215 Send packet to single queue on single egress port
216
217 Generate a packet
218 Generate and install a matching flow
219 Add action to direct the packet to an egress port and queue
220 Send the packet to ingress dataplane port
221 Verify the packet is received at the egress port only
222 """
223 def runTest(self):
224 self.handleFlow()
225
Howard Persh670b5672012-04-13 09:08:29 -0700226 def portQueuesGet(self, queue_stats, port_num):
227 result = []
228 for qs in queue_stats.stats:
229 if qs.port_no != port_num:
230 continue
231 result.append(qs.queue_id)
232 return result
233
Howard Pershf97840f2012-04-10 16:30:42 -0700234 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700235 of_ports = config["port_map"].keys()
Howard Pershf97840f2012-04-10 16:30:42 -0700236 of_ports.sort()
237 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
238
239 if (pkttype == 'ICMP'):
240 pkt = simple_icmp_packet()
241 else:
242 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700243 match = packet_to_flow_match(self, pkt)
Howard Pershf97840f2012-04-10 16:30:42 -0700244 match.wildcards &= ~ofp.OFPFW_IN_PORT
245 self.assertTrue(match is not None,
246 "Could not generate flow match from pkt")
247
Howard Persh670b5672012-04-13 09:08:29 -0700248 # Get queue stats from switch
249
250 request = message.queue_stats_request()
251 request.port_no = ofp.OFPP_ALL
252 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700253 (queue_stats, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700254 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
255
256 act = action.action_enqueue()
Howard Pershf97840f2012-04-10 16:30:42 -0700257
258 for idx in range(len(of_ports)):
Howard Pershf97840f2012-04-10 16:30:42 -0700259 ingress_port = of_ports[idx]
260 egress_port = of_ports[(idx + 1) % len(of_ports)]
Howard Pershf97840f2012-04-10 16:30:42 -0700261
Howard Persh670b5672012-04-13 09:08:29 -0700262 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700263 logging.info("Ingress " + str(ingress_port)
Howard Persh670b5672012-04-13 09:08:29 -0700264 + " to egress " + str(egress_port)
265 + " queue " + str(egress_queue_id)
266 )
Howard Pershf97840f2012-04-10 16:30:42 -0700267
Rich Lane32bf9482013-01-03 17:26:30 -0800268 delete_all_flows(self.controller)
Howard Pershf97840f2012-04-10 16:30:42 -0700269
Howard Persh670b5672012-04-13 09:08:29 -0700270 match.in_port = ingress_port
271
272 request = message.flow_mod()
273 request.match = match
Howard Pershf97840f2012-04-10 16:30:42 -0700274
Howard Persh670b5672012-04-13 09:08:29 -0700275 request.buffer_id = 0xffffffff
276 act.port = egress_port
277 act.queue_id = egress_queue_id
Rich Lanee30455b2013-01-03 16:24:44 -0800278 request.actions.add(act)
Howard Pershf97840f2012-04-10 16:30:42 -0700279
Rich Lane9a003812012-10-04 17:17:59 -0700280 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800281 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800282 do_barrier(self.controller)
Howard Pershf97840f2012-04-10 16:30:42 -0700283
Howard Persh670b5672012-04-13 09:08:29 -0700284 # Get current stats for selected egress queue
Howard Pershf97840f2012-04-10 16:30:42 -0700285
Howard Persh670b5672012-04-13 09:08:29 -0700286 request = message.queue_stats_request()
287 request.port_no = egress_port
288 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700289 (qs_before, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700290 self.assertNotEqual(qs_before, None, "Queue stats request failed")
291
Rich Lane9a003812012-10-04 17:17:59 -0700292 logging.info("Sending packet to dp port " +
Howard Persh670b5672012-04-13 09:08:29 -0700293 str(ingress_port))
294 self.dataplane.send(ingress_port, str(pkt))
295
296 exp_pkt_arg = None
297 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700298 if config["relax"]:
Howard Persh670b5672012-04-13 09:08:29 -0700299 exp_pkt_arg = pkt
300 exp_port = egress_port
301
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700302 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Howard Persh670b5672012-04-13 09:08:29 -0700303 exp_pkt=exp_pkt_arg)
304 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700305 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Howard Persh670b5672012-04-13 09:08:29 -0700306 str(rcv_port))
307 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
308 self.assertEqual(str(pkt), str(rcv_pkt),
309 'Response packet does not match send packet')
310
Ed Swierkb8a86512012-04-18 18:45:58 -0700311 # FIXME: instead of sleeping, keep requesting queue stats until
312 # the expected queue counter increases or some large timeout is
313 # reached
314 time.sleep(2)
315
Howard Persh670b5672012-04-13 09:08:29 -0700316 # Get current stats for selected egress queue again
317
318 request = message.queue_stats_request()
319 request.port_no = egress_port
320 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700321 (qs_after, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700322 self.assertNotEqual(qs_after, None, "Queue stats request failed")
323
324 # Make sure that tx packet counter for selected egress queue was
325 # incremented
326
Ed Swierk22f59152012-04-17 16:36:47 -0700327 self.assertEqual(qs_after.stats[0].tx_packets, \
328 qs_before.stats[0].tx_packets + 1, \
Howard Persh670b5672012-04-13 09:08:29 -0700329 "Verification of egress queue tx packet count failed"
330 )
331
332
Rich Laneb90a1c42012-10-05 09:16:05 -0700333class DirectPacketControllerQueue(base_tests.SimpleDataPlane):
Ken Chiang899ff8e2012-05-23 18:26:12 -0700334 """
335 Send a packet from each of the openflow ports
336 to each of the queues configured on the controller port.
337 If no queues have been configured, no packets are sent.
Howard Pershf97840f2012-04-10 16:30:42 -0700338
Ken Chiang899ff8e2012-05-23 18:26:12 -0700339 Generate a packet
340 Generate and install a matching flow
341 Add action to direct the packet to one of the controller port queues
342 Send the packet to ingress dataplane port
343 Verify the packet is received on the controller port queue
344 """
345 def runTest(self):
346 self.handleFlow()
347
348 def portQueuesGet(self, queue_stats, port_num):
349 result = []
350 for qs in queue_stats.stats:
351 if qs.port_no != port_num:
352 continue
353 result.append(qs.queue_id)
354 return result
355
356 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700357 of_ports = config["port_map"].keys()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700358 of_ports.sort()
359 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
360
361 if (pkttype == 'ICMP'):
362 pkt = simple_icmp_packet()
363 else:
364 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700365 match = packet_to_flow_match(self, pkt)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700366 match.wildcards &= ~ofp.OFPFW_IN_PORT
367 self.assertTrue(match is not None,
368 "Could not generate flow match from pkt")
369
370 # Get queue stats from switch
371
372 request = message.queue_stats_request()
373 request.port_no = ofp.OFPP_CONTROLLER
374 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700375 (queue_stats, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700376 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
Rich Laneb8c845a2012-12-31 17:23:51 -0800377 if queue_stats.header.type == ofp.OFPT_ERROR:
378 skip_message_emit(self, "Enqueue packet to controller")
379 return
Ken Chiang899ff8e2012-05-23 18:26:12 -0700380
381 act = action.action_enqueue()
382
383 for idx in range(len(of_ports)):
384 ingress_port = of_ports[idx]
385 egress_port = ofp.OFPP_CONTROLLER
386
Rich Lane9a003812012-10-04 17:17:59 -0700387 logging.info("Ingress port " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700388 + ", controller port queues "
389 + str(self.portQueuesGet(queue_stats, egress_port)))
390
391 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700392 logging.info("Ingress " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700393 + " to egress " + str(egress_port)
394 + " queue " + str(egress_queue_id)
395 )
396
Rich Lane32bf9482013-01-03 17:26:30 -0800397 delete_all_flows(self.controller)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700398
399 match.in_port = ingress_port
400
401 request = message.flow_mod()
402 request.match = match
403
404 request.buffer_id = 0xffffffff
405 act.port = egress_port
406 act.queue_id = egress_queue_id
Rich Lanee30455b2013-01-03 16:24:44 -0800407 request.actions.add(act)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700408
Rich Lane9a003812012-10-04 17:17:59 -0700409 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800410 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800411 do_barrier(self.controller)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700412
413 # Get current stats for selected egress queue
414
415 request = message.queue_stats_request()
416 request.port_no = egress_port
417 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700418 (qs_before, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700419 self.assertNotEqual(qs_before, None, "Queue stats request failed")
420
Rich Lane9a003812012-10-04 17:17:59 -0700421 logging.info("Sending packet to dp port " +
Ken Chiang899ff8e2012-05-23 18:26:12 -0700422 str(ingress_port))
423 self.dataplane.send(ingress_port, str(pkt))
424
425 exp_pkt_arg = None
426 exp_port = None
427
Rich Lanee5779d32012-10-05 17:56:04 -0700428 count = 0
Ken Chiang899ff8e2012-05-23 18:26:12 -0700429 while True:
Dan Talaycoc689a792012-09-28 14:22:53 -0700430 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700431 if not response: # Timeout
432 break
433 if dataplane.match_exp_pkt(pkt, response.data): # Got match
434 break
Rich Lane477f4812012-10-04 22:49:00 -0700435 if not config["relax"]: # Only one attempt to match
Ken Chiang899ff8e2012-05-23 18:26:12 -0700436 break
437 count += 1
438 if count > 10: # Too many tries
439 break
440
441 self.assertTrue(response is not None,
442 'Packet in message not received by controller')
443 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700444 logging.debug("Sent %s" % format_packet(pkt))
445 logging.debug("Resp %s" % format_packet(response.data))
Ken Chiang899ff8e2012-05-23 18:26:12 -0700446 self.assertTrue(False,
447 'Response packet does not match send packet' +
448 ' for controller port')
449
450 # FIXME: instead of sleeping, keep requesting queue stats until
451 # the expected queue counter increases or some large timeout is
452 # reached
453 time.sleep(2)
454
455 # Get current stats for selected egress queue again
456
457 request = message.queue_stats_request()
458 request.port_no = egress_port
459 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700460 (qs_after, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700461 self.assertNotEqual(qs_after, None, "Queue stats request failed")
462
463 # Make sure that tx packet counter for selected egress queue was
464 # incremented
465
466 self.assertEqual(qs_after.stats[0].tx_packets, \
467 qs_before.stats[0].tx_packets + 1, \
468 "Verification of egress queue tx packet count failed"
469 )
470
Howard Pershf97840f2012-04-10 16:30:42 -0700471
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700472class DirectPacketICMP(DirectPacket):
473 """
474 Send ICMP packet to single egress port
475
476 Generate a ICMP packet
477 Generate and install a matching flow
478 Add action to direct the packet to an egress port
479 Send the packet to ingress dataplane port
480 Verify the packet is received at the egress port only
481 Difference from DirectPacket test is that sent packet is ICMP
482 """
483 def runTest(self):
484 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700485
Rich Laneb90a1c42012-10-05 09:16:05 -0700486class DirectTwoPorts(base_tests.SimpleDataPlane):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700487 """
488 Send packet to two egress ports
489
490 Generate a packet
491 Generate and install a matching flow
492 Add action to direct the packet to two egress ports
493 Send the packet to ingress dataplane port
494 Verify the packet is received at the two egress ports
495 """
496 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700497 of_ports = config["port_map"].keys()
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700498 of_ports.sort()
499 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
500
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700501 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700502 match = packet_to_flow_match(self, pkt)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700503 match.wildcards &= ~ofp.OFPFW_IN_PORT
504 self.assertTrue(match is not None,
505 "Could not generate flow match from pkt")
506 act = action.action_output()
507
508 for idx in range(len(of_ports)):
Rich Lane32bf9482013-01-03 17:26:30 -0800509 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700510
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700511 ingress_port = of_ports[idx]
512 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
513 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700514 logging.info("Ingress " + str(ingress_port) +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700515 " to egress " + str(egress_port1) + " and " +
516 str(egress_port2))
517
518 match.in_port = ingress_port
519
520 request = message.flow_mod()
521 request.match = match
522 request.buffer_id = 0xffffffff
523 act.port = egress_port1
Rich Lanee30455b2013-01-03 16:24:44 -0800524 request.actions.add(act)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700525 act.port = egress_port2
Rich Lanee30455b2013-01-03 16:24:44 -0800526 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700527 # logging.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700528
Rich Lane9a003812012-10-04 17:17:59 -0700529 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800530 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800531 do_barrier(self.controller)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700532
Rich Lane9a003812012-10-04 17:17:59 -0700533 logging.info("Sending packet to dp port " +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700534 str(ingress_port))
535 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700536 yes_ports = set([egress_port1, egress_port2])
537 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700538
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700539 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Rich Lane2014f9b2012-10-05 15:29:40 -0700540 self)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700541
Rich Laneb90a1c42012-10-05 09:16:05 -0700542class DirectMCNonIngress(base_tests.SimpleDataPlane):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700543 """
544 Multicast to all non-ingress ports
545
546 Generate a packet
547 Generate and install a matching flow
548 Add action to direct the packet to all non-ingress ports
549 Send the packet to ingress dataplane port
550 Verify the packet is received at all non-ingress ports
551
552 Does not use the flood action
553 """
554 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700555 of_ports = config["port_map"].keys()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700556 of_ports.sort()
557 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
558
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700559 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700560 match = packet_to_flow_match(self, pkt)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700561 match.wildcards &= ~ofp.OFPFW_IN_PORT
562 self.assertTrue(match is not None,
563 "Could not generate flow match from pkt")
564 act = action.action_output()
565
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700566 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800567 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700568
Rich Lane9a003812012-10-04 17:17:59 -0700569 logging.info("Ingress " + str(ingress_port) +
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700570 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700571 match.in_port = ingress_port
572
573 request = message.flow_mod()
574 request.match = match
575 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700576 for egress_port in of_ports:
577 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700578 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700579 act.port = egress_port
Rich Lanee30455b2013-01-03 16:24:44 -0800580 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700581 logging.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700582
Rich Lane9a003812012-10-04 17:17:59 -0700583 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800584 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800585 do_barrier(self.controller)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700586
Rich Lane9a003812012-10-04 17:17:59 -0700587 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700588 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700589 yes_ports = set(of_ports).difference([ingress_port])
590 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700591 self)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700592
Dan Talayco32fa6542010-05-11 15:54:08 -0700593
Rich Laneb90a1c42012-10-05 09:16:05 -0700594class DirectMC(base_tests.SimpleDataPlane):
Dan Talayco32fa6542010-05-11 15:54:08 -0700595 """
596 Multicast to all ports including ingress
597
598 Generate a packet
599 Generate and install a matching flow
600 Add action to direct the packet to all non-ingress ports
601 Send the packet to ingress dataplane port
602 Verify the packet is received at all ports
603
604 Does not use the flood action
605 """
606 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700607 of_ports = config["port_map"].keys()
Dan Talayco32fa6542010-05-11 15:54:08 -0700608 of_ports.sort()
609 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
610
Dan Talayco32fa6542010-05-11 15:54:08 -0700611 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700612 match = packet_to_flow_match(self, pkt)
Dan Talayco32fa6542010-05-11 15:54:08 -0700613 match.wildcards &= ~ofp.OFPFW_IN_PORT
614 self.assertTrue(match is not None,
615 "Could not generate flow match from pkt")
616 act = action.action_output()
617
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700618 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800619 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700620
Rich Lane9a003812012-10-04 17:17:59 -0700621 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700622 match.in_port = ingress_port
623
624 request = message.flow_mod()
625 request.match = match
626 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700627 for egress_port in of_ports:
628 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700629 act.port = ofp.OFPP_IN_PORT
630 else:
631 act.port = egress_port
Rich Lanee30455b2013-01-03 16:24:44 -0800632 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700633 # logging.info(request.show())
Dan Talayco2e77a842010-05-12 15:39:46 -0700634
Rich Lane9a003812012-10-04 17:17:59 -0700635 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800636 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800637 do_barrier(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700638
Rich Lane9a003812012-10-04 17:17:59 -0700639 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700640 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700641 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco2e77a842010-05-12 15:39:46 -0700642
Rich Laneb90a1c42012-10-05 09:16:05 -0700643class Flood(base_tests.SimpleDataPlane):
Dan Talayco2e77a842010-05-12 15:39:46 -0700644 """
645 Flood to all ports except ingress
646
Dan Talaycofcc09912013-02-08 23:46:08 -0800647 Make sure noflood bit is off on all ports
Dan Talayco2e77a842010-05-12 15:39:46 -0700648 Generate a packet
649 Generate and install a matching flow
650 Add action to flood the packet
651 Send the packet to ingress dataplane port
652 Verify the packet is received at all other ports
653 """
654 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700655 of_ports = config["port_map"].keys()
Dan Talayco2e77a842010-05-12 15:39:46 -0700656 of_ports.sort()
657 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
658
659 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700660 match = packet_to_flow_match(self, pkt)
Dan Talayco2e77a842010-05-12 15:39:46 -0700661 match.wildcards &= ~ofp.OFPFW_IN_PORT
662 self.assertTrue(match is not None,
663 "Could not generate flow match from pkt")
664 act = action.action_output()
665
Dan Talaycofcc09912013-02-08 23:46:08 -0800666 for of_port in of_ports:
667 # Clear relevant bits that might block ports
668 rv = port_config_set(self.controller, of_port, 0,
669 ofp.OFPPC_NO_FLOOD | ofp.OFPPC_NO_FWD |
670 ofp.OFPPC_PORT_DOWN)
671 self.assertTrue(rv == 0, "Did not set port config")
672 logging.debug("Enabled and cleared no-flood for port " + str(of_port))
673
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700674 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800675 delete_all_flows(self.controller)
Dan Talayco2e77a842010-05-12 15:39:46 -0700676
Rich Lane9a003812012-10-04 17:17:59 -0700677 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700678 match.in_port = ingress_port
679
680 request = message.flow_mod()
681 request.match = match
682 request.buffer_id = 0xffffffff
683 act.port = ofp.OFPP_FLOOD
Rich Lanee30455b2013-01-03 16:24:44 -0800684 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700685 logging.info(request.show())
Dan Talayco32fa6542010-05-11 15:54:08 -0700686
Rich Lane9a003812012-10-04 17:17:59 -0700687 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800688 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800689 do_barrier(self.controller)
Dan Talayco32fa6542010-05-11 15:54:08 -0700690
Rich Lane9a003812012-10-04 17:17:59 -0700691 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco32fa6542010-05-11 15:54:08 -0700692 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700693 yes_ports = set(of_ports).difference([ingress_port])
694 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700695 self)
Dan Talayco3be5b062010-05-12 15:46:21 -0700696
Rich Laneb90a1c42012-10-05 09:16:05 -0700697class FloodPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco3be5b062010-05-12 15:46:21 -0700698 """
699 Flood to all ports plus send to ingress port
700
701 Generate a packet
702 Generate and install a matching flow
703 Add action to flood the packet
704 Add action to send to ingress port
705 Send the packet to ingress dataplane port
706 Verify the packet is received at all other ports
707 """
708 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700709 of_ports = config["port_map"].keys()
Dan Talayco3be5b062010-05-12 15:46:21 -0700710 of_ports.sort()
711 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
712
713 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700714 match = packet_to_flow_match(self, pkt)
Dan Talayco3be5b062010-05-12 15:46:21 -0700715 match.wildcards &= ~ofp.OFPFW_IN_PORT
716 self.assertTrue(match is not None,
717 "Could not generate flow match from pkt")
718 act = action.action_output()
719
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700720 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800721 delete_all_flows(self.controller)
Dan Talayco3be5b062010-05-12 15:46:21 -0700722
Rich Lane9a003812012-10-04 17:17:59 -0700723 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700724 match.in_port = ingress_port
725
726 request = message.flow_mod()
727 request.match = match
728 request.buffer_id = 0xffffffff
729 act.port = ofp.OFPP_FLOOD
Rich Lanee30455b2013-01-03 16:24:44 -0800730 request.actions.add(act)
Dan Talayco4aa13122010-05-12 15:54:44 -0700731 act.port = ofp.OFPP_IN_PORT
Rich Lanee30455b2013-01-03 16:24:44 -0800732 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700733 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700734
Rich Lane9a003812012-10-04 17:17:59 -0700735 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800736 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800737 do_barrier(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700738
Rich Lane9a003812012-10-04 17:17:59 -0700739 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700740 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700741 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco4aa13122010-05-12 15:54:44 -0700742
Rich Laneb90a1c42012-10-05 09:16:05 -0700743class All(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700744 """
745 Send to OFPP_ALL port
746
747 Generate a packet
748 Generate and install a matching flow
749 Add action to forward to OFPP_ALL
750 Send the packet to ingress dataplane port
751 Verify the packet is received at all other ports
752 """
753 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700754 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700755 of_ports.sort()
756 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
757
758 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700759 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700760 match.wildcards &= ~ofp.OFPFW_IN_PORT
761 self.assertTrue(match is not None,
762 "Could not generate flow match from pkt")
763 act = action.action_output()
764
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700765 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800766 delete_all_flows(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700767
Rich Lane9a003812012-10-04 17:17:59 -0700768 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700769 match.in_port = ingress_port
770
771 request = message.flow_mod()
772 request.match = match
773 request.buffer_id = 0xffffffff
774 act.port = ofp.OFPP_ALL
Rich Lanee30455b2013-01-03 16:24:44 -0800775 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700776 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700777
Rich Lane9a003812012-10-04 17:17:59 -0700778 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800779 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800780 do_barrier(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700781
Rich Lane9a003812012-10-04 17:17:59 -0700782 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700783 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700784 yes_ports = set(of_ports).difference([ingress_port])
785 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700786 self)
Dan Talayco4aa13122010-05-12 15:54:44 -0700787
Rich Laneb90a1c42012-10-05 09:16:05 -0700788class AllPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700789 """
790 Send to OFPP_ALL port and ingress port
791
792 Generate a packet
793 Generate and install a matching flow
794 Add action to forward to OFPP_ALL
795 Add action to forward to ingress port
796 Send the packet to ingress dataplane port
797 Verify the packet is received at all other ports
798 """
799 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700800 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700801 of_ports.sort()
802 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
803
804 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700805 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700806 match.wildcards &= ~ofp.OFPFW_IN_PORT
807 self.assertTrue(match is not None,
808 "Could not generate flow match from pkt")
809 act = action.action_output()
810
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700811 for ingress_port in of_ports:
Rich Lane32bf9482013-01-03 17:26:30 -0800812 delete_all_flows(self.controller)
Dan Talayco4aa13122010-05-12 15:54:44 -0700813
Rich Lane9a003812012-10-04 17:17:59 -0700814 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700815 match.in_port = ingress_port
816
817 request = message.flow_mod()
818 request.match = match
819 request.buffer_id = 0xffffffff
820 act.port = ofp.OFPP_ALL
Rich Lanee30455b2013-01-03 16:24:44 -0800821 request.actions.add(act)
Dan Talayco3be5b062010-05-12 15:46:21 -0700822 act.port = ofp.OFPP_IN_PORT
Rich Lanee30455b2013-01-03 16:24:44 -0800823 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700824 logging.info(request.show())
Dan Talayco3be5b062010-05-12 15:46:21 -0700825
Rich Lane9a003812012-10-04 17:17:59 -0700826 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800827 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800828 do_barrier(self.controller)
Dan Talayco3be5b062010-05-12 15:46:21 -0700829
Rich Lane9a003812012-10-04 17:17:59 -0700830 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco3be5b062010-05-12 15:46:21 -0700831 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700832 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700833
Rich Laneb90a1c42012-10-05 09:16:05 -0700834class FloodMinusPort(base_tests.SimpleDataPlane):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700835 """
836 Config port with No_Flood and test Flood action
837
838 Generate a packet
839 Generate a matching flow
840 Add action to forward to OFPP_ALL
841 Set port to no-flood
842 Send the packet to ingress dataplane port
843 Verify the packet is received at all other ports except
844 the ingress port and the no_flood port
845 """
846 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700847 of_ports = config["port_map"].keys()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700848 of_ports.sort()
849 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
850
851 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700852 match = packet_to_flow_match(self, pkt)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700853 match.wildcards &= ~ofp.OFPFW_IN_PORT
854 self.assertTrue(match is not None,
855 "Could not generate flow match from pkt")
856 act = action.action_output()
857
Rich Lane4b9e38c2012-12-06 16:33:20 -0800858 # Clear OFPPC_NO_FLOOD on each port
859 for of_port in of_ports:
860 rv = port_config_set(self.controller, of_port,
861 0, ofp.OFPPC_NO_FLOOD)
862 self.assertEqual(rv, 0, "Failed to set port config")
863
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700864 for idx in range(len(of_ports)):
Rich Lane32bf9482013-01-03 17:26:30 -0800865 delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700866
867 ingress_port = of_ports[idx]
868 no_flood_idx = (idx + 1) % len(of_ports)
869 no_flood_port = of_ports[no_flood_idx]
870 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700871 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700872 self.assertEqual(rv, 0, "Failed to set port config")
873
874 match.in_port = ingress_port
875
876 request = message.flow_mod()
877 request.match = match
878 request.buffer_id = 0xffffffff
879 act.port = ofp.OFPP_FLOOD
Rich Lanee30455b2013-01-03 16:24:44 -0800880 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700881 logging.info(request.show())
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700882
Rich Lane9a003812012-10-04 17:17:59 -0700883 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800884 self.controller.message_send(request)
Rich Lane3a261d52013-01-03 17:45:08 -0800885 do_barrier(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700886
Rich Lane9a003812012-10-04 17:17:59 -0700887 logging.info("Sending packet to dp port " + str(ingress_port))
888 logging.info("No flood port is " + str(no_flood_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700889 self.dataplane.send(ingress_port, str(pkt))
890 no_ports = set([ingress_port, no_flood_port])
891 yes_ports = set(of_ports).difference(no_ports)
Rich Lane2014f9b2012-10-05 15:29:40 -0700892 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700893
894 # Turn no flood off again
895 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700896 0, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700897 self.assertEqual(rv, 0, "Failed to reset port config")
Rich Lane3a261d52013-01-03 17:45:08 -0800898 do_barrier(self.controller)
Rich Lane4ecc1f42012-12-06 16:35:24 -0800899
900 # Check that packets are now flooded to no_flood_port
901 logging.info("Sending packet to dp port " + str(ingress_port))
902 self.dataplane.send(ingress_port, str(pkt))
903 no_ports = set([ingress_port])
904 yes_ports = set(of_ports).difference(no_ports)
905 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700906
907 #@todo Should check no other packets received
908
Dan Talayco21381562010-07-17 00:34:47 -0700909
910
Dan Talayco551befa2010-07-15 17:05:32 -0700911################################################################
912
Rich Laneb90a1c42012-10-05 09:16:05 -0700913class BaseMatchCase(base_tests.SimpleDataPlane):
Dan Talayco551befa2010-07-15 17:05:32 -0700914 def setUp(self):
Rich Laneb90a1c42012-10-05 09:16:05 -0700915 base_tests.SimpleDataPlane.setUp(self)
Dan Talayco551befa2010-07-15 17:05:32 -0700916 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -0700917 logging.info("BaseMatchCase")
Dan Talayco551befa2010-07-15 17:05:32 -0700918
919class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700920 """
Dan Talayco551befa2010-07-15 17:05:32 -0700921 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700922
923 Generate a packet
924 Generate and install a matching flow without wildcard mask
925 Add action to forward to a port
926 Send the packet to the port
927 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700928 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700929
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700930 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700931 flow_match_test(self, config["port_map"])
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700932
Dan Talayco551befa2010-07-15 17:05:32 -0700933class ExactMatchTagged(BaseMatchCase):
934 """
935 Exact match for all port pairs with tagged pkts
936 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700937
Dan Talayco551befa2010-07-15 17:05:32 -0700938 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -0700939 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Lane477f4812012-10-04 22:49:00 -0700940 flow_match_test(self, config["port_map"], dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700941
Rich Lane0a4f6372013-01-02 14:40:22 -0800942@disabled
Dan Talayco551befa2010-07-15 17:05:32 -0700943class ExactMatchTaggedMany(BaseMatchCase):
944 """
945 ExactMatchTagged with many VLANS
946 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700947
Dan Talayco551befa2010-07-15 17:05:32 -0700948 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700949 for vid in range(2,100,10):
Rich Lane477f4812012-10-04 22:49:00 -0700950 flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
Dan Talayco551befa2010-07-15 17:05:32 -0700951 for vid in range(100,4000,389):
Rich Lane477f4812012-10-04 22:49:00 -0700952 flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
953 flow_match_test(self, config["port_map"], dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700954
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700955class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700956 """
957 SingleWildcardMatchPriority
958 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700959
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700960 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700961 self.pkt = simple_tcp_packet()
962 self.flowMsgs = {}
963
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700964 def _ClearTable(self):
Rich Lane32bf9482013-01-03 17:26:30 -0800965 delete_all_flows(self.controller)
Rich Lane3a261d52013-01-03 17:45:08 -0800966 do_barrier(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700967
968 def runTest(self):
969
970 self._Init()
Rich Lane477f4812012-10-04 22:49:00 -0700971 of_ports = config["port_map"].keys()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700972 of_ports.sort()
973
974 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700975 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700976
977 # Run several combinations, each at lower priority settings.
978 # At the end of each call to runPrioFlows(), the table should
979 # be empty. If its not, we'll catch it as the priorities decreases
980 portA = of_ports[0]
981 portB = of_ports[1]
982 portC = of_ports[2]
983
984 # TODO -- these priority numbers should be validated somehow?
985 self.runPrioFlows(portA, portB, portC, 1000, 999)
986 self.runPrioFlows(portB, portC, portA, 998, 997)
987 self.runPrioFlows(portC, portA, portB, 996, 995)
988 self.runPrioFlows(portA, portC, portB, 994, 993)
989
990
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700991
992 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
993 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700994
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700995 if clearTable:
996 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700997
998 # Sanity check flow at lower priority from pA to pB
Rich Lane9a003812012-10-04 17:17:59 -0700999 logging.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001000 % (portA, portB, portC, prioHigher, prioLower))
1001
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001002 # Sanity check flow at lower priority from pA to pC
1003 self.installFlow(prioLower, portA, portC)
1004 self.verifyFlow(portA, portC)
1005 self.removeFlow(prioLower)
1006
1007 # Install and verify pA->pB @ prioLower
1008 self.installFlow(prioLower, portA, portB)
1009 self.verifyFlow(portA, portB)
1010
1011 # Install and verify pA->pC @ prioHigher, should override pA->pB
1012 self.installFlow(prioHigher, portA, portC)
1013 self.verifyFlow(portA, portC)
1014 # remove pA->pC
1015 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001016 # Old flow pA -> pB @ prioLower should still be active
1017 self.verifyFlow(portA, portB)
1018 self.removeFlow(prioLower)
1019
1020 # Table should be empty at this point, leave it alone as
1021 # an assumption for future test runs
1022
1023
1024
Ed Swierk99a74de2012-08-22 06:40:54 -07001025 def installFlow(self, prio, inp, egp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001026 wildcards=ofp.OFPFW_DL_SRC):
Ed Swierk99a74de2012-08-22 06:40:54 -07001027 wildcards |= required_wildcards(self)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001028 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001029 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001030 egr_ports=egp)
1031 request.priority = prio
Rich Lane9a003812012-10-04 17:17:59 -07001032 logging.debug("Install flow with priority " + str(prio))
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001033 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001034 self.flowMsgs[prio] = request
1035
1036 def removeFlow(self, prio):
1037 if self.flowMsgs.has_key(prio):
1038 msg = self.flowMsgs[prio]
1039 msg.command = ofp.OFPFC_DELETE_STRICT
1040 # This *must* be set for DELETE
1041 msg.out_port = ofp.OFPP_NONE
Rich Lane9a003812012-10-04 17:17:59 -07001042 logging.debug("Remove flow with priority " + str(prio))
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001043 self.controller.message_send(msg)
Rich Lane3a261d52013-01-03 17:45:08 -08001044 do_barrier(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001045 else:
1046 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001047
1048
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001049 def verifyFlow(self, inp, egp, pkt=None):
1050 if pkt == None:
1051 pkt = self.pkt
1052
Rich Lane9a003812012-10-04 17:17:59 -07001053 logging.info("Pkt match test: " + str(inp) + " to " + str(egp))
1054 logging.debug("Send packet: " + str(inp) + " to " + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001055 self.dataplane.send(inp, str(pkt))
1056 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001057
1058
1059
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001060class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
1061
1062 def runTest(self):
1063
1064 self._Init()
1065
Rich Lane477f4812012-10-04 22:49:00 -07001066 of_ports = config["port_map"].keys()
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001067 of_ports.sort()
1068
1069 # Install an entry from 0 -> 1 @ prio 1000
1070 self._ClearTable()
1071 self.installFlow(1000, of_ports[0], of_ports[1])
1072 self.verifyFlow(of_ports[0], of_ports[1])
1073 self.installFlow(1000, of_ports[1], of_ports[0])
1074 self.verifyFlow(of_ports[1], of_ports[0])
1075 self.installFlow(1001, of_ports[0], of_ports[1])
1076 self.verifyFlow(of_ports[0], of_ports[1])
1077 self.installFlow(1001, of_ports[1], of_ports[0])
1078 self.verifyFlow(of_ports[1], of_ports[0])
1079 self.removeFlow(1001)
1080 self.verifyFlow(of_ports[0], of_ports[1])
1081 self.removeFlow(1000)
1082
1083
1084
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001085class WildcardPriority(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001086 """
1087 1. Add wildcard flow, verify packet received.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001088 2. Add wildcard flow with higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001089 on port specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001090 3. Add wildcard flow with lower priority, verify packet received
Rich Laneb8392082012-11-21 15:52:54 -08001091 on port specified by the highest priority flow.
Ken Chiang38d7a152012-05-24 15:33:50 -07001092 """
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001093
1094 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001095
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001096 self._Init()
1097
Rich Lane477f4812012-10-04 22:49:00 -07001098 of_ports = config["port_map"].keys()
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001099 of_ports.sort()
1100
1101 self._ClearTable()
Ken Chiang38d7a152012-05-24 15:33:50 -07001102
1103 # Install a flow with wildcards
1104 self.installFlow(999, of_ports[0], of_ports[1],
1105 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001106 self.verifyFlow(of_ports[0], of_ports[1])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001107 # Install a flow with wildcards with higher priority
1108 self.installFlow(1000, of_ports[0], of_ports[2],
1109 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001110 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001111 # Install a flow with wildcards with lower priority
Rich Laneb8392082012-11-21 15:52:54 -08001112 self.installFlow(999, of_ports[0], of_ports[1],
1113 wildcards=ofp.OFPFW_DL_SRC)
Rich Lane0a78fbd2012-12-31 16:25:04 -08001114 self.verifyFlow(of_ports[0], of_ports[2])
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001115
1116
Rich Lane97e99652013-01-02 17:23:20 -08001117@group("smoke")
Ken Chiang3978f242012-06-13 14:14:09 -07001118class WildcardPriorityWithDelete(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001119 """
Rich Lane0a78fbd2012-12-31 16:25:04 -08001120 1. Add wildcard match flow, verify packet received.
Ken Chiang38d7a152012-05-24 15:33:50 -07001121 2. Add wildcard flow with higher priority, verify packet received on port
1122 specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001123 3. Add wildcard flow with even higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001124 on port specified by this flow.
1125 4. Delete lowest priority flow, verify packet received on port specified
1126 by highest priority flow.
1127 5. Delete highest priority flow, verify packet received on port specified
1128 by remaining flow.
1129 """
1130
1131 def runTest(self):
1132
1133 self._Init()
1134
Rich Lane477f4812012-10-04 22:49:00 -07001135 of_ports = config["port_map"].keys()
Ken Chiang38d7a152012-05-24 15:33:50 -07001136 of_ports.sort()
1137
1138 self._ClearTable()
1139
Rich Lane0a78fbd2012-12-31 16:25:04 -08001140 # Install a flow with wildcards
1141 self.installFlow(250, of_ports[0], of_ports[1],
1142 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001143 self.verifyFlow(of_ports[0], of_ports[1])
1144 # Install a flow with wildcards of higher priority
1145 self.installFlow(1250, of_ports[0], of_ports[2],
1146 wildcards=ofp.OFPFW_DL_DST)
1147 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001148 # Install a flow with wildcards with even higher priority
1149 self.installFlow(2001, of_ports[0], of_ports[3],
1150 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001151 self.verifyFlow(of_ports[0], of_ports[3])
1152 # Delete lowest priority flow
1153 self.removeFlow(250)
1154 self.verifyFlow(of_ports[0], of_ports[3])
1155 # Delete highest priority flow
1156 self.removeFlow(2001)
1157 self.verifyFlow(of_ports[0], of_ports[2])
1158
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001159
Dan Talayco551befa2010-07-15 17:05:32 -07001160class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001161 """
1162 Exercise wildcard matching for all ports
1163
1164 Generate a packet
1165 Generate and install a matching flow with wildcard mask
1166 Add action to forward to a port
1167 Send the packet to the port
1168 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001169 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001170 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001171 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001172 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001173 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001174 wc |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001175 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001176 # Set nonzero VLAN id to avoid sending priority-tagged packet
1177 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001178 else:
1179 dl_vlan = -1
Rich Lane477f4812012-10-04 22:49:00 -07001180 flow_match_test(self, config["port_map"], wildcards=wc,
Dan Talayco4431d542012-03-21 16:42:16 -07001181 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001182
Dan Talayco551befa2010-07-15 17:05:32 -07001183class SingleWildcardMatchTagged(BaseMatchCase):
1184 """
1185 SingleWildcardMatch with tagged packets
1186 """
1187 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001188 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001189 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001190 wc |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001191 flow_match_test(self, config["port_map"], wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -07001192 max_test=10)
1193
1194class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001195 """
Dan Talayco80b54ed2010-07-13 09:48:35 -07001196 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001197
1198 Generate a packet
1199 Generate and install a matching flow with wildcard all except one filed
1200 Add action to forward to a port
1201 Send the packet to the port
1202 Verify the packet is received at all other ports (one port at a time)
1203 Verify flow_expiration message is correct when command option is set
1204 """
1205 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001206 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001207 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001208 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001209 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001210 # Set nonzero VLAN id to avoid sending priority-tagged packet
1211 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001212 else:
1213 dl_vlan = -1
Rich Lane477f4812012-10-04 22:49:00 -07001214 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Dan Talayco4431d542012-03-21 16:42:16 -07001215 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001216
Dan Talayco551befa2010-07-15 17:05:32 -07001217class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1218 """
1219 Match one field with tagged packets
1220 """
1221 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001222 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001223 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001224 all_exp_one_wildcard |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001225 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Dan Talayco21381562010-07-17 00:34:47 -07001226 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001227
1228class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001229 """
1230 Create Wildcard-all flow and exercise for all ports
1231
1232 Generate a packet
1233 Generate and install a matching flow with wildcard-all
1234 Add action to forward to a port
1235 Send the packet to the port
1236 Verify the packet is received at all other ports (one port at a time)
1237 Verify flow_expiration message is correct when command option is set
1238 """
1239 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001240 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001241
Dan Talayco551befa2010-07-15 17:05:32 -07001242class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001243 """
Dan Talayco551befa2010-07-15 17:05:32 -07001244 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001245 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001246 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001247 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Lane477f4812012-10-04 22:49:00 -07001248 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL,
Dan Talayco21381562010-07-17 00:34:47 -07001249 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001250
Rich Lane97e99652013-01-02 17:23:20 -08001251@group('smoke')
Dan Talayco551befa2010-07-15 17:05:32 -07001252class AddVLANTag(BaseMatchCase):
1253 """
1254 Add a VLAN tag to an untagged packet
1255 """
1256 def runTest(self):
1257 new_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001258 sup_acts = self.supported_actions
Dan Talayco551befa2010-07-15 17:05:32 -07001259 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001260 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001261 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001262
Dan Talayco551befa2010-07-15 17:05:32 -07001263 len = 100
1264 len_w_vid = 104
1265 pkt = simple_tcp_packet(pktlen=len)
1266 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1267 dl_vlan=new_vid)
1268 vid_act = action.action_set_vlan_vid()
1269 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001270
Rich Lane477f4812012-10-04 22:49:00 -07001271 flow_match_test(self, config["port_map"], pkt=pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001272 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001273
Rich Lane0a4f6372013-01-02 14:40:22 -08001274@disabled
Rich Laneb90a1c42012-10-05 09:16:05 -07001275class PacketOnly(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001276 """
1277 Just send a packet thru the switch
1278 """
Rich Laned1d9c282012-10-04 22:07:10 -07001279
Dan Talayco551befa2010-07-15 17:05:32 -07001280 def runTest(self):
1281 pkt = simple_tcp_packet()
Rich Lane477f4812012-10-04 22:49:00 -07001282 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001283 of_ports.sort()
1284 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001285 logging.info("Sending packet to " + str(ing_port))
1286 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001287 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001288
Rich Lane0a4f6372013-01-02 14:40:22 -08001289@disabled
Rich Laneb90a1c42012-10-05 09:16:05 -07001290class PacketOnlyTagged(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001291 """
1292 Just send a packet thru the switch
1293 """
Rich Laned1d9c282012-10-04 22:07:10 -07001294
Dan Talayco551befa2010-07-15 17:05:32 -07001295 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001296 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001297 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
Rich Lane477f4812012-10-04 22:49:00 -07001298 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001299 of_ports.sort()
1300 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001301 logging.info("Sending packet to " + str(ing_port))
1302 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001303 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001304
Dan Talayco551befa2010-07-15 17:05:32 -07001305class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001306 """
1307 Modify the VLAN ID in the VLAN tag of a tagged packet
1308 """
Dan Talaycoaf669322012-09-12 22:51:22 -07001309 def setUp(self):
1310 BaseMatchCase.setUp(self)
1311 self.ing_port=False
1312
Dan Talayco551befa2010-07-15 17:05:32 -07001313 def runTest(self):
1314 old_vid = 2
1315 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001316 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001317 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001318 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001319 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001320
Dan Talayco551befa2010-07-15 17:05:32 -07001321 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1322 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
1323 vid_act = action.action_set_vlan_vid()
1324 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001325
Rich Lane477f4812012-10-04 22:49:00 -07001326 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoaf669322012-09-12 22:51:22 -07001327 action_list=[vid_act], ing_port=self.ing_port)
1328
1329class ModifyVIDToIngress(ModifyVID):
1330 """
1331 Modify the VLAN ID in the VLAN tag of a tagged packet and send to
1332 ingress port
1333 """
1334 def setUp(self):
1335 BaseMatchCase.setUp(self)
1336 self.ing_port=True
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001337
Ken Chiange9a211d2012-04-20 14:52:11 -07001338class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1339 """
1340 With vlan ID and priority wildcarded, perform SET_VLAN_VID action.
1341 The same flow should match on both untagged and tagged packets.
1342 """
1343 def runTest(self):
1344 old_vid = 2
1345 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001346 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001347 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1348 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1349 return
1350
Rich Lane477f4812012-10-04 22:49:00 -07001351 of_ports = config["port_map"].keys()
Ken Chiange9a211d2012-04-20 14:52:11 -07001352 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1353 ing_port = of_ports[0]
1354 egr_ports = of_ports[1]
1355
Rich Lane32bf9482013-01-03 17:26:30 -08001356 delete_all_flows(self.controller)
Ken Chiange9a211d2012-04-20 14:52:11 -07001357
1358 len_untagged = 100
1359 len_w_vid = 104
1360 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1361 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
1362 dl_vlan_enable=True, dl_vlan=old_vid)
1363 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1364 dl_vlan=new_vid)
Ed Swierk99a74de2012-08-22 06:40:54 -07001365 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1366 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001367 vid_act = action.action_set_vlan_vid()
1368 vid_act.vlan_vid = new_vid
1369 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
1370 wildcards=wildcards, egr_ports=egr_ports,
1371 action_list=[vid_act])
1372 flow_msg_install(self, request)
1373
Rich Lane9a003812012-10-04 17:17:59 -07001374 logging.debug("Send untagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001375 str(egr_ports))
1376 self.dataplane.send(ing_port, str(untagged_pkt))
1377 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1378
Rich Lane9a003812012-10-04 17:17:59 -07001379 logging.debug("Send tagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001380 str(egr_ports))
1381 self.dataplane.send(ing_port, str(tagged_pkt))
1382 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1383
Howard Pershc1199d52012-04-11 14:21:32 -07001384class ModifyVlanPcp(BaseMatchCase):
1385 """
1386 Modify the priority field of the VLAN tag of a tagged packet
1387 """
1388 def runTest(self):
1389 vid = 123
1390 old_vlan_pcp = 2
1391 new_vlan_pcp = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001392 sup_acts = self.supported_actions
Ed Swierk8c3af7f2012-04-24 14:19:17 -07001393 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_PCP):
1394 skip_message_emit(self, "Modify VLAN priority test")
Howard Pershc1199d52012-04-11 14:21:32 -07001395 return
1396
1397 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1398 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1399 vid_act = action.action_set_vlan_pcp()
1400 vid_act.vlan_pcp = new_vlan_pcp
1401
Rich Lane477f4812012-10-04 22:49:00 -07001402 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Howard Pershc1199d52012-04-11 14:21:32 -07001403 action_list=[vid_act])
1404
Dan Talayco551befa2010-07-15 17:05:32 -07001405class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001406 """
1407 Strip the VLAN tag from a tagged packet
1408 """
Dan Talayco551befa2010-07-15 17:05:32 -07001409 def runTest(self):
1410 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001411 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001412 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001413 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001414 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001415
Dan Talayco551befa2010-07-15 17:05:32 -07001416 len_w_vid = 104
1417 len = 100
1418 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1419 dl_vlan=old_vid)
1420 exp_pkt = simple_tcp_packet(pktlen=len)
1421 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001422
Rich Lane477f4812012-10-04 22:49:00 -07001423 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001424 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001425
Ken Chiange9a211d2012-04-20 14:52:11 -07001426class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1427 """
1428 Strip the VLAN tag from a tagged packet.
1429 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1430 """
1431 def runTest(self):
1432 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001433 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001434 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1435 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1436 return
1437
1438 len_w_vid = 104
1439 len_untagged = 100
1440 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1441 dl_vlan=old_vid)
1442 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
Ed Swierk99a74de2012-08-22 06:40:54 -07001443 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1444 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001445 vid_act = action.action_strip_vlan()
1446
Rich Lane477f4812012-10-04 22:49:00 -07001447 flow_match_test(self, config["port_map"],
Ed Swierk99a74de2012-08-22 06:40:54 -07001448 wildcards=wildcards,
Ken Chiange9a211d2012-04-20 14:52:11 -07001449 pkt=pkt, exp_pkt=exp_pkt,
1450 action_list=[vid_act])
1451
Dan Talayco4b2bee62010-07-20 14:10:05 -07001452def init_pkt_args():
1453 """
1454 Pass back a dictionary with default packet arguments
1455 """
1456 args = {}
1457 args["dl_src"] = '00:23:45:67:89:AB'
1458
1459 dl_vlan_enable=False
1460 dl_vlan=-1
Rich Lane477f4812012-10-04 22:49:00 -07001461 if config["test-params"]["vid"]:
Dan Talayco4b2bee62010-07-20 14:10:05 -07001462 dl_vlan_enable=True
Rich Lane477f4812012-10-04 22:49:00 -07001463 dl_vlan = config["test-params"]["vid"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001464
1465# Unpack operator is ** on a dictionary
1466
1467 return args
1468
Dan Talayco551befa2010-07-15 17:05:32 -07001469class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001470 """
1471 Modify the source MAC address (TP1)
1472 """
Dan Talayco551befa2010-07-15 17:05:32 -07001473 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001474 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001475 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001476 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001477 return
1478
1479 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1480 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001481 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001482 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001483
Dan Talayco551befa2010-07-15 17:05:32 -07001484class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001485 """
1486 Modify the dest MAC address (TP1)
1487 """
Dan Talayco551befa2010-07-15 17:05:32 -07001488 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001489 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001490 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001491 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001492 return
1493
1494 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1495 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001496 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001497 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001498
Dan Talayco551befa2010-07-15 17:05:32 -07001499class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001500 """
1501 Modify the source IP address of an IP packet (TP1)
1502 """
Dan Talayco551befa2010-07-15 17:05:32 -07001503 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001504 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001505 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001506 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001507 return
1508
1509 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1510 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001511 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001512 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001513
Dan Talayco551befa2010-07-15 17:05:32 -07001514class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001515 """
1516 Modify the dest IP address of an IP packet (TP1)
1517 """
Dan Talayco551befa2010-07-15 17:05:32 -07001518 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001519 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001520 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001521 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001522 return
1523
1524 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1525 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001526 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001527 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001528
1529class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001530 """
1531 Modify the source TCP port of a TCP packet (TP1)
1532 """
Dan Talayco551befa2010-07-15 17:05:32 -07001533 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001534 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001535 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001536 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001537 return
1538
1539 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1540 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001541 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001542 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001543
Rich Lane01c2b862012-10-26 16:26:25 -07001544class ModifyL4SrcUdp(BaseMatchCase):
1545 """
1546 Modify the source UDP port of a UDP packet
1547 """
1548 def runTest(self):
1549 sup_acts = self.supported_actions
1550 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1551 skip_message_emit(self, "ModifyL4SrcUdp test")
1552 return
1553
1554 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_sport'],
1555 check_test_params=True, tp="udp")
1556 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1557 action_list=acts, max_test=2)
1558
Dan Talayco551befa2010-07-15 17:05:32 -07001559class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001560 """
1561 Modify the dest TCP port of a TCP packet (TP1)
1562 """
Dan Talayco551befa2010-07-15 17:05:32 -07001563 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001564 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001565 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001566 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001567 return
1568
1569 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1570 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001571 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001572 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001573
Rich Lane01c2b862012-10-26 16:26:25 -07001574class ModifyL4DstUdp(BaseMatchCase):
1575 """
1576 Modify the dest UDP port of a UDP packet
1577 """
1578 def runTest(self):
1579 sup_acts = self.supported_actions
1580 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1581 skip_message_emit(self, "ModifyL4DstUdp test")
1582 return
1583
1584 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_dport'],
1585 check_test_params=True, tp="udp")
1586 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1587 action_list=acts, max_test=2)
1588
Dan Talayco551befa2010-07-15 17:05:32 -07001589class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001590 """
1591 Modify the IP type of service of an IP packet (TP1)
1592 """
Dan Talayco551befa2010-07-15 17:05:32 -07001593 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001594 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001595 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001596 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001597 return
Dan Talayco551befa2010-07-15 17:05:32 -07001598
Dan Talayco4b2bee62010-07-20 14:10:05 -07001599 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1600 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001601 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001602 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001603
Dan Talaycof6e76c02012-03-23 10:56:12 -07001604class ModifyL2DstMC(BaseMatchCase):
1605 """
1606 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001607 """
1608 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001609 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001610 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001611 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001612 return
1613
Dan Talaycof6e76c02012-03-23 10:56:12 -07001614 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1615 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001616 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001617 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001618
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001619class ModifyL2DstIngress(BaseMatchCase):
1620 """
1621 Modify the L2 dest and send to the ingress port
1622 """
1623 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001624 sup_acts = self.supported_actions
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001625 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001626 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001627 return
1628
1629 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1630 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001631 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001632 action_list=acts, max_test=2, egr_count=0,
1633 ing_port=True)
1634
Dan Talaycod8ae7582012-03-23 12:24:56 -07001635class ModifyL2DstIngressMC(BaseMatchCase):
1636 """
1637 Modify the L2 dest and send to the ingress port
1638 """
1639 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001640 sup_acts = self.supported_actions
Dan Talaycod8ae7582012-03-23 12:24:56 -07001641 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1642 skip_message_emit(self, "ModifyL2dstMC test")
1643 return
1644
1645 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1646 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001647 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001648 action_list=acts, max_test=2, egr_count=-1,
1649 ing_port=True)
1650
Dan Talaycof6e76c02012-03-23 10:56:12 -07001651class ModifyL2SrcMC(BaseMatchCase):
1652 """
1653 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001654 """
1655 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001656 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001657 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001658 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001659 return
1660
Dan Talaycof6e76c02012-03-23 10:56:12 -07001661 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1662 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001663 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001664 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001665
1666class ModifyL2SrcDstMC(BaseMatchCase):
1667 """
1668 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001669 """
1670 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001671 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001672 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1673 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1674 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001675 return
1676
Dan Talaycof6e76c02012-03-23 10:56:12 -07001677 mod_fields = ['dl_dst', 'dl_src']
1678 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1679 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001680 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001681 action_list=acts, max_test=2, egr_count=-1)
1682
1683class ModifyL2DstVIDMC(BaseMatchCase):
1684 """
1685 Modify the L2 dest and send to 2 ports
1686 """
1687 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001688 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001689 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1690 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1691 skip_message_emit(self, "ModifyL2DstVIDMC test")
1692 return
1693
1694 mod_fields = ['dl_dst', 'dl_vlan']
1695 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1696 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1697 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001698 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001699 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001700
Rich Lane97e99652013-01-02 17:23:20 -08001701@group("smoke")
Rich Lane22e74c12012-11-12 15:06:06 -08001702class ModifyAll(BaseMatchCase):
1703 """
1704 Modify all supported fields and output to a port
1705 """
1706 def runTest(self):
1707 sup_acts = self.supported_actions
1708
1709 sup_map = {
1710 "dl_dst" : ofp.OFPAT_SET_DL_DST,
1711 "dl_src" : ofp.OFPAT_SET_DL_SRC,
1712 "dl_vlan_enable" : ofp.OFPAT_SET_VLAN_VID,
1713 "dl_vlan" : ofp.OFPAT_SET_VLAN_VID,
1714 "dl_vlan_pcp" : ofp.OFPAT_SET_VLAN_PCP,
1715 "ip_src" : ofp.OFPAT_SET_NW_SRC,
1716 "ip_dst" : ofp.OFPAT_SET_NW_DST,
1717 "ip_tos" : ofp.OFPAT_SET_NW_TOS,
1718 "tcp_sport" : ofp.OFPAT_SET_TP_SRC,
1719 "tcp_dport" : ofp.OFPAT_SET_TP_DST,
1720 }
1721
1722 mod_fields = [field for (field, bit) in sup_map.items() if (sup_acts & 1 << bit)]
1723 random.shuffle(mod_fields)
1724 start_field_vals = { "dl_vlan_enable" : True }
1725 mod_field_vals = { "dl_vlan_enable" : True }
1726 logging.info("modifying fields: %s" % repr(mod_fields))
1727
1728 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1729 mod_fields=mod_fields,
1730 start_field_vals=start_field_vals,
1731 mod_field_vals=mod_field_vals,
1732 check_test_params=True)
1733 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1734 action_list=acts, max_test=2)
1735
Dan Talaycofa6454f2012-04-05 10:04:13 -07001736class FlowToggle(BaseMatchCase):
1737 """
1738 Add flows to the table and modify them repeatedly
Dan Talaycof7c41312012-07-23 12:53:19 -07001739
1740 This is done by using only "add" flow messages. Since the check overlap
1741 flag is not set, the switch is supposed to modify the existing flow if
1742 the match already exists.
1743
1744 Would probably be better to exercise more of the flow modify commands
1745 (add, modify, delete +/- strict).
Dan Talaycofa6454f2012-04-05 10:04:13 -07001746 """
1747 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001748 flow_count = test_param_get('ft_flow_count', default=20)
1749 iter_count = test_param_get('ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001750
Rich Lane9a003812012-10-04 17:17:59 -07001751 logging.info("Running flow toggle with %d flows, %d iterations" %
Dan Talaycofa6454f2012-04-05 10:04:13 -07001752 (flow_count, iter_count))
1753 acts = []
1754 acts.append(action.action_output())
1755 acts.append(action.action_output())
1756
Rich Lane477f4812012-10-04 22:49:00 -07001757 of_ports = config["port_map"].keys()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001758 if len(of_ports) < 3:
1759 self.assertTrue(False, "Too few ports for test")
1760
1761 for idx in range(2):
1762 acts[idx].port = of_ports[idx]
1763
1764 flows = []
1765 flows.append([])
1766 flows.append([])
1767
Ed Swierk99a74de2012-08-22 06:40:54 -07001768 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_SRC |
1769 ofp.OFPFW_DL_DST)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001770 # Create up the flows in an array
1771 for toggle in range(2):
1772 for f_idx in range(flow_count):
1773 pkt = simple_tcp_packet(tcp_sport=f_idx)
1774 msg = message.flow_mod()
Ed Swierk99a74de2012-08-22 06:40:54 -07001775 match = packet_to_flow_match(self, pkt)
Shudong Zhou031373c2012-07-19 17:37:42 -07001776 match.in_port = of_ports[2]
Dan Talayco50be7672012-04-05 11:38:08 -07001777 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001778 msg.match = match
1779 msg.buffer_id = 0xffffffff
Dan Talaycof7c41312012-07-23 12:53:19 -07001780 msg.command = ofp.OFPFC_ADD
Dan Talaycofa6454f2012-04-05 10:04:13 -07001781 msg.actions.add(acts[toggle])
1782 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001783
1784 # Show two sample flows
Rich Lane9a003812012-10-04 17:17:59 -07001785 logging.debug(flows[0][0].show())
1786 logging.debug(flows[1][0].show())
Dan Talayco50be7672012-04-05 11:38:08 -07001787
Dan Talaycofa6454f2012-04-05 10:04:13 -07001788 # Install the first set of flows
1789 for f_idx in range(flow_count):
Rich Lane5c3151c2013-01-03 17:15:41 -08001790 self.controller.message_send(flows[0][f_idx])
Rich Lane3a261d52013-01-03 17:45:08 -08001791 do_barrier(self.controller)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001792
Rich Lane9a003812012-10-04 17:17:59 -07001793 logging.info("Installed %d flows" % flow_count)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001794
1795 # Repeatedly modify all the flows back and forth
1796 updates = 0
1797 # Report status about 5 times
1798 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001799 start = time.time()
1800 for iter_idx in range(iter_count):
1801 if not iter_idx % mod_val:
Rich Lane9a003812012-10-04 17:17:59 -07001802 logging.info("Flow Toggle: iter %d of %d. " %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001803 (iter_idx, iter_count) +
1804 "%d updates in %d secs" %
1805 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001806 for toggle in range(2):
1807 t_idx = 1 - toggle
1808 for f_idx in range(flow_count):
Rich Lane5c3151c2013-01-03 17:15:41 -08001809 self.controller.message_send(flows[t_idx][f_idx])
Dan Talaycofa6454f2012-04-05 10:04:13 -07001810 updates += 1
Rich Lane3a261d52013-01-03 17:45:08 -08001811 do_barrier(self.controller)
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001812
1813 end = time.time()
1814 divisor = end - start or (end - start + 1)
Rich Lane9a003812012-10-04 17:17:59 -07001815 logging.info("Flow toggle: %d iterations" % iter_count)
1816 logging.info(" %d flow mods in %d secs, %d mods/sec" %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001817 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001818
1819
Dan Talayco8a64e332012-03-28 14:53:20 -07001820# You can pick and choose these by commenting tests in or out
1821iter_classes = [
1822 basic.PacketIn,
1823 basic.PacketOut,
1824 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001825 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001826 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001827 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001828 AllWildcardMatch,
1829 AllWildcardMatchTagged,
1830 SingleWildcardMatch,
1831 SingleWildcardMatchTagged,
1832 ExactMatch,
1833 ExactMatchTagged,
1834 SingleWildcardMatch,
1835 ModifyL2Src,
1836 ModifyL2Dst,
1837 ModifyL2SrcMC,
1838 ModifyL2DstMC,
1839 ModifyL2SrcDstMC
1840 ]
1841
Rich Lane0a4f6372013-01-02 14:40:22 -08001842@disabled
Dan Talayco8a64e332012-03-28 14:53:20 -07001843class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001844 """
1845 Iterate over a bunch of test cases
1846
1847 The cases come from the list above
1848 """
1849
Dan Talayco8a64e332012-03-28 14:53:20 -07001850 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001851 count = test_param_get('iter_count', default=10)
Dan Talayco8a64e332012-03-28 14:53:20 -07001852 tests_done = 0
Rich Lane9a003812012-10-04 17:17:59 -07001853 logging.info("Running iteration test " + str(count) + " times")
Dan Talayco8a64e332012-03-28 14:53:20 -07001854 start = time.time()
1855 last = start
1856 for idx in range(count):
Rich Lane9a003812012-10-04 17:17:59 -07001857 logging.info("Iteration " + str(idx + 1))
Dan Talayco8a64e332012-03-28 14:53:20 -07001858 for cls in iter_classes:
1859 test = cls()
1860 test.inheritSetup(self)
1861 test.runTest()
1862 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001863 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001864 if time.time() - last > 60:
1865 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001866 logging.info(
Dan Talaycofa6454f2012-04-05 10:04:13 -07001867 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1868 (idx, count, tests_done, last - start) +
1869 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001870 stats = all_stats_get(self)
1871 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001872 logging.info("\nIterCases ran %d tests in %d seconds." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001873 (tests_done, last - start))
Rich Lane9a003812012-10-04 17:17:59 -07001874 logging.info(" flows: %d. packets: %d. bytes: %d" %
Dan Talayco8a64e332012-03-28 14:53:20 -07001875 (stats["flows"], stats["packets"], stats["bytes"]))
Rich Lane9a003812012-10-04 17:17:59 -07001876 logging.info(" active: %d. lookups: %d. matched %d." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001877 (stats["active"], stats["lookups"], stats["matched"]))
1878
Dan Talayco4b2bee62010-07-20 14:10:05 -07001879#@todo Need to implement tagged versions of the above tests
1880#
1881#@todo Implement a test case that strips tag 2, adds tag 3
1882# and modifies tag 4 to tag 5. Then verify (in addition) that
1883# tag 6 does not get modified.
1884
Rich Lane0a4f6372013-01-02 14:40:22 -08001885@disabled
Dan Talayco4b2bee62010-07-20 14:10:05 -07001886class MixedVLAN(BaseMatchCase):
1887 """
1888 Test mixture of VLAN tag actions
1889
1890 Strip tag 2 on port 1, send to port 2
1891 Add tag 3 on port 1, send to port 2
1892 Modify tag 4 to 5 on port 1, send to port 2
1893 All other traffic from port 1, send to port 3
1894 All traffic from port 2 sent to port 4
1895 Use exact matches with different packets for all mods
1896 Verify the following: (port, vid)
1897 (port 1, vid 2) => VLAN tag stripped, out port 2
1898 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1899 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1900 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1901 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1902 (port 2, no tag) => untagged packet out port 4
1903 (port 2, vid 2-6) => unmodified packet out port 4
1904
1905 Variation: Might try sending VID 5 to port 3 and check.
1906 If only VID 5 distinguishes pkt, this will fail on some platforms
1907 """
1908
Rich Lane97e99652013-01-02 17:23:20 -08001909@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -07001910class MatchEach(base_tests.SimpleDataPlane):
Rich Lane8d6ab272012-09-23 18:06:20 -07001911 """
1912 Check that each match field is actually matched on.
1913 Installs two flows that differ in one field. The flow that should not
1914 match has a higher priority, so if that field is ignored during matching
1915 the packet will be sent out the wrong port.
1916
1917 TODO test UDP, ARP, ICMP, etc.
1918 """
1919 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001920 of_ports = config["port_map"].keys()
Rich Lane8d6ab272012-09-23 18:06:20 -07001921 of_ports.sort()
1922 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1923
Rich Lane9a003812012-10-04 17:17:59 -07001924 delete_all_flows(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001925
Ed Swierk7040a8d2012-12-11 16:30:13 -08001926 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=2)
Rich Lane8d6ab272012-09-23 18:06:20 -07001927 ingress_port = of_ports[0]
1928 egress_port = of_ports[1]
1929
1930 def testField(field, mask):
Rich Lane9a003812012-10-04 17:17:59 -07001931 logging.info("Testing field %s" % field)
Rich Lane8d6ab272012-09-23 18:06:20 -07001932
1933 def addFlow(matching, priority, output_port):
1934 match = packet_to_flow_match(self, pkt)
1935 self.assertTrue(match is not None, "Could not generate flow match from pkt")
1936 match.wildcards &= ~ofp.OFPFW_IN_PORT
1937 match.in_port = ingress_port
1938 if not matching:
1939 # Make sure flow doesn't match
1940 orig = getattr(match, field)
1941 if isinstance(orig, list):
1942 new = map(lambda a: ~a[0] & a[1], zip(orig, mask))
1943 else:
1944 new = ~orig & mask
1945 setattr(match, field, new)
1946 request = message.flow_mod()
1947 request.match = match
1948 request.buffer_id = 0xffffffff
1949 request.priority = priority
1950 act = action.action_output()
1951 act.port = output_port
Rich Lanee30455b2013-01-03 16:24:44 -08001952 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -07001953 logging.info("Inserting flow")
Rich Lane8d6ab272012-09-23 18:06:20 -07001954 self.controller.message_send(request)
1955
1956 # This flow should match.
1957 addFlow(matching=True, priority=0, output_port=egress_port)
1958 # This flow should not match, but it has a higher priority.
1959 addFlow(matching=False, priority=1, output_port=ofp.OFPP_IN_PORT)
1960
Rich Lane3a261d52013-01-03 17:45:08 -08001961 do_barrier(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001962
Rich Lane9a003812012-10-04 17:17:59 -07001963 logging.info("Sending packet to dp port " + str(ingress_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001964 self.dataplane.send(ingress_port, str(pkt))
1965
1966 exp_pkt_arg = None
1967 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -07001968 if config["relax"]:
Rich Lane8d6ab272012-09-23 18:06:20 -07001969 exp_pkt_arg = pkt
1970 exp_port = egress_port
1971
1972 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
1973 exp_pkt=exp_pkt_arg)
1974 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -07001975 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001976 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
1977 self.assertEqual(str(pkt), str(rcv_pkt), 'Response packet does not match send packet')
1978
Ed Swierkb603b192012-12-12 15:38:49 -08001979 wildcards = required_wildcards(self)
Rich Lane8d6ab272012-09-23 18:06:20 -07001980 # TODO in_port
Ed Swierkb603b192012-12-12 15:38:49 -08001981 if not (wildcards & ofp.OFPFW_DL_SRC):
1982 testField("dl_src", [0xff]*6)
1983 if not (wildcards & ofp.OFPFW_DL_DST):
1984 testField("dl_dst", [0xff]*6)
1985 if not (wildcards & ofp.OFPFW_DL_TYPE):
1986 testField("dl_type", 0xffff)
1987 if not (wildcards & ofp.OFPFW_DL_VLAN):
1988 testField("dl_vlan", 0xfff)
Rich Lane8d6ab272012-09-23 18:06:20 -07001989 # TODO dl_vlan_pcp
Ed Swierkb603b192012-12-12 15:38:49 -08001990 if not (wildcards & ofp.OFPFW_NW_SRC_ALL):
1991 testField("nw_src", 0xffffffff)
1992 if not (wildcards & ofp.OFPFW_NW_DST_ALL):
1993 testField("nw_dst", 0xffffffff)
1994 if not (wildcards & ofp.OFPFW_NW_TOS):
1995 testField("nw_tos", 0x3f)
1996 if not (wildcards & ofp.OFPFW_NW_PROTO):
1997 testField("nw_proto", 0xff)
1998 if not (wildcards & ofp.OFPFW_TP_SRC):
1999 testField("tp_src", 0xffff)
2000 if not (wildcards & ofp.OFPFW_TP_DST):
2001 testField("tp_dst", 0xffff)
Rich Lane8d6ab272012-09-23 18:06:20 -07002002
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002003class DirectBadPacketBase(base_tests.SimpleDataPlane):
2004 """
2005 Base class for sending single packets with single flow table entries.
2006 Used to verify matching of unusual packets and parsing/matching of
2007 corrupted packets.
2008
2009 The idea is to generate packets that may either be totally malformed or
2010 malformed just enough to trick the flow matcher into making mistakes.
2011
2012 Generate a 'bad' packet
2013 Generate and install a matching flow
2014 Add action to direct the packet to an egress port
2015 Send the packet to ingress dataplane port
2016 Verify the packet is received at the egress port only
2017 """
2018
2019 RESULT_MATCH = "MATCH"
2020 RESULT_NOMATCH = "NO MATCH"
2021 RESULT_ANY = "ANY MATCH"
2022
2023 def runTest(self):
2024 pass
2025 # TODO:
2026 # - ICMP?
2027 # - VLAN?
2028 # - action
2029
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002030 def createMatch(self, **kwargs):
2031 match = ofp.ofp_match()
2032 match.wildcards = ofp.OFPFW_ALL
2033 fields = {
2034 'dl_dst': ofp.OFPFW_DL_DST,
2035 'dl_src': ofp.OFPFW_DL_SRC,
2036 'dl_type': ofp.OFPFW_DL_TYPE,
2037 'dl_vlan': ofp.OFPFW_DL_VLAN,
2038 'nw_src': ofp.OFPFW_NW_SRC_MASK,
2039 'nw_dst': ofp.OFPFW_NW_DST_MASK,
2040 'nw_tos': ofp.OFPFW_NW_TOS,
2041 'nw_proto': ofp.OFPFW_NW_PROTO,
2042 'tp_src': ofp.OFPFW_TP_SRC,
2043 'tp_dst': ofp.OFPFW_TP_DST,
2044 }
2045 for key in kwargs:
2046 setattr(match, key, kwargs[key])
2047 match.wildcards &= ~fields[key]
2048 return match
2049
2050 def testPktsAgainstFlow(self, pkts, acts, match):
2051 if type(acts) != list:
2052 acts = [acts]
2053 for info in pkts:
2054 title, pkt, expected_result = info
2055 self.testPktAgainstFlow(title, pkt, acts, match, expected_result)
2056
2057 def testPktAgainstFlow(self, title, pkt, acts, match, expected_result):
2058 of_ports = config["port_map"].keys()
2059 of_ports.sort()
2060 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
2061
Rich Lane32bf9482013-01-03 17:26:30 -08002062 delete_all_flows(self.controller)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002063
2064 ingress_port = of_ports[0]
2065 egress_port = of_ports[1]
2066
2067 logging.info("Testing packet '%s', expect result %s" %
2068 (title, expected_result))
2069 logging.info("Ingress %s to egress %s" %
2070 (str(ingress_port), str(egress_port)))
2071 logging.info("Packet:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002072 logging.info(inspect_packet(pkt))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002073
2074 match.in_port = ingress_port
2075
2076 request = message.flow_mod()
2077 request.match = match
Rich Lane44cf12d2012-10-15 11:10:45 -07002078 request.priority = 1
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002079
2080 request.buffer_id = 0xffffffff
2081 for act in acts:
2082 act.port = egress_port
Rich Lanee30455b2013-01-03 16:24:44 -08002083 request.actions.add(act)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002084
2085 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08002086 self.controller.message_send(request)
Rich Lane44cf12d2012-10-15 11:10:45 -07002087
2088 # This flow speeds up negative tests
2089 logging.info("Inserting catch-all flow")
2090 request2 = message.flow_mod()
2091 request2.match = self.createMatch()
Dan Talayco3bfc8222013-02-13 18:18:57 -08002092 request2.match.wildcards &= ~ofp.OFPFW_IN_PORT
2093 request2.match.in_port = ingress_port
2094
Rich Lane44cf12d2012-10-15 11:10:45 -07002095 request2.priority = 0
2096 act = action.action_output()
2097 act.port = ofp.OFPP_IN_PORT
2098 request2.actions.add(act)
Rich Lane5c3151c2013-01-03 17:15:41 -08002099 self.controller.message_send(request2)
Rich Lane44cf12d2012-10-15 11:10:45 -07002100
Rich Lane3a261d52013-01-03 17:45:08 -08002101 do_barrier(self.controller)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002102
Dan Talayco3bfc8222013-02-13 18:18:57 -08002103 pkt_str = str(pkt)
2104 if config["minsize"] > len(str(pkt)):
2105 pkt_str += '0' * (config["minsize"] - len(str(pkt)))
2106
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002107 logging.info("Sending packet to dp port " +
2108 str(ingress_port))
Dan Talayco3bfc8222013-02-13 18:18:57 -08002109 self.dataplane.send(ingress_port, pkt_str)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002110
2111 exp_pkt_arg = None
2112 exp_port = None
2113 if config["relax"]:
2114 exp_pkt_arg = pkt
2115 exp_port = egress_port
2116
Rich Lane44cf12d2012-10-15 11:10:45 -07002117 if expected_result == self.RESULT_MATCH:
2118 timeout = -1 # default timeout
2119 else:
2120 timeout = 1 # short timeout for negative tests
2121
2122 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(exp_pkt=exp_pkt_arg,
2123 timeout=timeout)
2124 if rcv_port == ingress_port:
2125 logging.debug("Packet matched catch-all flow")
2126 rcv_pkt = None
2127
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002128 if expected_result == self.RESULT_MATCH:
2129 self.assertTrue(rcv_pkt is not None,
2130 "Did not receive packet, expected a match")
2131 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
2132 str(rcv_port))
2133 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
2134 str_pkt = str(pkt)
2135 str_rcv_pkt = str(rcv_pkt)
2136 str_rcv_pkt = str_rcv_pkt[0:len(str_pkt)]
2137 if str_pkt != str_rcv_pkt:
2138 logging.error("Response packet does not match send packet")
2139 logging.info("Response:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002140 logging.info(inspect_packet(scapy.Ether(rcv_pkt)))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002141 self.assertEqual(str_pkt, str_rcv_pkt,
2142 'Response packet does not match send packet')
2143 elif expected_result == self.RESULT_NOMATCH:
2144 self.assertTrue(rcv_pkt is None, "Received packet, expected drop")
2145 else:
2146 logging.debug("Match or drop accepted. Result = %s" %
2147 ("match" if rcv_pkt is not None else "drop"))
2148
2149
2150class DirectBadIpTcpPacketsBase(DirectBadPacketBase):
2151 """
2152 Base class for TCP and UDP parsing/matching verification under corruptions
2153 """
2154 def runTest(self):
2155 pass
2156
2157 def runTestWithProto(self, protoName = 'TCP'):
2158 dl_dst='00:01:02:03:04:05'
2159 dl_src='00:06:07:08:09:0a'
2160 ip_src='192.168.0.1'
2161 ip_dst='192.168.0.2'
2162 ip_tos=0
2163 tcp_sport=1234
2164 tcp_dport=80
2165
2166 # Generate a proper packet for constructing a match
2167 tp = None
2168 if protoName == 'TCP':
2169 tp = scapy.TCP
2170 proto = 6
2171 elif protoName == 'UDP':
2172 tp = scapy.UDP
2173 proto = 17
2174 else:
2175 raise Exception("Passed in unknown proto name")
2176
2177 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
2178 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2179 tp(sport=tcp_sport, dport=tcp_dport)
2180 match = packet_to_flow_match(self, match_pkt)
2181 self.assertTrue(match is not None,
2182 "Could not generate flow match from pkt")
2183 match.wildcards &= ~ofp.OFPFW_IN_PORT
2184
2185 def testPacket(title, pkt, result):
2186 act = action.action_output()
2187 pkts = [
2188 [title, pkt, result]
2189 ]
2190 self.testPktsAgainstFlow(pkts, act, match)
2191
2192 # Try incomplete IP headers
2193 testPacket("Incomplete IP header (1 bytes)",
2194 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2195 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:1],
2196 self.RESULT_NOMATCH,
2197 )
2198 testPacket("Incomplete IP header (2 bytes)",
2199 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2200 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:2],
2201 self.RESULT_NOMATCH,
2202 )
2203 testPacket("Incomplete IP header (3 bytes)",
2204 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2205 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:3],
2206 self.RESULT_NOMATCH,
2207 )
2208 testPacket("Incomplete IP header (12 bytes)",
2209 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2210 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:12],
2211 self.RESULT_NOMATCH,
2212 )
2213 testPacket("Incomplete IP header (16 bytes)",
2214 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2215 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:16],
2216 self.RESULT_NOMATCH,
2217 )
2218 testPacket("Incomplete IP header (19 bytes)",
2219 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2220 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:19],
2221 self.RESULT_NOMATCH,
2222 )
2223
2224 # Try variations where the TCP header is missing or incomplete. As we
2225 # saw bugs before where buffers were reused and lengths weren't honored,
2226 # we initiatlize once with a non-matching full packet and once with a
2227 # matching full packet.
2228 testPacket("Non-Matching TCP packet, warming buffer",
2229 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2230 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2231 tp(sport=tcp_sport, dport=tcp_dport + 1),
2232 self.RESULT_NOMATCH,
2233 )
2234 testPacket("Missing TCP header, buffer warmed with non-match",
2235 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2236 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2237 self.RESULT_NOMATCH,
2238 )
2239 testPacket("Matching TCP packet, warming buffer",
2240 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2241 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2242 tp(sport=tcp_sport, dport=tcp_dport),
2243 self.RESULT_MATCH,
2244 )
2245 testPacket("Missing TCP header, buffer warmed with match",
2246 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2247 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2248 self.RESULT_NOMATCH,
2249 )
2250 testPacket("Truncated TCP header: 2 bytes",
2251 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2252 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2253 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:2]),
2254 self.RESULT_NOMATCH,
2255 )
2256
2257 # Play with IP header length values that put the start of TCP either
2258 # inside the generated TCP header or beyond. In some cases it may even
2259 # be beyond the packet boundary. Also play with IP options and more
2260 # importantly IP total length corruptions.
2261 testPacket("TCP packet, corrupt ihl (0x6)",
2262 simple_tcp_packet(ip_ihl=6),
2263 self.RESULT_NOMATCH,
2264 )
2265 testPacket("TCP packet, corrupt ihl (0xf)",
2266 simple_tcp_packet(ip_ihl=0xf), # ihl = 15 * 4 = 60
2267 self.RESULT_NOMATCH,
2268 )
2269 testPacket("TCP packet, corrupt ihl and total length",
2270 simple_tcp_packet(ip_ihl=0xf, pktlen=56), # ihl = 15 * 4 = 60,
2271 self.RESULT_NOMATCH,
2272 )
2273 testPacket("Corrupt IPoption: First 4 bytes of matching TCP header",
2274 simple_tcp_packet(
2275 ip_options=scapy.IPOption('\x04\xd2\x00\x50'),
2276 tcp_dport=2, tcp_sport=2
2277 ),
2278 self.RESULT_NOMATCH,
2279 )
2280 testPacket("Missing TCP header, corrupt ihl",
2281 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2282 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto),
2283 self.RESULT_NOMATCH,
2284 )
2285 testPacket("Missing TCP header, corrupt total length",
2286 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2287 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, len= 100),
2288 self.RESULT_NOMATCH,
2289 )
2290 testPacket("Missing TCP header, corrupt ihl and total length",
2291 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2292 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto, len=43),
2293 self.RESULT_NOMATCH,
2294 )
2295 testPacket("Incomplete IP header (12 bytes), corrupt ihl and total length",
2296 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2297 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:12],
2298 self.RESULT_NOMATCH,
2299 )
2300 testPacket("Incomplete IP header (16 bytes), corrupt ihl and total length",
2301 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2302 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:16],
2303 self.RESULT_NOMATCH,
2304 )
2305
2306 # Try an incomplete TCP header that has enough bytes to carry source and
2307 # destination ports. As that is all we care about during matching, some
2308 # implementations may match and some may drop the packet
2309 testPacket("Incomplete TCP header: src/dst port present",
2310 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2311 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2312 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:4]),
2313 self.RESULT_ANY,
2314 )
2315
2316 for i in range(1):
2317 for length in range(40 / 4): # IPv4 options are a maximum of 40 in length
2318 bytes = "".join([("%c" % random.randint(0, 255)) for x in range(length * 4)])
2319 eth = scapy.Ether(dst=dl_dst, src=dl_src)
2320 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2321 tcp = tp(sport=tcp_sport, dport=tcp_dport+1)
2322 pkt = eth / ip
2323 pkt = pkt / bytes
2324 pkt = pkt / str(tcp)
2325 testPacket("Random IP options len = %d - TP match must fail" % length * 4,
2326 pkt,
2327 self.RESULT_NOMATCH
2328 )
2329
2330 eth = scapy.Ether(dst=dl_dst, src=dl_src)
2331 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2332 tcp = tp(sport=tcp_sport, dport=tcp_dport)
2333 pkt = eth / ip
2334 pkt = pkt / bytes
2335 pkt = pkt / str(tcp)
2336
2337 testPacket("Random IP options len = %d - May match",
2338 pkt,
2339 self.RESULT_ANY
2340 )
2341
2342
2343class DirectBadIpTcpPackets(DirectBadIpTcpPacketsBase):
2344 """
2345 Verify IP/TCP parsing and matching. Focus on packet corruptions
2346 """
2347 def runTest(self):
2348 self.runTestWithProto(protoName = 'TCP')
2349
2350class DirectBadIpUdpPackets(DirectBadIpTcpPacketsBase):
2351 """
2352 Verify IP/UDP parsing and matching. Focus on packet corruptions
2353 """
2354 def runTest(self):
2355 self.runTestWithProto(protoName = 'UDP')
2356
2357class DirectBadLlcPackets(DirectBadPacketBase):
2358 """
2359 Verify LLC/SNAP parsing and matching. Focus on packet corruptions
2360 """
2361 def runTest(self):
2362 dl_dst='00:01:02:03:04:05'
2363 dl_src='00:06:07:08:09:0a'
2364 ip_src='192.168.0.1'
2365 ip_dst='192.168.0.2'
2366 ip_tos=0
2367 tcp_sport=1234
2368 tcp_dport=80
2369
2370 IS_SNAP_IP = 1
2371 IS_SNAP_IP_CORRUPT = 2
2372 IS_NOT_SNAP_IP = 3
2373
2374 def testPacketTcpMatch(title, llc):
2375 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
2376 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2377 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
2378 match = packet_to_flow_match(self, match_pkt)
2379 self.assertTrue(match is not None,
2380 "Could not generate flow match from pkt")
2381 match.wildcards &= ~ofp.OFPFW_IN_PORT
2382 act = action.action_output()
2383
2384 self.testPktsAgainstFlow(
2385 [[
2386 "TCP match - LLC frame correct length - %s" % title,
2387 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2388 self.RESULT_ANY,
2389 ]],
2390 act, match
2391 )
2392
2393 # Corrupt length field
2394 ethLen = random.randint(0, 1535)
2395 self.testPktsAgainstFlow(
2396 [[
2397 "TCP match - LLC frame corrupted length - %s" % title,
2398 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
2399 self.RESULT_ANY,
2400 ]],
2401 act, match
2402 )
2403
2404 def testPacketEthSrcDstMatch(title, llc):
2405 # Matching based on Ethernet source and destination
2406 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)
2407 match = packet_to_flow_match(self, match_pkt)
2408 self.assertTrue(match is not None,
2409 "Could not generate flow match from pkt")
2410 match.wildcards &= ~ofp.OFPFW_IN_PORT
2411 match.wildcards |= ofp.OFPFW_DL_TYPE
2412 self.testPktsAgainstFlow(
2413 [[
2414 "Eth addr match - LLC frame correct length- %s" % title,
2415 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2416 self.RESULT_MATCH,
2417 ]],
2418 action.action_output(), match
2419 )
2420
2421 # Corrupt length field
2422 ethLen = random.randint(0, 1535)
2423 self.testPktsAgainstFlow(
2424 [[
2425 "Eth addr match - LLC frame corrupted length- %s" % title,
2426 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
2427 self.RESULT_ANY,
2428 ]],
2429 action.action_output(), match
2430 )
2431
2432 def testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip):
2433 # Matching based on Ethernet source, destination and type
2434 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src, type=0x800)
2435 match = packet_to_flow_match(self, match_pkt)
2436 self.assertTrue(match is not None,
2437 "Could not generate flow match from pkt")
2438 match.wildcards &= ~ofp.OFPFW_IN_PORT
2439 if is_snap_ip == IS_SNAP_IP:
2440 is_match = self.RESULT_MATCH
2441 elif is_snap_ip == IS_SNAP_IP_CORRUPT:
2442 is_match = self.RESULT_ANY
2443 else:
2444 is_match = self.RESULT_NOMATCH
2445 self.testPktsAgainstFlow(
2446 [[
2447 "Eth addr+type match - LLC frame correct length - %s" % title,
2448 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2449 is_match,
2450 ]],
2451 action.action_output(), match
2452 )
2453
2454 # Corrupt length field
2455 ethLen = random.randint(0, 1535)
2456 self.testPktsAgainstFlow(
2457 [[
2458 "Eth addr+type match - LLC frame corrupted length - %s" % title,
2459 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
Christian Dickmanne9b6d252012-10-08 22:56:50 -07002460 self.RESULT_ANY,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002461 ]],
2462 action.action_output(), match
2463 )
2464
2465 def testPacket(title, llc, is_snap_ip):
2466 testPacketTcpMatch(title, llc)
2467 testPacketEthSrcDstMatch(title, llc)
2468 testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip)
2469
2470 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002471 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002472 IS_NOT_SNAP_IP,
2473 )
2474 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002475 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002476 IS_NOT_SNAP_IP,
2477 )
2478 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002479 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002480 IS_NOT_SNAP_IP,
2481 )
2482 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002483 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002484 IS_NOT_SNAP_IP,
2485 )
2486 testPacket("LLC - SNAP - Small bogus payload",
2487 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2488 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2489 IS_SNAP_IP_CORRUPT,
2490 )
2491 testPacket("LLC - SNAP - Max -1 bogus payload",
2492 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2493 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2494 IS_NOT_SNAP_IP,
2495 )
2496 testPacket("LLC - SNAP - Max bogus payload",
2497 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2498 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2499 IS_NOT_SNAP_IP,
2500 )
2501 testPacket("LLC - SNAP - IP - TCP",
2502 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2503 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2504 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2505 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2506 IS_SNAP_IP,
2507 )
2508
2509
2510class DirectLlcPackets(DirectBadPacketBase):
2511 """
2512 Verify LLC/SNAP parsing (valid and corrupted packets) and matching
2513 """
2514 def runTest(self):
2515 dl_dst='00:01:02:03:04:05'
2516 dl_src='00:06:07:08:09:0a'
2517 ip_src='192.168.0.1'
2518 ip_dst='192.168.0.2'
2519 ip_tos=0
2520 tcp_sport=1234
2521 tcp_dport=80
2522
2523 # Test ethertype in face of LLC/SNAP and OFP_DL_TYPE_NOT_ETH_TYPE
2524 IS_SNAP_NOT_IP = 1
2525 IS_SNAP_AND_IP = 2
2526 IS_NOT_SNAP = 3
2527
2528 def testPacketEthTypeIP(title, llc, is_snap):
2529 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src, type=0x800)
2530 match = packet_to_flow_match(self, match_pkt)
2531 self.assertTrue(match is not None,
2532 "Could not generate flow match from pkt")
2533 match.wildcards &= ~ofp.OFPFW_IN_PORT
2534 pkts = []
2535 if is_snap == IS_NOT_SNAP or is_snap == IS_SNAP_NOT_IP:
2536 result = self.RESULT_NOMATCH
2537 else:
2538 result = self.RESULT_MATCH
2539 pkts.append([
2540 "Ether type 0x800 match - %s" % title,
2541 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2542 result,
2543 ])
2544 act = action.action_output()
2545 self.testPktsAgainstFlow(pkts, act, match)
2546
2547 def testPacketEthTypeNotEth(title, llc, is_snap):
2548 match_pkt = scapy.Ether(dst = dl_dst, src = dl_src,
2549 type = ofp.OFP_DL_TYPE_NOT_ETH_TYPE)
2550 match = packet_to_flow_match(self, match_pkt)
2551 self.assertTrue(match is not None,
2552 "Could not generate flow match from pkt")
2553 match.wildcards &= ~ofp.OFPFW_IN_PORT
2554 pkts = []
2555 if is_snap == IS_NOT_SNAP:
2556 result = self.RESULT_MATCH
2557 else:
2558 result = self.RESULT_NOMATCH
2559 pkts.append([
2560 "Ether type OFP_DL_TYPE_NOT_ETH_TYPE match - %s" % title,
2561 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2562 result,
2563 ])
2564 act = action.action_output()
2565 self.testPktsAgainstFlow(pkts, act, match)
2566
2567 def testPacket(title, llc, is_snap):
2568 testPacketEthTypeIP(title, llc, is_snap)
2569 testPacketEthTypeNotEth(title, llc, is_snap)
2570
2571 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002572 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
2573 IS_NOT_SNAP,
2574 )
2575 testPacket("LLC (with information field) - No SNAP - No Payload",
2576 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x12) / "S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002577 IS_NOT_SNAP,
2578 )
2579 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002580 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002581 IS_NOT_SNAP,
2582 )
2583 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002584 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002585 IS_NOT_SNAP,
2586 )
2587 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002588 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002589 IS_NOT_SNAP,
2590 )
2591 testPacket("LLC - SNAP - Non-default OUI",
2592 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2593 scapy.SNAP(OUI=0x000001, code=0x800) / ("S" * 10),
2594 IS_NOT_SNAP,
2595 )
2596 testPacket("LLC - SNAP - Default OUI",
2597 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2598 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2599 IS_SNAP_AND_IP,
2600 )
2601 testPacket("LLC - SNAP - Max -1 bogus payload",
2602 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2603 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2604 IS_SNAP_NOT_IP,
2605 )
2606 testPacket("LLC - SNAP - Max bogus payload",
2607 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2608 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2609 IS_SNAP_NOT_IP,
2610 )
2611 testPacket("LLC - SNAP - IP - TCP",
2612 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2613 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2614 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2615 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2616 IS_SNAP_AND_IP,
2617 )
2618
2619
2620class DirectArpPackets(DirectBadPacketBase):
2621 """
2622 Verify ARP parsing (valid and corrupted packets) and ARP matching
2623 """
2624 def runTest(self):
2625 self.testArpHandling()
2626
2627 def testArpHandling(self):
2628 dl_dst='00:01:02:03:04:05'
2629 dl_src='00:06:07:08:09:0a'
2630 ip_src='192.168.0.1'
2631 ip_dst='192.168.0.2'
2632 ip_src2='192.168.1.1'
2633 ip_dst2='192.168.1.2'
2634 ip_tos=0
2635 tcp_sport=1234
2636 tcp_dport=80
2637
2638 def testPacket(title, arp_match, arp_pkt, result):
2639 pkts = []
2640
2641 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src) / arp_match
2642 match = packet_to_flow_match(self, match_pkt)
2643 self.assertTrue(match is not None,
2644 "Could not generate flow match from pkt")
2645 match.wildcards &= ~ofp.OFPFW_IN_PORT
2646
2647 pkts.append([
2648 title,
2649 scapy.Ether(dst=dl_dst, src=dl_src) / arp_pkt,
2650 result,
2651 ])
2652
2653 act = action.action_output()
2654 self.testPktsAgainstFlow(pkts, act, match)
2655
2656 testPacket("Basic ARP",
2657 scapy.ARP(psrc=ip_src, pdst=ip_dst, op = 1),
2658 scapy.ARP(hwdst = '00:00:00:00:00:00', hwsrc = dl_src,
2659 psrc = ip_src, pdst = ip_dst, hwlen = 6, plen = 4,
2660 ptype = 0x800, hwtype = 1, op = 1),
2661 self.RESULT_MATCH
2662 )
2663 # More stuff:
2664 # - Non matches on any property
2665 # - Corrupted hwlen and plen
2666 # - Other hwtype, ptype
2667 # - Truncated ARP pkt
2668
2669
2670class DirectVlanPackets(DirectBadPacketBase):
2671 """
2672 Verify VLAN parsing (valid and corrupted packets) and ARP matching
2673 """
2674 def runTest(self):
2675 dl_dst='00:01:02:03:04:05'
2676 dl_src='00:06:07:08:09:0a'
2677 ip_src='192.168.0.1'
2678 ip_dst='192.168.0.2'
2679 ip_src2='192.168.1.1'
2680 ip_dst2='192.168.1.2'
2681 ip_tos=0
2682 tcp_sport=1234
2683 tcp_dport=80
2684
2685 def testPacket(title, match, pkt, result):
2686 pkts = []
2687
2688 self.assertTrue(match is not None,
2689 "Could not generate flow match from pkt")
2690 match.wildcards &= ~ofp.OFPFW_IN_PORT
2691
2692 pkts.append([
2693 "%s" % title,
2694 pkt,
2695 result,
2696 ])
2697
2698 act = action.action_output()
2699 self.testPktsAgainstFlow(pkts, act, match)
2700
2701 testPacket("Basic MAC matching - IPv4 payload",
2702 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2703 scapy.Ether(dst=dl_dst, src=dl_src, type=0x800) / scapy.IP(),
2704 self.RESULT_MATCH
2705 )
2706 testPacket("Basic MAC matching - VMware beacon - no payload",
2707 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2708 scapy.Ether(dst=dl_dst, src=dl_src, type=0x8922),
2709 self.RESULT_MATCH
2710 )
2711 testPacket("Basic MAC matching - VMware beacon - with payload",
2712 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2713 scapy.Ether(dst=dl_dst, src=dl_src, type=0x8922)/ ("X" * 1),
2714 self.RESULT_MATCH
2715 )
2716 testPacket("Basic MAC matching - IPv6 payload",
2717 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2718 scapy.Ether(dst=dl_dst, src=dl_src) / scapy.IPv6(),
2719 self.RESULT_MATCH
2720 )
2721 testPacket("Basic MAC matching with VLAN tag present",
2722 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2723 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002724 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002725 scapy.IP(),
2726 self.RESULT_MATCH
2727 )
2728 testPacket("Basic MAC matching with VLAN tag present",
2729 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2730 dl_type=0x800),
2731 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002732 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002733 scapy.IP(),
2734 self.RESULT_MATCH
2735 )
2736 testPacket("Ether matching with VLAN tag present - No type match",
2737 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2738 dl_type=0x801),
2739 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002740 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002741 scapy.IP(),
2742 self.RESULT_NOMATCH
2743 )
2744 testPacket("Ether matching with VLAN tag present - No type match 0x8100",
2745 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2746 dl_type=0x8100),
2747 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002748 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002749 scapy.IP(),
2750 self.RESULT_NOMATCH
2751 )
2752 testPacket("Ether matching with double VLAN tag - Wrong type match",
2753 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2754 dl_type=0x800),
2755 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002756 scapy.Dot1Q(prio=5, vlan=1000)/ \
2757 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002758 scapy.IP(),
2759 self.RESULT_NOMATCH
2760 )
2761 testPacket("Ether matching with double VLAN tag - Type match",
2762 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2763 dl_type=0x8100),
2764 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002765 scapy.Dot1Q(prio=5, vlan=1000)/ \
2766 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002767 scapy.IP(),
2768 self.RESULT_MATCH
2769 )
2770 testPacket("IP matching - VLAN tag",
2771 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2772 dl_type=0x0800,
2773 nw_src=parse_ip(ip_src), nw_dst=parse_ip(ip_dst)),
2774 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002775 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002776 scapy.IP(src=ip_src, dst=ip_dst),
2777 self.RESULT_MATCH
2778 )
2779 # XXX:
2780 # - Matching on VLAN ID and Prio
2781 # - Actions
2782
2783
2784
Dan Talayco9f47f4d2010-06-03 13:54:37 -07002785if __name__ == "__main__":
2786 print "Please run through oft script: ./oft --test_spec=basic"