blob: 4a9f7cc97a619ce90d1a547c6e0326b7d60f2b7c [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
Dan Talayco5eba8442010-03-10 13:58:43 -080020
Rich Lane477f4812012-10-04 22:49:00 -070021from oftest import config
Dan Talayco5eba8442010-03-10 13:58:43 -080022import oftest.controller as controller
23import oftest.cstruct as ofp
24import oftest.message as message
25import oftest.dataplane as dataplane
26import oftest.action as action
27import oftest.parse as parse
Rich Laneb90a1c42012-10-05 09:16:05 -070028import oftest.base_tests as base_tests
29import basic # for IterCases
Dan Talayco5eba8442010-03-10 13:58:43 -080030
Christian Dickmann8b59b4b2012-09-23 16:48:30 -070031from oftest.parse import parse_mac, parse_ip
32
Rich Laneda3b5ad2012-10-03 09:05:32 -070033from oftest.testutils import *
Dan Talayco5eba8442010-03-10 13:58:43 -080034
Dan Talayco551befa2010-07-15 17:05:32 -070035WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
Dan Talayco488fbc52012-04-09 16:30:41 -070036 ofp.OFPFW_DL_VLAN | ofp.OFPFW_DL_VLAN_PCP,
Dan Talayco551befa2010-07-15 17:05:32 -070037 ofp.OFPFW_DL_SRC,
38 ofp.OFPFW_DL_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070039 (ofp.OFPFW_DL_TYPE | ofp.OFPFW_NW_SRC_ALL |
40 ofp.OFPFW_NW_DST_ALL | ofp.OFPFW_NW_TOS | ofp.OFPFW_NW_PROTO |
41 ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
42 (ofp.OFPFW_NW_PROTO | ofp.OFPFW_TP_SRC | ofp.OFPFW_TP_DST),
Dan Talayco551befa2010-07-15 17:05:32 -070043 ofp.OFPFW_TP_SRC,
44 ofp.OFPFW_TP_DST,
Dan Talayco488fbc52012-04-09 16:30:41 -070045 ofp.OFPFW_NW_SRC_MASK,
46 ofp.OFPFW_NW_DST_MASK,
Dan Talayco551befa2010-07-15 17:05:32 -070047 ofp.OFPFW_DL_VLAN_PCP,
48 ofp.OFPFW_NW_TOS]
49
Dan Talayco488fbc52012-04-09 16:30:41 -070050NO_WILDCARD_VALUES = [(ofp.OFPFW_ALL ^ ofp.OFPFW_IN_PORT),
51 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN),
52 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_SRC),
53 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_DST),
54 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE),
55 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO),
56 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
57 ofp.OFPFW_TP_SRC),
58 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
59 ofp.OFPFW_TP_DST),
60 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
61 ofp.OFPFW_NW_SRC_MASK),
62 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
63 ofp.OFPFW_NW_DST_MASK),
64 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_VLAN ^ ofp.OFPFW_DL_VLAN_PCP),
65 (ofp.OFPFW_ALL ^ ofp.OFPFW_DL_TYPE ^ ofp.OFPFW_NW_PROTO ^
66 ofp.OFPFW_NW_TOS)]
67
Dan Talayco551befa2010-07-15 17:05:32 -070068MODIFY_ACTION_VALUES = [ofp.OFPAT_SET_VLAN_VID,
69 ofp.OFPAT_SET_VLAN_PCP,
70 ofp.OFPAT_STRIP_VLAN,
71 ofp.OFPAT_SET_DL_SRC,
72 ofp.OFPAT_SET_DL_DST,
73 ofp.OFPAT_SET_NW_SRC,
74 ofp.OFPAT_SET_NW_DST,
75 ofp.OFPAT_SET_NW_TOS,
76 ofp.OFPAT_SET_TP_SRC,
77 ofp.OFPAT_SET_TP_DST]
78
Dan Talayco21381562010-07-17 00:34:47 -070079TEST_VID_DEFAULT = 2
80
Rich Laneb90a1c42012-10-05 09:16:05 -070081class DirectPacket(base_tests.SimpleDataPlane):
Dan Talayco5eba8442010-03-10 13:58:43 -080082 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -070083 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -080084
85 Generate a packet
86 Generate and install a matching flow
87 Add action to direct the packet to an egress port
88 Send the packet to ingress dataplane port
89 Verify the packet is received at the egress port only
90 """
91 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -070092 self.handleFlow()
93
94 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -070095 of_ports = config["port_map"].keys()
Dan Talayco5eba8442010-03-10 13:58:43 -080096 of_ports.sort()
97 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
98
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -070099 if (pkttype == 'ICMP'):
100 pkt = simple_icmp_packet()
101 else:
102 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700103 match = packet_to_flow_match(self, pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700104 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800105 self.assertTrue(match is not None,
106 "Could not generate flow match from pkt")
107 act = action.action_output()
108
109 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700110 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700111 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700112
Dan Talayco5eba8442010-03-10 13:58:43 -0800113 ingress_port = of_ports[idx]
114 egress_port = of_ports[(idx + 1) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700115 logging.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700116 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800117
118 match.in_port = ingress_port
119
120 request = message.flow_mod()
121 request.match = match
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700122
Dan Talayco5eba8442010-03-10 13:58:43 -0800123 request.buffer_id = 0xffffffff
124 act.port = egress_port
Rich Lanee30455b2013-01-03 16:24:44 -0800125 request.actions.add(act)
Dan Talayco5eba8442010-03-10 13:58:43 -0800126
Rich Lane9a003812012-10-04 17:17:59 -0700127 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800128 self.controller.message_send(request)
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700129 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco5eba8442010-03-10 13:58:43 -0800130
Rich Lane9a003812012-10-04 17:17:59 -0700131 logging.info("Sending packet to dp port " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800132 str(ingress_port))
133 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700134
135 exp_pkt_arg = None
136 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700137 if config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700138 exp_pkt_arg = pkt
139 exp_port = egress_port
140
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700141 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700142 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800143 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700144 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800145 str(rcv_port))
146 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
147 self.assertEqual(str(pkt), str(rcv_pkt),
148 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700149
Rich Laneb90a1c42012-10-05 09:16:05 -0700150class DirectPacketController(base_tests.SimpleDataPlane):
Rich Lane51c23b32012-07-27 16:37:25 -0700151 """
152 Send packet to the controller port
153
154 Generate a packet
155 Generate and install a matching flow
156 Add action to direct the packet to the controller port
157 Send the packet to ingress dataplane port
158 Verify the packet is received at the controller port
159 """
160 def runTest(self):
161 self.handleFlow()
162
163 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700164 of_ports = config["port_map"].keys()
Rich Lane51c23b32012-07-27 16:37:25 -0700165 of_ports.sort()
166 self.assertTrue(len(of_ports) > 0, "Not enough ports for test")
167
168 if (pkttype == 'ICMP'):
169 pkt = simple_icmp_packet()
170 else:
171 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700172 match = packet_to_flow_match(self, pkt)
Rich Lane51c23b32012-07-27 16:37:25 -0700173 match.wildcards &= ~ofp.OFPFW_IN_PORT
174 self.assertTrue(match is not None,
175 "Could not generate flow match from pkt")
176 act = action.action_output()
177
Rich Lane9a003812012-10-04 17:17:59 -0700178 rv = delete_all_flows(self.controller)
Rich Lane51c23b32012-07-27 16:37:25 -0700179 self.assertEqual(rv, 0, "Failed to delete all flows")
180
181 ingress_port = of_ports[0]
182 match.in_port = ingress_port
183
184 request = message.flow_mod()
185 request.match = match
186
187 request.buffer_id = 0xffffffff
188 act.port = ofp.OFPP_CONTROLLER
189 act.max_len = 65535
Rich Lanee30455b2013-01-03 16:24:44 -0800190 request.actions.add(act)
Rich Lane51c23b32012-07-27 16:37:25 -0700191
Rich Lane9a003812012-10-04 17:17:59 -0700192 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800193 self.controller.message_send(request)
Rich Lane51c23b32012-07-27 16:37:25 -0700194 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
195
Rich Lane9a003812012-10-04 17:17:59 -0700196 logging.info("Sending packet to dp port " +
Rich Lane51c23b32012-07-27 16:37:25 -0700197 str(ingress_port))
198 self.dataplane.send(ingress_port, str(pkt))
199
200 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
201
202 self.assertTrue(response is not None,
203 'Packet in message not received by controller')
204 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700205 logging.debug("Sent %s" % format_packet(pkt))
206 logging.debug("Resp %s" % format_packet(response.data))
Rich Lane51c23b32012-07-27 16:37:25 -0700207 self.assertTrue(False,
208 'Response packet does not match send packet' +
209 ' for controller port')
210
Howard Pershf97840f2012-04-10 16:30:42 -0700211
Rich Laneb90a1c42012-10-05 09:16:05 -0700212class DirectPacketQueue(base_tests.SimpleDataPlane):
Howard Pershf97840f2012-04-10 16:30:42 -0700213 """
214 Send packet to single queue on single egress port
215
216 Generate a packet
217 Generate and install a matching flow
218 Add action to direct the packet to an egress port and queue
219 Send the packet to ingress dataplane port
220 Verify the packet is received at the egress port only
221 """
222 def runTest(self):
223 self.handleFlow()
224
Howard Persh670b5672012-04-13 09:08:29 -0700225 def portQueuesGet(self, queue_stats, port_num):
226 result = []
227 for qs in queue_stats.stats:
228 if qs.port_no != port_num:
229 continue
230 result.append(qs.queue_id)
231 return result
232
Howard Pershf97840f2012-04-10 16:30:42 -0700233 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700234 of_ports = config["port_map"].keys()
Howard Pershf97840f2012-04-10 16:30:42 -0700235 of_ports.sort()
236 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
237
238 if (pkttype == 'ICMP'):
239 pkt = simple_icmp_packet()
240 else:
241 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700242 match = packet_to_flow_match(self, pkt)
Howard Pershf97840f2012-04-10 16:30:42 -0700243 match.wildcards &= ~ofp.OFPFW_IN_PORT
244 self.assertTrue(match is not None,
245 "Could not generate flow match from pkt")
246
Howard Persh670b5672012-04-13 09:08:29 -0700247 # Get queue stats from switch
248
249 request = message.queue_stats_request()
250 request.port_no = ofp.OFPP_ALL
251 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700252 (queue_stats, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700253 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
254
255 act = action.action_enqueue()
Howard Pershf97840f2012-04-10 16:30:42 -0700256
257 for idx in range(len(of_ports)):
Howard Pershf97840f2012-04-10 16:30:42 -0700258 ingress_port = of_ports[idx]
259 egress_port = of_ports[(idx + 1) % len(of_ports)]
Howard Pershf97840f2012-04-10 16:30:42 -0700260
Howard Persh670b5672012-04-13 09:08:29 -0700261 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700262 logging.info("Ingress " + str(ingress_port)
Howard Persh670b5672012-04-13 09:08:29 -0700263 + " to egress " + str(egress_port)
264 + " queue " + str(egress_queue_id)
265 )
Howard Pershf97840f2012-04-10 16:30:42 -0700266
Rich Lane9a003812012-10-04 17:17:59 -0700267 rv = delete_all_flows(self.controller)
Howard Persh670b5672012-04-13 09:08:29 -0700268 self.assertEqual(rv, 0, "Failed to delete all flows")
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)
Howard Persh670b5672012-04-13 09:08:29 -0700282 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
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 Lane9a003812012-10-04 17:17:59 -0700397 rv = delete_all_flows(self.controller)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700398 self.assertEqual(rv, 0, "Failed to delete all flows")
399
400 match.in_port = ingress_port
401
402 request = message.flow_mod()
403 request.match = match
404
405 request.buffer_id = 0xffffffff
406 act.port = egress_port
407 act.queue_id = egress_queue_id
Rich Lanee30455b2013-01-03 16:24:44 -0800408 request.actions.add(act)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700409
Rich Lane9a003812012-10-04 17:17:59 -0700410 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800411 self.controller.message_send(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700412 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
413
414 # Get current stats for selected egress queue
415
416 request = message.queue_stats_request()
417 request.port_no = egress_port
418 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700419 (qs_before, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700420 self.assertNotEqual(qs_before, None, "Queue stats request failed")
421
Rich Lane9a003812012-10-04 17:17:59 -0700422 logging.info("Sending packet to dp port " +
Ken Chiang899ff8e2012-05-23 18:26:12 -0700423 str(ingress_port))
424 self.dataplane.send(ingress_port, str(pkt))
425
426 exp_pkt_arg = None
427 exp_port = None
428
Rich Lanee5779d32012-10-05 17:56:04 -0700429 count = 0
Ken Chiang899ff8e2012-05-23 18:26:12 -0700430 while True:
Dan Talaycoc689a792012-09-28 14:22:53 -0700431 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700432 if not response: # Timeout
433 break
434 if dataplane.match_exp_pkt(pkt, response.data): # Got match
435 break
Rich Lane477f4812012-10-04 22:49:00 -0700436 if not config["relax"]: # Only one attempt to match
Ken Chiang899ff8e2012-05-23 18:26:12 -0700437 break
438 count += 1
439 if count > 10: # Too many tries
440 break
441
442 self.assertTrue(response is not None,
443 'Packet in message not received by controller')
444 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700445 logging.debug("Sent %s" % format_packet(pkt))
446 logging.debug("Resp %s" % format_packet(response.data))
Ken Chiang899ff8e2012-05-23 18:26:12 -0700447 self.assertTrue(False,
448 'Response packet does not match send packet' +
449 ' for controller port')
450
451 # FIXME: instead of sleeping, keep requesting queue stats until
452 # the expected queue counter increases or some large timeout is
453 # reached
454 time.sleep(2)
455
456 # Get current stats for selected egress queue again
457
458 request = message.queue_stats_request()
459 request.port_no = egress_port
460 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700461 (qs_after, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700462 self.assertNotEqual(qs_after, None, "Queue stats request failed")
463
464 # Make sure that tx packet counter for selected egress queue was
465 # incremented
466
467 self.assertEqual(qs_after.stats[0].tx_packets, \
468 qs_before.stats[0].tx_packets + 1, \
469 "Verification of egress queue tx packet count failed"
470 )
471
Howard Pershf97840f2012-04-10 16:30:42 -0700472
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700473class DirectPacketICMP(DirectPacket):
474 """
475 Send ICMP packet to single egress port
476
477 Generate a ICMP packet
478 Generate and install a matching flow
479 Add action to direct the packet to an egress port
480 Send the packet to ingress dataplane port
481 Verify the packet is received at the egress port only
482 Difference from DirectPacket test is that sent packet is ICMP
483 """
484 def runTest(self):
485 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700486
Rich Laneb90a1c42012-10-05 09:16:05 -0700487class DirectTwoPorts(base_tests.SimpleDataPlane):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700488 """
489 Send packet to two egress ports
490
491 Generate a packet
492 Generate and install a matching flow
493 Add action to direct the packet to two egress ports
494 Send the packet to ingress dataplane port
495 Verify the packet is received at the two egress ports
496 """
497 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700498 of_ports = config["port_map"].keys()
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700499 of_ports.sort()
500 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
501
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700502 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700503 match = packet_to_flow_match(self, pkt)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700504 match.wildcards &= ~ofp.OFPFW_IN_PORT
505 self.assertTrue(match is not None,
506 "Could not generate flow match from pkt")
507 act = action.action_output()
508
509 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700510 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700511 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700512
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700513 ingress_port = of_ports[idx]
514 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
515 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700516 logging.info("Ingress " + str(ingress_port) +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700517 " to egress " + str(egress_port1) + " and " +
518 str(egress_port2))
519
520 match.in_port = ingress_port
521
522 request = message.flow_mod()
523 request.match = match
524 request.buffer_id = 0xffffffff
525 act.port = egress_port1
Rich Lanee30455b2013-01-03 16:24:44 -0800526 request.actions.add(act)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700527 act.port = egress_port2
Rich Lanee30455b2013-01-03 16:24:44 -0800528 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700529 # logging.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700530
Rich Lane9a003812012-10-04 17:17:59 -0700531 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800532 self.controller.message_send(request)
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700533 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700534
Rich Lane9a003812012-10-04 17:17:59 -0700535 logging.info("Sending packet to dp port " +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700536 str(ingress_port))
537 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700538 yes_ports = set([egress_port1, egress_port2])
539 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700540
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700541 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Rich Lane2014f9b2012-10-05 15:29:40 -0700542 self)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700543
Rich Laneb90a1c42012-10-05 09:16:05 -0700544class DirectMCNonIngress(base_tests.SimpleDataPlane):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700545 """
546 Multicast to all non-ingress ports
547
548 Generate a packet
549 Generate and install a matching flow
550 Add action to direct the packet to all non-ingress ports
551 Send the packet to ingress dataplane port
552 Verify the packet is received at all non-ingress ports
553
554 Does not use the flood action
555 """
556 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700557 of_ports = config["port_map"].keys()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700558 of_ports.sort()
559 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
560
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700561 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700562 match = packet_to_flow_match(self, pkt)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700563 match.wildcards &= ~ofp.OFPFW_IN_PORT
564 self.assertTrue(match is not None,
565 "Could not generate flow match from pkt")
566 act = action.action_output()
567
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700568 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700569 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700570 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700571
Rich Lane9a003812012-10-04 17:17:59 -0700572 logging.info("Ingress " + str(ingress_port) +
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700573 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700574 match.in_port = ingress_port
575
576 request = message.flow_mod()
577 request.match = match
578 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700579 for egress_port in of_ports:
580 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700581 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700582 act.port = egress_port
Rich Lanee30455b2013-01-03 16:24:44 -0800583 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700584 logging.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700585
Rich Lane9a003812012-10-04 17:17:59 -0700586 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800587 self.controller.message_send(request)
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700588 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700589
Rich Lane9a003812012-10-04 17:17:59 -0700590 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700591 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700592 yes_ports = set(of_ports).difference([ingress_port])
593 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700594 self)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700595
Dan Talayco32fa6542010-05-11 15:54:08 -0700596
Rich Laneb90a1c42012-10-05 09:16:05 -0700597class DirectMC(base_tests.SimpleDataPlane):
Dan Talayco32fa6542010-05-11 15:54:08 -0700598 """
599 Multicast to all ports including ingress
600
601 Generate a packet
602 Generate and install a matching flow
603 Add action to direct the packet to all non-ingress ports
604 Send the packet to ingress dataplane port
605 Verify the packet is received at all ports
606
607 Does not use the flood action
608 """
609 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700610 of_ports = config["port_map"].keys()
Dan Talayco32fa6542010-05-11 15:54:08 -0700611 of_ports.sort()
612 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
613
Dan Talayco32fa6542010-05-11 15:54:08 -0700614 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700615 match = packet_to_flow_match(self, pkt)
Dan Talayco32fa6542010-05-11 15:54:08 -0700616 match.wildcards &= ~ofp.OFPFW_IN_PORT
617 self.assertTrue(match is not None,
618 "Could not generate flow match from pkt")
619 act = action.action_output()
620
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700621 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700622 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700623 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700624
Rich Lane9a003812012-10-04 17:17:59 -0700625 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700626 match.in_port = ingress_port
627
628 request = message.flow_mod()
629 request.match = match
630 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700631 for egress_port in of_ports:
632 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700633 act.port = ofp.OFPP_IN_PORT
634 else:
635 act.port = egress_port
Rich Lanee30455b2013-01-03 16:24:44 -0800636 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700637 # logging.info(request.show())
Dan Talayco2e77a842010-05-12 15:39:46 -0700638
Rich Lane9a003812012-10-04 17:17:59 -0700639 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800640 self.controller.message_send(request)
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700641 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2e77a842010-05-12 15:39:46 -0700642
Rich Lane9a003812012-10-04 17:17:59 -0700643 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700644 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700645 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco2e77a842010-05-12 15:39:46 -0700646
Rich Laneb90a1c42012-10-05 09:16:05 -0700647class Flood(base_tests.SimpleDataPlane):
Dan Talayco2e77a842010-05-12 15:39:46 -0700648 """
649 Flood to all ports except ingress
650
651 Generate a packet
652 Generate and install a matching flow
653 Add action to flood the packet
654 Send the packet to ingress dataplane port
655 Verify the packet is received at all other ports
656 """
657 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700658 of_ports = config["port_map"].keys()
Dan Talayco2e77a842010-05-12 15:39:46 -0700659 of_ports.sort()
660 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
661
662 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700663 match = packet_to_flow_match(self, pkt)
Dan Talayco2e77a842010-05-12 15:39:46 -0700664 match.wildcards &= ~ofp.OFPFW_IN_PORT
665 self.assertTrue(match is not None,
666 "Could not generate flow match from pkt")
667 act = action.action_output()
668
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700669 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700670 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700671 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700672
Rich Lane9a003812012-10-04 17:17:59 -0700673 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700674 match.in_port = ingress_port
675
676 request = message.flow_mod()
677 request.match = match
678 request.buffer_id = 0xffffffff
679 act.port = ofp.OFPP_FLOOD
Rich Lanee30455b2013-01-03 16:24:44 -0800680 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700681 logging.info(request.show())
Dan Talayco32fa6542010-05-11 15:54:08 -0700682
Rich Lane9a003812012-10-04 17:17:59 -0700683 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800684 self.controller.message_send(request)
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700685 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco32fa6542010-05-11 15:54:08 -0700686
Rich Lane9a003812012-10-04 17:17:59 -0700687 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco32fa6542010-05-11 15:54:08 -0700688 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700689 yes_ports = set(of_ports).difference([ingress_port])
690 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700691 self)
Dan Talayco3be5b062010-05-12 15:46:21 -0700692
Rich Laneb90a1c42012-10-05 09:16:05 -0700693class FloodPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco3be5b062010-05-12 15:46:21 -0700694 """
695 Flood to all ports plus send to ingress port
696
697 Generate a packet
698 Generate and install a matching flow
699 Add action to flood the packet
700 Add action to send to ingress port
701 Send the packet to ingress dataplane port
702 Verify the packet is received at all other ports
703 """
704 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700705 of_ports = config["port_map"].keys()
Dan Talayco3be5b062010-05-12 15:46:21 -0700706 of_ports.sort()
707 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
708
709 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700710 match = packet_to_flow_match(self, pkt)
Dan Talayco3be5b062010-05-12 15:46:21 -0700711 match.wildcards &= ~ofp.OFPFW_IN_PORT
712 self.assertTrue(match is not None,
713 "Could not generate flow match from pkt")
714 act = action.action_output()
715
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700716 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700717 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700718 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700719
Rich Lane9a003812012-10-04 17:17:59 -0700720 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700721 match.in_port = ingress_port
722
723 request = message.flow_mod()
724 request.match = match
725 request.buffer_id = 0xffffffff
726 act.port = ofp.OFPP_FLOOD
Rich Lanee30455b2013-01-03 16:24:44 -0800727 request.actions.add(act)
Dan Talayco4aa13122010-05-12 15:54:44 -0700728 act.port = ofp.OFPP_IN_PORT
Rich Lanee30455b2013-01-03 16:24:44 -0800729 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700730 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700731
Rich Lane9a003812012-10-04 17:17:59 -0700732 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800733 self.controller.message_send(request)
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700734 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700735
Rich Lane9a003812012-10-04 17:17:59 -0700736 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700737 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700738 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco4aa13122010-05-12 15:54:44 -0700739
Rich Laneb90a1c42012-10-05 09:16:05 -0700740class All(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700741 """
742 Send to OFPP_ALL port
743
744 Generate a packet
745 Generate and install a matching flow
746 Add action to forward to OFPP_ALL
747 Send the packet to ingress dataplane port
748 Verify the packet is received at all other ports
749 """
750 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700751 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700752 of_ports.sort()
753 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
754
755 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700756 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700757 match.wildcards &= ~ofp.OFPFW_IN_PORT
758 self.assertTrue(match is not None,
759 "Could not generate flow match from pkt")
760 act = action.action_output()
761
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700762 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700763 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700764 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700765
Rich Lane9a003812012-10-04 17:17:59 -0700766 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700767 match.in_port = ingress_port
768
769 request = message.flow_mod()
770 request.match = match
771 request.buffer_id = 0xffffffff
772 act.port = ofp.OFPP_ALL
Rich Lanee30455b2013-01-03 16:24:44 -0800773 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700774 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700775
Rich Lane9a003812012-10-04 17:17:59 -0700776 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800777 self.controller.message_send(request)
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700778 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700779
Rich Lane9a003812012-10-04 17:17:59 -0700780 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700781 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700782 yes_ports = set(of_ports).difference([ingress_port])
783 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700784 self)
Dan Talayco4aa13122010-05-12 15:54:44 -0700785
Rich Laneb90a1c42012-10-05 09:16:05 -0700786class AllPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700787 """
788 Send to OFPP_ALL port and ingress port
789
790 Generate a packet
791 Generate and install a matching flow
792 Add action to forward to OFPP_ALL
793 Add action to forward to ingress port
794 Send the packet to ingress dataplane port
795 Verify the packet is received at all other ports
796 """
797 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700798 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700799 of_ports.sort()
800 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
801
802 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700803 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700804 match.wildcards &= ~ofp.OFPFW_IN_PORT
805 self.assertTrue(match is not None,
806 "Could not generate flow match from pkt")
807 act = action.action_output()
808
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700809 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700810 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700811 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700812
Rich Lane9a003812012-10-04 17:17:59 -0700813 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700814 match.in_port = ingress_port
815
816 request = message.flow_mod()
817 request.match = match
818 request.buffer_id = 0xffffffff
819 act.port = ofp.OFPP_ALL
Rich Lanee30455b2013-01-03 16:24:44 -0800820 request.actions.add(act)
Dan Talayco3be5b062010-05-12 15:46:21 -0700821 act.port = ofp.OFPP_IN_PORT
Rich Lanee30455b2013-01-03 16:24:44 -0800822 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700823 logging.info(request.show())
Dan Talayco3be5b062010-05-12 15:46:21 -0700824
Rich Lane9a003812012-10-04 17:17:59 -0700825 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -0800826 self.controller.message_send(request)
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700827 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco3be5b062010-05-12 15:46:21 -0700828
Rich Lane9a003812012-10-04 17:17:59 -0700829 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco3be5b062010-05-12 15:46:21 -0700830 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700831 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700832
Rich Laneb90a1c42012-10-05 09:16:05 -0700833class FloodMinusPort(base_tests.SimpleDataPlane):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700834 """
835 Config port with No_Flood and test Flood action
836
837 Generate a packet
838 Generate a matching flow
839 Add action to forward to OFPP_ALL
840 Set port to no-flood
841 Send the packet to ingress dataplane port
842 Verify the packet is received at all other ports except
843 the ingress port and the no_flood port
844 """
845 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700846 of_ports = config["port_map"].keys()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700847 of_ports.sort()
848 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
849
850 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700851 match = packet_to_flow_match(self, pkt)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700852 match.wildcards &= ~ofp.OFPFW_IN_PORT
853 self.assertTrue(match is not None,
854 "Could not generate flow match from pkt")
855 act = action.action_output()
856
Rich Lane4b9e38c2012-12-06 16:33:20 -0800857 # Clear OFPPC_NO_FLOOD on each port
858 for of_port in of_ports:
859 rv = port_config_set(self.controller, of_port,
860 0, ofp.OFPPC_NO_FLOOD)
861 self.assertEqual(rv, 0, "Failed to set port config")
862
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700863 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700864 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700865 self.assertEqual(rv, 0, "Failed to delete all flows")
866
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)
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700885 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
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 Lane4ecc1f42012-12-06 16:35:24 -0800898 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
899
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
Dan Talayco551befa2010-07-15 17:05:32 -0700942class ExactMatchTaggedMany(BaseMatchCase):
943 """
944 ExactMatchTagged with many VLANS
945 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700946
Rich Laned1d9c282012-10-04 22:07:10 -0700947 priority = -1
948
Dan Talayco551befa2010-07-15 17:05:32 -0700949 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700950 for vid in range(2,100,10):
Rich Lane477f4812012-10-04 22:49:00 -0700951 flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
Dan Talayco551befa2010-07-15 17:05:32 -0700952 for vid in range(100,4000,389):
Rich Lane477f4812012-10-04 22:49:00 -0700953 flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
954 flow_match_test(self, config["port_map"], dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700955
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700956class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700957 """
958 SingleWildcardMatchPriority
959 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700960
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700961 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700962 self.pkt = simple_tcp_packet()
963 self.flowMsgs = {}
964
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700965 def _ClearTable(self):
Rich Lane9a003812012-10-04 17:17:59 -0700966 rc = delete_all_flows(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700967 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700968 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700969
970 def runTest(self):
971
972 self._Init()
Rich Lane477f4812012-10-04 22:49:00 -0700973 of_ports = config["port_map"].keys()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700974 of_ports.sort()
975
976 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700977 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700978
979 # Run several combinations, each at lower priority settings.
980 # At the end of each call to runPrioFlows(), the table should
981 # be empty. If its not, we'll catch it as the priorities decreases
982 portA = of_ports[0]
983 portB = of_ports[1]
984 portC = of_ports[2]
985
986 # TODO -- these priority numbers should be validated somehow?
987 self.runPrioFlows(portA, portB, portC, 1000, 999)
988 self.runPrioFlows(portB, portC, portA, 998, 997)
989 self.runPrioFlows(portC, portA, portB, 996, 995)
990 self.runPrioFlows(portA, portC, portB, 994, 993)
991
992
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700993
994 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
995 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700996
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700997 if clearTable:
998 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700999
1000 # Sanity check flow at lower priority from pA to pB
Rich Lane9a003812012-10-04 17:17:59 -07001001 logging.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001002 % (portA, portB, portC, prioHigher, prioLower))
1003
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001004 # Sanity check flow at lower priority from pA to pC
1005 self.installFlow(prioLower, portA, portC)
1006 self.verifyFlow(portA, portC)
1007 self.removeFlow(prioLower)
1008
1009 # Install and verify pA->pB @ prioLower
1010 self.installFlow(prioLower, portA, portB)
1011 self.verifyFlow(portA, portB)
1012
1013 # Install and verify pA->pC @ prioHigher, should override pA->pB
1014 self.installFlow(prioHigher, portA, portC)
1015 self.verifyFlow(portA, portC)
1016 # remove pA->pC
1017 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001018 # Old flow pA -> pB @ prioLower should still be active
1019 self.verifyFlow(portA, portB)
1020 self.removeFlow(prioLower)
1021
1022 # Table should be empty at this point, leave it alone as
1023 # an assumption for future test runs
1024
1025
1026
Ed Swierk99a74de2012-08-22 06:40:54 -07001027 def installFlow(self, prio, inp, egp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001028 wildcards=ofp.OFPFW_DL_SRC):
Ed Swierk99a74de2012-08-22 06:40:54 -07001029 wildcards |= required_wildcards(self)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001030 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001031 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001032 egr_ports=egp)
1033 request.priority = prio
Rich Lane9a003812012-10-04 17:17:59 -07001034 logging.debug("Install flow with priority " + str(prio))
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001035 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001036 self.flowMsgs[prio] = request
1037
1038 def removeFlow(self, prio):
1039 if self.flowMsgs.has_key(prio):
1040 msg = self.flowMsgs[prio]
1041 msg.command = ofp.OFPFC_DELETE_STRICT
1042 # This *must* be set for DELETE
1043 msg.out_port = ofp.OFPP_NONE
Rich Lane9a003812012-10-04 17:17:59 -07001044 logging.debug("Remove flow with priority " + str(prio))
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001045 self.controller.message_send(msg)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001046 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001047 else:
1048 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001049
1050
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001051 def verifyFlow(self, inp, egp, pkt=None):
1052 if pkt == None:
1053 pkt = self.pkt
1054
Rich Lane9a003812012-10-04 17:17:59 -07001055 logging.info("Pkt match test: " + str(inp) + " to " + str(egp))
1056 logging.debug("Send packet: " + str(inp) + " to " + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001057 self.dataplane.send(inp, str(pkt))
1058 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001059
1060
1061
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001062class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
1063
1064 def runTest(self):
1065
1066 self._Init()
1067
Rich Lane477f4812012-10-04 22:49:00 -07001068 of_ports = config["port_map"].keys()
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001069 of_ports.sort()
1070
1071 # Install an entry from 0 -> 1 @ prio 1000
1072 self._ClearTable()
1073 self.installFlow(1000, of_ports[0], of_ports[1])
1074 self.verifyFlow(of_ports[0], of_ports[1])
1075 self.installFlow(1000, of_ports[1], of_ports[0])
1076 self.verifyFlow(of_ports[1], of_ports[0])
1077 self.installFlow(1001, of_ports[0], of_ports[1])
1078 self.verifyFlow(of_ports[0], of_ports[1])
1079 self.installFlow(1001, of_ports[1], of_ports[0])
1080 self.verifyFlow(of_ports[1], of_ports[0])
1081 self.removeFlow(1001)
1082 self.verifyFlow(of_ports[0], of_ports[1])
1083 self.removeFlow(1000)
1084
1085
1086
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001087class WildcardPriority(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001088 """
1089 1. Add wildcard flow, verify packet received.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001090 2. Add wildcard flow with higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001091 on port specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001092 3. Add wildcard flow with lower priority, verify packet received
Rich Laneb8392082012-11-21 15:52:54 -08001093 on port specified by the highest priority flow.
Ken Chiang38d7a152012-05-24 15:33:50 -07001094 """
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001095
1096 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001097
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001098 self._Init()
1099
Rich Lane477f4812012-10-04 22:49:00 -07001100 of_ports = config["port_map"].keys()
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001101 of_ports.sort()
1102
1103 self._ClearTable()
Ken Chiang38d7a152012-05-24 15:33:50 -07001104
1105 # Install a flow with wildcards
1106 self.installFlow(999, of_ports[0], of_ports[1],
1107 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001108 self.verifyFlow(of_ports[0], of_ports[1])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001109 # Install a flow with wildcards with higher priority
1110 self.installFlow(1000, of_ports[0], of_ports[2],
1111 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001112 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001113 # Install a flow with wildcards with lower priority
Rich Laneb8392082012-11-21 15:52:54 -08001114 self.installFlow(999, of_ports[0], of_ports[1],
1115 wildcards=ofp.OFPFW_DL_SRC)
Rich Lane0a78fbd2012-12-31 16:25:04 -08001116 self.verifyFlow(of_ports[0], of_ports[2])
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001117
1118
Ken Chiang3978f242012-06-13 14:14:09 -07001119class WildcardPriorityWithDelete(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001120 """
Rich Lane0a78fbd2012-12-31 16:25:04 -08001121 1. Add wildcard match flow, verify packet received.
Ken Chiang38d7a152012-05-24 15:33:50 -07001122 2. Add wildcard flow with higher priority, verify packet received on port
1123 specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001124 3. Add wildcard flow with even higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001125 on port specified by this flow.
1126 4. Delete lowest priority flow, verify packet received on port specified
1127 by highest priority flow.
1128 5. Delete highest priority flow, verify packet received on port specified
1129 by remaining flow.
1130 """
1131
1132 def runTest(self):
1133
1134 self._Init()
1135
Rich Lane477f4812012-10-04 22:49:00 -07001136 of_ports = config["port_map"].keys()
Ken Chiang38d7a152012-05-24 15:33:50 -07001137 of_ports.sort()
1138
1139 self._ClearTable()
1140
Rich Lane0a78fbd2012-12-31 16:25:04 -08001141 # Install a flow with wildcards
1142 self.installFlow(250, of_ports[0], of_ports[1],
1143 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001144 self.verifyFlow(of_ports[0], of_ports[1])
1145 # Install a flow with wildcards of higher priority
1146 self.installFlow(1250, of_ports[0], of_ports[2],
1147 wildcards=ofp.OFPFW_DL_DST)
1148 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001149 # Install a flow with wildcards with even higher priority
1150 self.installFlow(2001, of_ports[0], of_ports[3],
1151 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001152 self.verifyFlow(of_ports[0], of_ports[3])
1153 # Delete lowest priority flow
1154 self.removeFlow(250)
1155 self.verifyFlow(of_ports[0], of_ports[3])
1156 # Delete highest priority flow
1157 self.removeFlow(2001)
1158 self.verifyFlow(of_ports[0], of_ports[2])
1159
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001160
Dan Talayco551befa2010-07-15 17:05:32 -07001161class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001162 """
1163 Exercise wildcard matching for all ports
1164
1165 Generate a packet
1166 Generate and install a matching flow with wildcard mask
1167 Add action to forward to a port
1168 Send the packet to the port
1169 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001170 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001171 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001172 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001173 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001174 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001175 wc |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001176 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001177 # Set nonzero VLAN id to avoid sending priority-tagged packet
1178 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001179 else:
1180 dl_vlan = -1
Rich Lane477f4812012-10-04 22:49:00 -07001181 flow_match_test(self, config["port_map"], wildcards=wc,
Dan Talayco4431d542012-03-21 16:42:16 -07001182 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001183
Dan Talayco551befa2010-07-15 17:05:32 -07001184class SingleWildcardMatchTagged(BaseMatchCase):
1185 """
1186 SingleWildcardMatch with tagged packets
1187 """
1188 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001189 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001190 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001191 wc |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001192 flow_match_test(self, config["port_map"], wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -07001193 max_test=10)
1194
1195class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001196 """
Dan Talayco80b54ed2010-07-13 09:48:35 -07001197 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001198
1199 Generate a packet
1200 Generate and install a matching flow with wildcard all except one filed
1201 Add action to forward to a port
1202 Send the packet to the port
1203 Verify the packet is received at all other ports (one port at a time)
1204 Verify flow_expiration message is correct when command option is set
1205 """
1206 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001207 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001208 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001209 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001210 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001211 # Set nonzero VLAN id to avoid sending priority-tagged packet
1212 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001213 else:
1214 dl_vlan = -1
Rich Lane477f4812012-10-04 22:49:00 -07001215 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Dan Talayco4431d542012-03-21 16:42:16 -07001216 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001217
Dan Talayco551befa2010-07-15 17:05:32 -07001218class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1219 """
1220 Match one field with tagged packets
1221 """
1222 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001223 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001224 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001225 all_exp_one_wildcard |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001226 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Dan Talayco21381562010-07-17 00:34:47 -07001227 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001228
1229class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001230 """
1231 Create Wildcard-all flow and exercise for all ports
1232
1233 Generate a packet
1234 Generate and install a matching flow with wildcard-all
1235 Add action to forward to a port
1236 Send the packet to the port
1237 Verify the packet is received at all other ports (one port at a time)
1238 Verify flow_expiration message is correct when command option is set
1239 """
1240 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001241 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001242
Dan Talayco551befa2010-07-15 17:05:32 -07001243class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001244 """
Dan Talayco551befa2010-07-15 17:05:32 -07001245 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001246 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001247 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001248 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Lane477f4812012-10-04 22:49:00 -07001249 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL,
Dan Talayco21381562010-07-17 00:34:47 -07001250 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001251
Dan Talaycoba3745c2010-07-21 21:51:08 -07001252
Dan Talayco551befa2010-07-15 17:05:32 -07001253class AddVLANTag(BaseMatchCase):
1254 """
1255 Add a VLAN tag to an untagged packet
1256 """
1257 def runTest(self):
1258 new_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001259 sup_acts = self.supported_actions
Dan Talayco551befa2010-07-15 17:05:32 -07001260 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001261 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001262 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001263
Dan Talayco551befa2010-07-15 17:05:32 -07001264 len = 100
1265 len_w_vid = 104
1266 pkt = simple_tcp_packet(pktlen=len)
1267 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1268 dl_vlan=new_vid)
1269 vid_act = action.action_set_vlan_vid()
1270 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001271
Rich Lane477f4812012-10-04 22:49:00 -07001272 flow_match_test(self, config["port_map"], pkt=pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001273 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001274
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
1280 priority = -1
1281
Dan Talayco551befa2010-07-15 17:05:32 -07001282 def runTest(self):
1283 pkt = simple_tcp_packet()
Rich Lane477f4812012-10-04 22:49:00 -07001284 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001285 of_ports.sort()
1286 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001287 logging.info("Sending packet to " + str(ing_port))
1288 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001289 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001290
Rich Laneb90a1c42012-10-05 09:16:05 -07001291class PacketOnlyTagged(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001292 """
1293 Just send a packet thru the switch
1294 """
Rich Laned1d9c282012-10-04 22:07:10 -07001295
1296 priority = -1
1297
Dan Talayco551befa2010-07-15 17:05:32 -07001298 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001299 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001300 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
Rich Lane477f4812012-10-04 22:49:00 -07001301 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001302 of_ports.sort()
1303 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001304 logging.info("Sending packet to " + str(ing_port))
1305 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001306 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001307
Dan Talayco551befa2010-07-15 17:05:32 -07001308class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001309 """
1310 Modify the VLAN ID in the VLAN tag of a tagged packet
1311 """
Dan Talaycoaf669322012-09-12 22:51:22 -07001312 def setUp(self):
1313 BaseMatchCase.setUp(self)
1314 self.ing_port=False
1315
Dan Talayco551befa2010-07-15 17:05:32 -07001316 def runTest(self):
1317 old_vid = 2
1318 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001319 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001320 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001321 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001322 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001323
Dan Talayco551befa2010-07-15 17:05:32 -07001324 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1325 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
1326 vid_act = action.action_set_vlan_vid()
1327 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001328
Rich Lane477f4812012-10-04 22:49:00 -07001329 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoaf669322012-09-12 22:51:22 -07001330 action_list=[vid_act], ing_port=self.ing_port)
1331
1332class ModifyVIDToIngress(ModifyVID):
1333 """
1334 Modify the VLAN ID in the VLAN tag of a tagged packet and send to
1335 ingress port
1336 """
1337 def setUp(self):
1338 BaseMatchCase.setUp(self)
1339 self.ing_port=True
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001340
Ken Chiange9a211d2012-04-20 14:52:11 -07001341class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1342 """
1343 With vlan ID and priority wildcarded, perform SET_VLAN_VID action.
1344 The same flow should match on both untagged and tagged packets.
1345 """
1346 def runTest(self):
1347 old_vid = 2
1348 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001349 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001350 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1351 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1352 return
1353
Rich Lane477f4812012-10-04 22:49:00 -07001354 of_ports = config["port_map"].keys()
Ken Chiange9a211d2012-04-20 14:52:11 -07001355 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1356 ing_port = of_ports[0]
1357 egr_ports = of_ports[1]
1358
Rich Lane9a003812012-10-04 17:17:59 -07001359 rv = delete_all_flows(self.controller)
Ken Chiange9a211d2012-04-20 14:52:11 -07001360 self.assertEqual(rv, 0, "Failed to delete all flows")
1361
1362 len_untagged = 100
1363 len_w_vid = 104
1364 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1365 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
1366 dl_vlan_enable=True, dl_vlan=old_vid)
1367 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1368 dl_vlan=new_vid)
Ed Swierk99a74de2012-08-22 06:40:54 -07001369 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1370 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001371 vid_act = action.action_set_vlan_vid()
1372 vid_act.vlan_vid = new_vid
1373 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
1374 wildcards=wildcards, egr_ports=egr_ports,
1375 action_list=[vid_act])
1376 flow_msg_install(self, request)
1377
Rich Lane9a003812012-10-04 17:17:59 -07001378 logging.debug("Send untagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001379 str(egr_ports))
1380 self.dataplane.send(ing_port, str(untagged_pkt))
1381 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1382
Rich Lane9a003812012-10-04 17:17:59 -07001383 logging.debug("Send tagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001384 str(egr_ports))
1385 self.dataplane.send(ing_port, str(tagged_pkt))
1386 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1387
Howard Pershc1199d52012-04-11 14:21:32 -07001388class ModifyVlanPcp(BaseMatchCase):
1389 """
1390 Modify the priority field of the VLAN tag of a tagged packet
1391 """
1392 def runTest(self):
1393 vid = 123
1394 old_vlan_pcp = 2
1395 new_vlan_pcp = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001396 sup_acts = self.supported_actions
Ed Swierk8c3af7f2012-04-24 14:19:17 -07001397 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_PCP):
1398 skip_message_emit(self, "Modify VLAN priority test")
Howard Pershc1199d52012-04-11 14:21:32 -07001399 return
1400
1401 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1402 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1403 vid_act = action.action_set_vlan_pcp()
1404 vid_act.vlan_pcp = new_vlan_pcp
1405
Rich Lane477f4812012-10-04 22:49:00 -07001406 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Howard Pershc1199d52012-04-11 14:21:32 -07001407 action_list=[vid_act])
1408
Dan Talayco551befa2010-07-15 17:05:32 -07001409class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001410 """
1411 Strip the VLAN tag from a tagged packet
1412 """
Dan Talayco551befa2010-07-15 17:05:32 -07001413 def runTest(self):
1414 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001415 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001416 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001417 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001418 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001419
Dan Talayco551befa2010-07-15 17:05:32 -07001420 len_w_vid = 104
1421 len = 100
1422 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1423 dl_vlan=old_vid)
1424 exp_pkt = simple_tcp_packet(pktlen=len)
1425 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001426
Rich Lane477f4812012-10-04 22:49:00 -07001427 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001428 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001429
Ken Chiange9a211d2012-04-20 14:52:11 -07001430class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1431 """
1432 Strip the VLAN tag from a tagged packet.
1433 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1434 """
1435 def runTest(self):
1436 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001437 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001438 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1439 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1440 return
1441
1442 len_w_vid = 104
1443 len_untagged = 100
1444 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1445 dl_vlan=old_vid)
1446 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
Ed Swierk99a74de2012-08-22 06:40:54 -07001447 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1448 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001449 vid_act = action.action_strip_vlan()
1450
Rich Lane477f4812012-10-04 22:49:00 -07001451 flow_match_test(self, config["port_map"],
Ed Swierk99a74de2012-08-22 06:40:54 -07001452 wildcards=wildcards,
Ken Chiange9a211d2012-04-20 14:52:11 -07001453 pkt=pkt, exp_pkt=exp_pkt,
1454 action_list=[vid_act])
1455
Dan Talayco4b2bee62010-07-20 14:10:05 -07001456def init_pkt_args():
1457 """
1458 Pass back a dictionary with default packet arguments
1459 """
1460 args = {}
1461 args["dl_src"] = '00:23:45:67:89:AB'
1462
1463 dl_vlan_enable=False
1464 dl_vlan=-1
Rich Lane477f4812012-10-04 22:49:00 -07001465 if config["test-params"]["vid"]:
Dan Talayco4b2bee62010-07-20 14:10:05 -07001466 dl_vlan_enable=True
Rich Lane477f4812012-10-04 22:49:00 -07001467 dl_vlan = config["test-params"]["vid"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001468
1469# Unpack operator is ** on a dictionary
1470
1471 return args
1472
Dan Talayco551befa2010-07-15 17:05:32 -07001473class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001474 """
1475 Modify the source MAC address (TP1)
1476 """
Dan Talayco551befa2010-07-15 17:05:32 -07001477 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001478 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001479 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001480 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001481 return
1482
1483 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1484 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001485 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001486 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001487
Dan Talayco551befa2010-07-15 17:05:32 -07001488class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001489 """
1490 Modify the dest MAC address (TP1)
1491 """
Dan Talayco551befa2010-07-15 17:05:32 -07001492 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001493 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001494 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001495 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001496 return
1497
1498 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1499 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001500 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001501 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001502
Dan Talayco551befa2010-07-15 17:05:32 -07001503class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001504 """
1505 Modify the source IP address of an IP packet (TP1)
1506 """
Dan Talayco551befa2010-07-15 17:05:32 -07001507 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001508 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001509 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001510 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001511 return
1512
1513 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1514 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001515 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001516 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001517
Dan Talayco551befa2010-07-15 17:05:32 -07001518class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001519 """
1520 Modify the dest IP address of an IP packet (TP1)
1521 """
Dan Talayco551befa2010-07-15 17:05:32 -07001522 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001523 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001524 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001525 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001526 return
1527
1528 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1529 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001530 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001531 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001532
1533class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001534 """
1535 Modify the source TCP port of a TCP packet (TP1)
1536 """
Dan Talayco551befa2010-07-15 17:05:32 -07001537 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001538 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001539 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001540 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001541 return
1542
1543 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1544 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001545 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001546 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001547
Rich Lane01c2b862012-10-26 16:26:25 -07001548class ModifyL4SrcUdp(BaseMatchCase):
1549 """
1550 Modify the source UDP port of a UDP packet
1551 """
1552 def runTest(self):
1553 sup_acts = self.supported_actions
1554 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1555 skip_message_emit(self, "ModifyL4SrcUdp test")
1556 return
1557
1558 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_sport'],
1559 check_test_params=True, tp="udp")
1560 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1561 action_list=acts, max_test=2)
1562
Dan Talayco551befa2010-07-15 17:05:32 -07001563class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001564 """
1565 Modify the dest TCP port of a TCP packet (TP1)
1566 """
Dan Talayco551befa2010-07-15 17:05:32 -07001567 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001568 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001569 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001570 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001571 return
1572
1573 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1574 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001575 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001576 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001577
Rich Lane01c2b862012-10-26 16:26:25 -07001578class ModifyL4DstUdp(BaseMatchCase):
1579 """
1580 Modify the dest UDP port of a UDP packet
1581 """
1582 def runTest(self):
1583 sup_acts = self.supported_actions
1584 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1585 skip_message_emit(self, "ModifyL4DstUdp test")
1586 return
1587
1588 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_dport'],
1589 check_test_params=True, tp="udp")
1590 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1591 action_list=acts, max_test=2)
1592
Dan Talayco551befa2010-07-15 17:05:32 -07001593class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001594 """
1595 Modify the IP type of service of an IP packet (TP1)
1596 """
Dan Talayco551befa2010-07-15 17:05:32 -07001597 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001598 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001599 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001600 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001601 return
Dan Talayco551befa2010-07-15 17:05:32 -07001602
Dan Talayco4b2bee62010-07-20 14:10:05 -07001603 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1604 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001605 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001606 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001607
Dan Talaycof6e76c02012-03-23 10:56:12 -07001608class ModifyL2DstMC(BaseMatchCase):
1609 """
1610 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001611 """
1612 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001613 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001614 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001615 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001616 return
1617
Dan Talaycof6e76c02012-03-23 10:56:12 -07001618 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1619 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001620 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001621 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001622
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001623class ModifyL2DstIngress(BaseMatchCase):
1624 """
1625 Modify the L2 dest and send to the ingress port
1626 """
1627 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001628 sup_acts = self.supported_actions
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001629 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001630 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001631 return
1632
1633 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1634 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001635 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001636 action_list=acts, max_test=2, egr_count=0,
1637 ing_port=True)
1638
Dan Talaycod8ae7582012-03-23 12:24:56 -07001639class ModifyL2DstIngressMC(BaseMatchCase):
1640 """
1641 Modify the L2 dest and send to the ingress port
1642 """
1643 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001644 sup_acts = self.supported_actions
Dan Talaycod8ae7582012-03-23 12:24:56 -07001645 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1646 skip_message_emit(self, "ModifyL2dstMC test")
1647 return
1648
1649 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1650 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001651 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001652 action_list=acts, max_test=2, egr_count=-1,
1653 ing_port=True)
1654
Dan Talaycof6e76c02012-03-23 10:56:12 -07001655class ModifyL2SrcMC(BaseMatchCase):
1656 """
1657 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001658 """
1659 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001660 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001661 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001662 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001663 return
1664
Dan Talaycof6e76c02012-03-23 10:56:12 -07001665 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1666 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001667 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001668 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001669
1670class ModifyL2SrcDstMC(BaseMatchCase):
1671 """
1672 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001673 """
1674 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001675 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001676 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1677 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1678 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001679 return
1680
Dan Talaycof6e76c02012-03-23 10:56:12 -07001681 mod_fields = ['dl_dst', 'dl_src']
1682 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1683 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001684 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001685 action_list=acts, max_test=2, egr_count=-1)
1686
1687class ModifyL2DstVIDMC(BaseMatchCase):
1688 """
1689 Modify the L2 dest and send to 2 ports
1690 """
1691 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001692 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001693 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1694 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1695 skip_message_emit(self, "ModifyL2DstVIDMC test")
1696 return
1697
1698 mod_fields = ['dl_dst', 'dl_vlan']
1699 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1700 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1701 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001702 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001703 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001704
Rich Lane22e74c12012-11-12 15:06:06 -08001705class ModifyAll(BaseMatchCase):
1706 """
1707 Modify all supported fields and output to a port
1708 """
1709 def runTest(self):
1710 sup_acts = self.supported_actions
1711
1712 sup_map = {
1713 "dl_dst" : ofp.OFPAT_SET_DL_DST,
1714 "dl_src" : ofp.OFPAT_SET_DL_SRC,
1715 "dl_vlan_enable" : ofp.OFPAT_SET_VLAN_VID,
1716 "dl_vlan" : ofp.OFPAT_SET_VLAN_VID,
1717 "dl_vlan_pcp" : ofp.OFPAT_SET_VLAN_PCP,
1718 "ip_src" : ofp.OFPAT_SET_NW_SRC,
1719 "ip_dst" : ofp.OFPAT_SET_NW_DST,
1720 "ip_tos" : ofp.OFPAT_SET_NW_TOS,
1721 "tcp_sport" : ofp.OFPAT_SET_TP_SRC,
1722 "tcp_dport" : ofp.OFPAT_SET_TP_DST,
1723 }
1724
1725 mod_fields = [field for (field, bit) in sup_map.items() if (sup_acts & 1 << bit)]
1726 random.shuffle(mod_fields)
1727 start_field_vals = { "dl_vlan_enable" : True }
1728 mod_field_vals = { "dl_vlan_enable" : True }
1729 logging.info("modifying fields: %s" % repr(mod_fields))
1730
1731 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1732 mod_fields=mod_fields,
1733 start_field_vals=start_field_vals,
1734 mod_field_vals=mod_field_vals,
1735 check_test_params=True)
1736 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1737 action_list=acts, max_test=2)
1738
Dan Talaycofa6454f2012-04-05 10:04:13 -07001739class FlowToggle(BaseMatchCase):
1740 """
1741 Add flows to the table and modify them repeatedly
Dan Talaycof7c41312012-07-23 12:53:19 -07001742
1743 This is done by using only "add" flow messages. Since the check overlap
1744 flag is not set, the switch is supposed to modify the existing flow if
1745 the match already exists.
1746
1747 Would probably be better to exercise more of the flow modify commands
1748 (add, modify, delete +/- strict).
Dan Talaycofa6454f2012-04-05 10:04:13 -07001749 """
1750 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001751 flow_count = test_param_get('ft_flow_count', default=20)
1752 iter_count = test_param_get('ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001753
Rich Lane9a003812012-10-04 17:17:59 -07001754 logging.info("Running flow toggle with %d flows, %d iterations" %
Dan Talaycofa6454f2012-04-05 10:04:13 -07001755 (flow_count, iter_count))
1756 acts = []
1757 acts.append(action.action_output())
1758 acts.append(action.action_output())
1759
Rich Lane477f4812012-10-04 22:49:00 -07001760 of_ports = config["port_map"].keys()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001761 if len(of_ports) < 3:
1762 self.assertTrue(False, "Too few ports for test")
1763
1764 for idx in range(2):
1765 acts[idx].port = of_ports[idx]
1766
1767 flows = []
1768 flows.append([])
1769 flows.append([])
1770
Ed Swierk99a74de2012-08-22 06:40:54 -07001771 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_SRC |
1772 ofp.OFPFW_DL_DST)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001773 # Create up the flows in an array
1774 for toggle in range(2):
1775 for f_idx in range(flow_count):
1776 pkt = simple_tcp_packet(tcp_sport=f_idx)
1777 msg = message.flow_mod()
Ed Swierk99a74de2012-08-22 06:40:54 -07001778 match = packet_to_flow_match(self, pkt)
Shudong Zhou031373c2012-07-19 17:37:42 -07001779 match.in_port = of_ports[2]
Dan Talayco50be7672012-04-05 11:38:08 -07001780 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001781 msg.match = match
1782 msg.buffer_id = 0xffffffff
Dan Talaycof7c41312012-07-23 12:53:19 -07001783 msg.command = ofp.OFPFC_ADD
Dan Talaycofa6454f2012-04-05 10:04:13 -07001784 msg.actions.add(acts[toggle])
1785 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001786
1787 # Show two sample flows
Rich Lane9a003812012-10-04 17:17:59 -07001788 logging.debug(flows[0][0].show())
1789 logging.debug(flows[1][0].show())
Dan Talayco50be7672012-04-05 11:38:08 -07001790
Dan Talaycofa6454f2012-04-05 10:04:13 -07001791 # Install the first set of flows
1792 for f_idx in range(flow_count):
Rich Lane5c3151c2013-01-03 17:15:41 -08001793 self.controller.message_send(flows[0][f_idx])
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001794 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycofa6454f2012-04-05 10:04:13 -07001795
Rich Lane9a003812012-10-04 17:17:59 -07001796 logging.info("Installed %d flows" % flow_count)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001797
1798 # Repeatedly modify all the flows back and forth
1799 updates = 0
1800 # Report status about 5 times
1801 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001802 start = time.time()
1803 for iter_idx in range(iter_count):
1804 if not iter_idx % mod_val:
Rich Lane9a003812012-10-04 17:17:59 -07001805 logging.info("Flow Toggle: iter %d of %d. " %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001806 (iter_idx, iter_count) +
1807 "%d updates in %d secs" %
1808 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001809 for toggle in range(2):
1810 t_idx = 1 - toggle
1811 for f_idx in range(flow_count):
Rich Lane5c3151c2013-01-03 17:15:41 -08001812 self.controller.message_send(flows[t_idx][f_idx])
Dan Talaycofa6454f2012-04-05 10:04:13 -07001813 updates += 1
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001814 self.assertEqual(do_barrier(self.controller), 0,
1815 "Barrier failed")
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001816
1817 end = time.time()
1818 divisor = end - start or (end - start + 1)
Rich Lane9a003812012-10-04 17:17:59 -07001819 logging.info("Flow toggle: %d iterations" % iter_count)
1820 logging.info(" %d flow mods in %d secs, %d mods/sec" %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001821 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001822
1823
Dan Talayco8a64e332012-03-28 14:53:20 -07001824# You can pick and choose these by commenting tests in or out
1825iter_classes = [
1826 basic.PacketIn,
1827 basic.PacketOut,
1828 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001829 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001830 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001831 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001832 AllWildcardMatch,
1833 AllWildcardMatchTagged,
1834 SingleWildcardMatch,
1835 SingleWildcardMatchTagged,
1836 ExactMatch,
1837 ExactMatchTagged,
1838 SingleWildcardMatch,
1839 ModifyL2Src,
1840 ModifyL2Dst,
1841 ModifyL2SrcMC,
1842 ModifyL2DstMC,
1843 ModifyL2SrcDstMC
1844 ]
1845
1846class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001847 """
1848 Iterate over a bunch of test cases
1849
1850 The cases come from the list above
1851 """
1852
Rich Laned1d9c282012-10-04 22:07:10 -07001853 priority = -1
1854
Dan Talayco8a64e332012-03-28 14:53:20 -07001855 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001856 count = test_param_get('iter_count', default=10)
Dan Talayco8a64e332012-03-28 14:53:20 -07001857 tests_done = 0
Rich Lane9a003812012-10-04 17:17:59 -07001858 logging.info("Running iteration test " + str(count) + " times")
Dan Talayco8a64e332012-03-28 14:53:20 -07001859 start = time.time()
1860 last = start
1861 for idx in range(count):
Rich Lane9a003812012-10-04 17:17:59 -07001862 logging.info("Iteration " + str(idx + 1))
Dan Talayco8a64e332012-03-28 14:53:20 -07001863 for cls in iter_classes:
1864 test = cls()
1865 test.inheritSetup(self)
1866 test.runTest()
1867 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001868 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001869 if time.time() - last > 60:
1870 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001871 logging.info(
Dan Talaycofa6454f2012-04-05 10:04:13 -07001872 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1873 (idx, count, tests_done, last - start) +
1874 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001875 stats = all_stats_get(self)
1876 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001877 logging.info("\nIterCases ran %d tests in %d seconds." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001878 (tests_done, last - start))
Rich Lane9a003812012-10-04 17:17:59 -07001879 logging.info(" flows: %d. packets: %d. bytes: %d" %
Dan Talayco8a64e332012-03-28 14:53:20 -07001880 (stats["flows"], stats["packets"], stats["bytes"]))
Rich Lane9a003812012-10-04 17:17:59 -07001881 logging.info(" active: %d. lookups: %d. matched %d." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001882 (stats["active"], stats["lookups"], stats["matched"]))
1883
Dan Talayco4b2bee62010-07-20 14:10:05 -07001884#@todo Need to implement tagged versions of the above tests
1885#
1886#@todo Implement a test case that strips tag 2, adds tag 3
1887# and modifies tag 4 to tag 5. Then verify (in addition) that
1888# tag 6 does not get modified.
1889
1890class MixedVLAN(BaseMatchCase):
1891 """
1892 Test mixture of VLAN tag actions
1893
1894 Strip tag 2 on port 1, send to port 2
1895 Add tag 3 on port 1, send to port 2
1896 Modify tag 4 to 5 on port 1, send to port 2
1897 All other traffic from port 1, send to port 3
1898 All traffic from port 2 sent to port 4
1899 Use exact matches with different packets for all mods
1900 Verify the following: (port, vid)
1901 (port 1, vid 2) => VLAN tag stripped, out port 2
1902 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1903 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1904 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1905 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1906 (port 2, no tag) => untagged packet out port 4
1907 (port 2, vid 2-6) => unmodified packet out port 4
1908
1909 Variation: Might try sending VID 5 to port 3 and check.
1910 If only VID 5 distinguishes pkt, this will fail on some platforms
1911 """
1912
Rich Laned1d9c282012-10-04 22:07:10 -07001913 priority = -1
Rich Lane8d6ab272012-09-23 18:06:20 -07001914
Rich Laneb90a1c42012-10-05 09:16:05 -07001915class MatchEach(base_tests.SimpleDataPlane):
Rich Lane8d6ab272012-09-23 18:06:20 -07001916 """
1917 Check that each match field is actually matched on.
1918 Installs two flows that differ in one field. The flow that should not
1919 match has a higher priority, so if that field is ignored during matching
1920 the packet will be sent out the wrong port.
1921
1922 TODO test UDP, ARP, ICMP, etc.
1923 """
1924 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001925 of_ports = config["port_map"].keys()
Rich Lane8d6ab272012-09-23 18:06:20 -07001926 of_ports.sort()
1927 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1928
Rich Lane9a003812012-10-04 17:17:59 -07001929 delete_all_flows(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001930
Ed Swierk7040a8d2012-12-11 16:30:13 -08001931 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=2)
Rich Lane8d6ab272012-09-23 18:06:20 -07001932 ingress_port = of_ports[0]
1933 egress_port = of_ports[1]
1934
1935 def testField(field, mask):
Rich Lane9a003812012-10-04 17:17:59 -07001936 logging.info("Testing field %s" % field)
Rich Lane8d6ab272012-09-23 18:06:20 -07001937
1938 def addFlow(matching, priority, output_port):
1939 match = packet_to_flow_match(self, pkt)
1940 self.assertTrue(match is not None, "Could not generate flow match from pkt")
1941 match.wildcards &= ~ofp.OFPFW_IN_PORT
1942 match.in_port = ingress_port
1943 if not matching:
1944 # Make sure flow doesn't match
1945 orig = getattr(match, field)
1946 if isinstance(orig, list):
1947 new = map(lambda a: ~a[0] & a[1], zip(orig, mask))
1948 else:
1949 new = ~orig & mask
1950 setattr(match, field, new)
1951 request = message.flow_mod()
1952 request.match = match
1953 request.buffer_id = 0xffffffff
1954 request.priority = priority
1955 act = action.action_output()
1956 act.port = output_port
Rich Lanee30455b2013-01-03 16:24:44 -08001957 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -07001958 logging.info("Inserting flow")
Rich Lane8d6ab272012-09-23 18:06:20 -07001959 self.controller.message_send(request)
1960
1961 # This flow should match.
1962 addFlow(matching=True, priority=0, output_port=egress_port)
1963 # This flow should not match, but it has a higher priority.
1964 addFlow(matching=False, priority=1, output_port=ofp.OFPP_IN_PORT)
1965
1966 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
1967
Rich Lane9a003812012-10-04 17:17:59 -07001968 logging.info("Sending packet to dp port " + str(ingress_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001969 self.dataplane.send(ingress_port, str(pkt))
1970
1971 exp_pkt_arg = None
1972 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -07001973 if config["relax"]:
Rich Lane8d6ab272012-09-23 18:06:20 -07001974 exp_pkt_arg = pkt
1975 exp_port = egress_port
1976
1977 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
1978 exp_pkt=exp_pkt_arg)
1979 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -07001980 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001981 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
1982 self.assertEqual(str(pkt), str(rcv_pkt), 'Response packet does not match send packet')
1983
Ed Swierkb603b192012-12-12 15:38:49 -08001984 wildcards = required_wildcards(self)
Rich Lane8d6ab272012-09-23 18:06:20 -07001985 # TODO in_port
Ed Swierkb603b192012-12-12 15:38:49 -08001986 if not (wildcards & ofp.OFPFW_DL_SRC):
1987 testField("dl_src", [0xff]*6)
1988 if not (wildcards & ofp.OFPFW_DL_DST):
1989 testField("dl_dst", [0xff]*6)
1990 if not (wildcards & ofp.OFPFW_DL_TYPE):
1991 testField("dl_type", 0xffff)
1992 if not (wildcards & ofp.OFPFW_DL_VLAN):
1993 testField("dl_vlan", 0xfff)
Rich Lane8d6ab272012-09-23 18:06:20 -07001994 # TODO dl_vlan_pcp
Ed Swierkb603b192012-12-12 15:38:49 -08001995 if not (wildcards & ofp.OFPFW_NW_SRC_ALL):
1996 testField("nw_src", 0xffffffff)
1997 if not (wildcards & ofp.OFPFW_NW_DST_ALL):
1998 testField("nw_dst", 0xffffffff)
1999 if not (wildcards & ofp.OFPFW_NW_TOS):
2000 testField("nw_tos", 0x3f)
2001 if not (wildcards & ofp.OFPFW_NW_PROTO):
2002 testField("nw_proto", 0xff)
2003 if not (wildcards & ofp.OFPFW_TP_SRC):
2004 testField("tp_src", 0xffff)
2005 if not (wildcards & ofp.OFPFW_TP_DST):
2006 testField("tp_dst", 0xffff)
Rich Lane8d6ab272012-09-23 18:06:20 -07002007
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002008class DirectBadPacketBase(base_tests.SimpleDataPlane):
2009 """
2010 Base class for sending single packets with single flow table entries.
2011 Used to verify matching of unusual packets and parsing/matching of
2012 corrupted packets.
2013
2014 The idea is to generate packets that may either be totally malformed or
2015 malformed just enough to trick the flow matcher into making mistakes.
2016
2017 Generate a 'bad' packet
2018 Generate and install a matching flow
2019 Add action to direct the packet to an egress port
2020 Send the packet to ingress dataplane port
2021 Verify the packet is received at the egress port only
2022 """
2023
2024 RESULT_MATCH = "MATCH"
2025 RESULT_NOMATCH = "NO MATCH"
2026 RESULT_ANY = "ANY MATCH"
2027
2028 def runTest(self):
2029 pass
2030 # TODO:
2031 # - ICMP?
2032 # - VLAN?
2033 # - action
2034
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002035 def createMatch(self, **kwargs):
2036 match = ofp.ofp_match()
2037 match.wildcards = ofp.OFPFW_ALL
2038 fields = {
2039 'dl_dst': ofp.OFPFW_DL_DST,
2040 'dl_src': ofp.OFPFW_DL_SRC,
2041 'dl_type': ofp.OFPFW_DL_TYPE,
2042 'dl_vlan': ofp.OFPFW_DL_VLAN,
2043 'nw_src': ofp.OFPFW_NW_SRC_MASK,
2044 'nw_dst': ofp.OFPFW_NW_DST_MASK,
2045 'nw_tos': ofp.OFPFW_NW_TOS,
2046 'nw_proto': ofp.OFPFW_NW_PROTO,
2047 'tp_src': ofp.OFPFW_TP_SRC,
2048 'tp_dst': ofp.OFPFW_TP_DST,
2049 }
2050 for key in kwargs:
2051 setattr(match, key, kwargs[key])
2052 match.wildcards &= ~fields[key]
2053 return match
2054
2055 def testPktsAgainstFlow(self, pkts, acts, match):
2056 if type(acts) != list:
2057 acts = [acts]
2058 for info in pkts:
2059 title, pkt, expected_result = info
2060 self.testPktAgainstFlow(title, pkt, acts, match, expected_result)
2061
2062 def testPktAgainstFlow(self, title, pkt, acts, match, expected_result):
2063 of_ports = config["port_map"].keys()
2064 of_ports.sort()
2065 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
2066
2067 rv = delete_all_flows(self.controller)
2068 self.assertEqual(rv, 0, "Failed to delete all flows")
2069
2070 ingress_port = of_ports[0]
2071 egress_port = of_ports[1]
2072
2073 logging.info("Testing packet '%s', expect result %s" %
2074 (title, expected_result))
2075 logging.info("Ingress %s to egress %s" %
2076 (str(ingress_port), str(egress_port)))
2077 logging.info("Packet:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002078 logging.info(inspect_packet(pkt))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002079
2080 match.in_port = ingress_port
2081
2082 request = message.flow_mod()
2083 request.match = match
Rich Lane44cf12d2012-10-15 11:10:45 -07002084 request.priority = 1
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002085
2086 request.buffer_id = 0xffffffff
2087 for act in acts:
2088 act.port = egress_port
Rich Lanee30455b2013-01-03 16:24:44 -08002089 request.actions.add(act)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002090
2091 logging.info("Inserting flow")
Rich Lane5c3151c2013-01-03 17:15:41 -08002092 self.controller.message_send(request)
Rich Lane44cf12d2012-10-15 11:10:45 -07002093
2094 # This flow speeds up negative tests
2095 logging.info("Inserting catch-all flow")
2096 request2 = message.flow_mod()
2097 request2.match = self.createMatch()
2098 request2.priority = 0
2099 act = action.action_output()
2100 act.port = ofp.OFPP_IN_PORT
2101 request2.actions.add(act)
Rich Lane5c3151c2013-01-03 17:15:41 -08002102 self.controller.message_send(request2)
Rich Lane44cf12d2012-10-15 11:10:45 -07002103
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002104 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
2105
2106 logging.info("Sending packet to dp port " +
2107 str(ingress_port))
2108 self.dataplane.send(ingress_port, str(pkt))
2109
2110 exp_pkt_arg = None
2111 exp_port = None
2112 if config["relax"]:
2113 exp_pkt_arg = pkt
2114 exp_port = egress_port
2115
Rich Lane44cf12d2012-10-15 11:10:45 -07002116 if expected_result == self.RESULT_MATCH:
2117 timeout = -1 # default timeout
2118 else:
2119 timeout = 1 # short timeout for negative tests
2120
2121 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(exp_pkt=exp_pkt_arg,
2122 timeout=timeout)
2123 if rcv_port == ingress_port:
2124 logging.debug("Packet matched catch-all flow")
2125 rcv_pkt = None
2126
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002127 if expected_result == self.RESULT_MATCH:
2128 self.assertTrue(rcv_pkt is not None,
2129 "Did not receive packet, expected a match")
2130 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
2131 str(rcv_port))
2132 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
2133 str_pkt = str(pkt)
2134 str_rcv_pkt = str(rcv_pkt)
2135 str_rcv_pkt = str_rcv_pkt[0:len(str_pkt)]
2136 if str_pkt != str_rcv_pkt:
2137 logging.error("Response packet does not match send packet")
2138 logging.info("Response:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002139 logging.info(inspect_packet(scapy.Ether(rcv_pkt)))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002140 self.assertEqual(str_pkt, str_rcv_pkt,
2141 'Response packet does not match send packet')
2142 elif expected_result == self.RESULT_NOMATCH:
2143 self.assertTrue(rcv_pkt is None, "Received packet, expected drop")
2144 else:
2145 logging.debug("Match or drop accepted. Result = %s" %
2146 ("match" if rcv_pkt is not None else "drop"))
2147
2148
2149class DirectBadIpTcpPacketsBase(DirectBadPacketBase):
2150 """
2151 Base class for TCP and UDP parsing/matching verification under corruptions
2152 """
2153 def runTest(self):
2154 pass
2155
2156 def runTestWithProto(self, protoName = 'TCP'):
2157 dl_dst='00:01:02:03:04:05'
2158 dl_src='00:06:07:08:09:0a'
2159 ip_src='192.168.0.1'
2160 ip_dst='192.168.0.2'
2161 ip_tos=0
2162 tcp_sport=1234
2163 tcp_dport=80
2164
2165 # Generate a proper packet for constructing a match
2166 tp = None
2167 if protoName == 'TCP':
2168 tp = scapy.TCP
2169 proto = 6
2170 elif protoName == 'UDP':
2171 tp = scapy.UDP
2172 proto = 17
2173 else:
2174 raise Exception("Passed in unknown proto name")
2175
2176 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
2177 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2178 tp(sport=tcp_sport, dport=tcp_dport)
2179 match = packet_to_flow_match(self, match_pkt)
2180 self.assertTrue(match is not None,
2181 "Could not generate flow match from pkt")
2182 match.wildcards &= ~ofp.OFPFW_IN_PORT
2183
2184 def testPacket(title, pkt, result):
2185 act = action.action_output()
2186 pkts = [
2187 [title, pkt, result]
2188 ]
2189 self.testPktsAgainstFlow(pkts, act, match)
2190
2191 # Try incomplete IP headers
2192 testPacket("Incomplete IP header (1 bytes)",
2193 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2194 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:1],
2195 self.RESULT_NOMATCH,
2196 )
2197 testPacket("Incomplete IP header (2 bytes)",
2198 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2199 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:2],
2200 self.RESULT_NOMATCH,
2201 )
2202 testPacket("Incomplete IP header (3 bytes)",
2203 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2204 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:3],
2205 self.RESULT_NOMATCH,
2206 )
2207 testPacket("Incomplete IP header (12 bytes)",
2208 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2209 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:12],
2210 self.RESULT_NOMATCH,
2211 )
2212 testPacket("Incomplete IP header (16 bytes)",
2213 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2214 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:16],
2215 self.RESULT_NOMATCH,
2216 )
2217 testPacket("Incomplete IP header (19 bytes)",
2218 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2219 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:19],
2220 self.RESULT_NOMATCH,
2221 )
2222
2223 # Try variations where the TCP header is missing or incomplete. As we
2224 # saw bugs before where buffers were reused and lengths weren't honored,
2225 # we initiatlize once with a non-matching full packet and once with a
2226 # matching full packet.
2227 testPacket("Non-Matching TCP packet, warming buffer",
2228 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2229 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2230 tp(sport=tcp_sport, dport=tcp_dport + 1),
2231 self.RESULT_NOMATCH,
2232 )
2233 testPacket("Missing TCP header, buffer warmed with non-match",
2234 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2235 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2236 self.RESULT_NOMATCH,
2237 )
2238 testPacket("Matching TCP packet, warming buffer",
2239 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2240 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2241 tp(sport=tcp_sport, dport=tcp_dport),
2242 self.RESULT_MATCH,
2243 )
2244 testPacket("Missing TCP header, buffer warmed with match",
2245 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2246 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2247 self.RESULT_NOMATCH,
2248 )
2249 testPacket("Truncated TCP header: 2 bytes",
2250 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2251 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2252 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:2]),
2253 self.RESULT_NOMATCH,
2254 )
2255
2256 # Play with IP header length values that put the start of TCP either
2257 # inside the generated TCP header or beyond. In some cases it may even
2258 # be beyond the packet boundary. Also play with IP options and more
2259 # importantly IP total length corruptions.
2260 testPacket("TCP packet, corrupt ihl (0x6)",
2261 simple_tcp_packet(ip_ihl=6),
2262 self.RESULT_NOMATCH,
2263 )
2264 testPacket("TCP packet, corrupt ihl (0xf)",
2265 simple_tcp_packet(ip_ihl=0xf), # ihl = 15 * 4 = 60
2266 self.RESULT_NOMATCH,
2267 )
2268 testPacket("TCP packet, corrupt ihl and total length",
2269 simple_tcp_packet(ip_ihl=0xf, pktlen=56), # ihl = 15 * 4 = 60,
2270 self.RESULT_NOMATCH,
2271 )
2272 testPacket("Corrupt IPoption: First 4 bytes of matching TCP header",
2273 simple_tcp_packet(
2274 ip_options=scapy.IPOption('\x04\xd2\x00\x50'),
2275 tcp_dport=2, tcp_sport=2
2276 ),
2277 self.RESULT_NOMATCH,
2278 )
2279 testPacket("Missing TCP header, corrupt ihl",
2280 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2281 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto),
2282 self.RESULT_NOMATCH,
2283 )
2284 testPacket("Missing TCP header, corrupt total length",
2285 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2286 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, len= 100),
2287 self.RESULT_NOMATCH,
2288 )
2289 testPacket("Missing TCP header, corrupt ihl and total length",
2290 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2291 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto, len=43),
2292 self.RESULT_NOMATCH,
2293 )
2294 testPacket("Incomplete IP header (12 bytes), corrupt ihl and total length",
2295 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2296 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:12],
2297 self.RESULT_NOMATCH,
2298 )
2299 testPacket("Incomplete IP header (16 bytes), corrupt ihl and total length",
2300 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2301 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:16],
2302 self.RESULT_NOMATCH,
2303 )
2304
2305 # Try an incomplete TCP header that has enough bytes to carry source and
2306 # destination ports. As that is all we care about during matching, some
2307 # implementations may match and some may drop the packet
2308 testPacket("Incomplete TCP header: src/dst port present",
2309 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2310 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2311 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:4]),
2312 self.RESULT_ANY,
2313 )
2314
2315 for i in range(1):
2316 for length in range(40 / 4): # IPv4 options are a maximum of 40 in length
2317 bytes = "".join([("%c" % random.randint(0, 255)) for x in range(length * 4)])
2318 eth = scapy.Ether(dst=dl_dst, src=dl_src)
2319 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2320 tcp = tp(sport=tcp_sport, dport=tcp_dport+1)
2321 pkt = eth / ip
2322 pkt = pkt / bytes
2323 pkt = pkt / str(tcp)
2324 testPacket("Random IP options len = %d - TP match must fail" % length * 4,
2325 pkt,
2326 self.RESULT_NOMATCH
2327 )
2328
2329 eth = scapy.Ether(dst=dl_dst, src=dl_src)
2330 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2331 tcp = tp(sport=tcp_sport, dport=tcp_dport)
2332 pkt = eth / ip
2333 pkt = pkt / bytes
2334 pkt = pkt / str(tcp)
2335
2336 testPacket("Random IP options len = %d - May match",
2337 pkt,
2338 self.RESULT_ANY
2339 )
2340
2341
2342class DirectBadIpTcpPackets(DirectBadIpTcpPacketsBase):
2343 """
2344 Verify IP/TCP parsing and matching. Focus on packet corruptions
2345 """
2346 def runTest(self):
2347 self.runTestWithProto(protoName = 'TCP')
2348
2349class DirectBadIpUdpPackets(DirectBadIpTcpPacketsBase):
2350 """
2351 Verify IP/UDP parsing and matching. Focus on packet corruptions
2352 """
2353 def runTest(self):
2354 self.runTestWithProto(protoName = 'UDP')
2355
2356class DirectBadLlcPackets(DirectBadPacketBase):
2357 """
2358 Verify LLC/SNAP parsing and matching. Focus on packet corruptions
2359 """
2360 def runTest(self):
2361 dl_dst='00:01:02:03:04:05'
2362 dl_src='00:06:07:08:09:0a'
2363 ip_src='192.168.0.1'
2364 ip_dst='192.168.0.2'
2365 ip_tos=0
2366 tcp_sport=1234
2367 tcp_dport=80
2368
2369 IS_SNAP_IP = 1
2370 IS_SNAP_IP_CORRUPT = 2
2371 IS_NOT_SNAP_IP = 3
2372
2373 def testPacketTcpMatch(title, llc):
2374 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
2375 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2376 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
2377 match = packet_to_flow_match(self, match_pkt)
2378 self.assertTrue(match is not None,
2379 "Could not generate flow match from pkt")
2380 match.wildcards &= ~ofp.OFPFW_IN_PORT
2381 act = action.action_output()
2382
2383 self.testPktsAgainstFlow(
2384 [[
2385 "TCP match - LLC frame correct length - %s" % title,
2386 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2387 self.RESULT_ANY,
2388 ]],
2389 act, match
2390 )
2391
2392 # Corrupt length field
2393 ethLen = random.randint(0, 1535)
2394 self.testPktsAgainstFlow(
2395 [[
2396 "TCP match - LLC frame corrupted length - %s" % title,
2397 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
2398 self.RESULT_ANY,
2399 ]],
2400 act, match
2401 )
2402
2403 def testPacketEthSrcDstMatch(title, llc):
2404 # Matching based on Ethernet source and destination
2405 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)
2406 match = packet_to_flow_match(self, match_pkt)
2407 self.assertTrue(match is not None,
2408 "Could not generate flow match from pkt")
2409 match.wildcards &= ~ofp.OFPFW_IN_PORT
2410 match.wildcards |= ofp.OFPFW_DL_TYPE
2411 self.testPktsAgainstFlow(
2412 [[
2413 "Eth addr match - LLC frame correct length- %s" % title,
2414 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2415 self.RESULT_MATCH,
2416 ]],
2417 action.action_output(), match
2418 )
2419
2420 # Corrupt length field
2421 ethLen = random.randint(0, 1535)
2422 self.testPktsAgainstFlow(
2423 [[
2424 "Eth addr match - LLC frame corrupted length- %s" % title,
2425 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
2426 self.RESULT_ANY,
2427 ]],
2428 action.action_output(), match
2429 )
2430
2431 def testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip):
2432 # Matching based on Ethernet source, destination and type
2433 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src, type=0x800)
2434 match = packet_to_flow_match(self, match_pkt)
2435 self.assertTrue(match is not None,
2436 "Could not generate flow match from pkt")
2437 match.wildcards &= ~ofp.OFPFW_IN_PORT
2438 if is_snap_ip == IS_SNAP_IP:
2439 is_match = self.RESULT_MATCH
2440 elif is_snap_ip == IS_SNAP_IP_CORRUPT:
2441 is_match = self.RESULT_ANY
2442 else:
2443 is_match = self.RESULT_NOMATCH
2444 self.testPktsAgainstFlow(
2445 [[
2446 "Eth addr+type match - LLC frame correct length - %s" % title,
2447 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2448 is_match,
2449 ]],
2450 action.action_output(), match
2451 )
2452
2453 # Corrupt length field
2454 ethLen = random.randint(0, 1535)
2455 self.testPktsAgainstFlow(
2456 [[
2457 "Eth addr+type match - LLC frame corrupted length - %s" % title,
2458 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
Christian Dickmanne9b6d252012-10-08 22:56:50 -07002459 self.RESULT_ANY,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002460 ]],
2461 action.action_output(), match
2462 )
2463
2464 def testPacket(title, llc, is_snap_ip):
2465 testPacketTcpMatch(title, llc)
2466 testPacketEthSrcDstMatch(title, llc)
2467 testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip)
2468
2469 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002470 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002471 IS_NOT_SNAP_IP,
2472 )
2473 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002474 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002475 IS_NOT_SNAP_IP,
2476 )
2477 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002478 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002479 IS_NOT_SNAP_IP,
2480 )
2481 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002482 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002483 IS_NOT_SNAP_IP,
2484 )
2485 testPacket("LLC - SNAP - Small bogus payload",
2486 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2487 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2488 IS_SNAP_IP_CORRUPT,
2489 )
2490 testPacket("LLC - SNAP - Max -1 bogus payload",
2491 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2492 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2493 IS_NOT_SNAP_IP,
2494 )
2495 testPacket("LLC - SNAP - Max bogus payload",
2496 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2497 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2498 IS_NOT_SNAP_IP,
2499 )
2500 testPacket("LLC - SNAP - IP - TCP",
2501 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2502 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2503 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2504 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2505 IS_SNAP_IP,
2506 )
2507
2508
2509class DirectLlcPackets(DirectBadPacketBase):
2510 """
2511 Verify LLC/SNAP parsing (valid and corrupted packets) and matching
2512 """
2513 def runTest(self):
2514 dl_dst='00:01:02:03:04:05'
2515 dl_src='00:06:07:08:09:0a'
2516 ip_src='192.168.0.1'
2517 ip_dst='192.168.0.2'
2518 ip_tos=0
2519 tcp_sport=1234
2520 tcp_dport=80
2521
2522 # Test ethertype in face of LLC/SNAP and OFP_DL_TYPE_NOT_ETH_TYPE
2523 IS_SNAP_NOT_IP = 1
2524 IS_SNAP_AND_IP = 2
2525 IS_NOT_SNAP = 3
2526
2527 def testPacketEthTypeIP(title, llc, is_snap):
2528 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src, type=0x800)
2529 match = packet_to_flow_match(self, match_pkt)
2530 self.assertTrue(match is not None,
2531 "Could not generate flow match from pkt")
2532 match.wildcards &= ~ofp.OFPFW_IN_PORT
2533 pkts = []
2534 if is_snap == IS_NOT_SNAP or is_snap == IS_SNAP_NOT_IP:
2535 result = self.RESULT_NOMATCH
2536 else:
2537 result = self.RESULT_MATCH
2538 pkts.append([
2539 "Ether type 0x800 match - %s" % title,
2540 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2541 result,
2542 ])
2543 act = action.action_output()
2544 self.testPktsAgainstFlow(pkts, act, match)
2545
2546 def testPacketEthTypeNotEth(title, llc, is_snap):
2547 match_pkt = scapy.Ether(dst = dl_dst, src = dl_src,
2548 type = ofp.OFP_DL_TYPE_NOT_ETH_TYPE)
2549 match = packet_to_flow_match(self, match_pkt)
2550 self.assertTrue(match is not None,
2551 "Could not generate flow match from pkt")
2552 match.wildcards &= ~ofp.OFPFW_IN_PORT
2553 pkts = []
2554 if is_snap == IS_NOT_SNAP:
2555 result = self.RESULT_MATCH
2556 else:
2557 result = self.RESULT_NOMATCH
2558 pkts.append([
2559 "Ether type OFP_DL_TYPE_NOT_ETH_TYPE match - %s" % title,
2560 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2561 result,
2562 ])
2563 act = action.action_output()
2564 self.testPktsAgainstFlow(pkts, act, match)
2565
2566 def testPacket(title, llc, is_snap):
2567 testPacketEthTypeIP(title, llc, is_snap)
2568 testPacketEthTypeNotEth(title, llc, is_snap)
2569
2570 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002571 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
2572 IS_NOT_SNAP,
2573 )
2574 testPacket("LLC (with information field) - No SNAP - No Payload",
2575 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x12) / "S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002576 IS_NOT_SNAP,
2577 )
2578 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002579 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002580 IS_NOT_SNAP,
2581 )
2582 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002583 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002584 IS_NOT_SNAP,
2585 )
2586 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002587 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002588 IS_NOT_SNAP,
2589 )
2590 testPacket("LLC - SNAP - Non-default OUI",
2591 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2592 scapy.SNAP(OUI=0x000001, code=0x800) / ("S" * 10),
2593 IS_NOT_SNAP,
2594 )
2595 testPacket("LLC - SNAP - Default OUI",
2596 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2597 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2598 IS_SNAP_AND_IP,
2599 )
2600 testPacket("LLC - SNAP - Max -1 bogus payload",
2601 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2602 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2603 IS_SNAP_NOT_IP,
2604 )
2605 testPacket("LLC - SNAP - Max bogus payload",
2606 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2607 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2608 IS_SNAP_NOT_IP,
2609 )
2610 testPacket("LLC - SNAP - IP - TCP",
2611 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2612 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2613 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2614 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2615 IS_SNAP_AND_IP,
2616 )
2617
2618
2619class DirectArpPackets(DirectBadPacketBase):
2620 """
2621 Verify ARP parsing (valid and corrupted packets) and ARP matching
2622 """
2623 def runTest(self):
2624 self.testArpHandling()
2625
2626 def testArpHandling(self):
2627 dl_dst='00:01:02:03:04:05'
2628 dl_src='00:06:07:08:09:0a'
2629 ip_src='192.168.0.1'
2630 ip_dst='192.168.0.2'
2631 ip_src2='192.168.1.1'
2632 ip_dst2='192.168.1.2'
2633 ip_tos=0
2634 tcp_sport=1234
2635 tcp_dport=80
2636
2637 def testPacket(title, arp_match, arp_pkt, result):
2638 pkts = []
2639
2640 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src) / arp_match
2641 match = packet_to_flow_match(self, match_pkt)
2642 self.assertTrue(match is not None,
2643 "Could not generate flow match from pkt")
2644 match.wildcards &= ~ofp.OFPFW_IN_PORT
2645
2646 pkts.append([
2647 title,
2648 scapy.Ether(dst=dl_dst, src=dl_src) / arp_pkt,
2649 result,
2650 ])
2651
2652 act = action.action_output()
2653 self.testPktsAgainstFlow(pkts, act, match)
2654
2655 testPacket("Basic ARP",
2656 scapy.ARP(psrc=ip_src, pdst=ip_dst, op = 1),
2657 scapy.ARP(hwdst = '00:00:00:00:00:00', hwsrc = dl_src,
2658 psrc = ip_src, pdst = ip_dst, hwlen = 6, plen = 4,
2659 ptype = 0x800, hwtype = 1, op = 1),
2660 self.RESULT_MATCH
2661 )
2662 # More stuff:
2663 # - Non matches on any property
2664 # - Corrupted hwlen and plen
2665 # - Other hwtype, ptype
2666 # - Truncated ARP pkt
2667
2668
2669class DirectVlanPackets(DirectBadPacketBase):
2670 """
2671 Verify VLAN parsing (valid and corrupted packets) and ARP matching
2672 """
2673 def runTest(self):
2674 dl_dst='00:01:02:03:04:05'
2675 dl_src='00:06:07:08:09:0a'
2676 ip_src='192.168.0.1'
2677 ip_dst='192.168.0.2'
2678 ip_src2='192.168.1.1'
2679 ip_dst2='192.168.1.2'
2680 ip_tos=0
2681 tcp_sport=1234
2682 tcp_dport=80
2683
2684 def testPacket(title, match, pkt, result):
2685 pkts = []
2686
2687 self.assertTrue(match is not None,
2688 "Could not generate flow match from pkt")
2689 match.wildcards &= ~ofp.OFPFW_IN_PORT
2690
2691 pkts.append([
2692 "%s" % title,
2693 pkt,
2694 result,
2695 ])
2696
2697 act = action.action_output()
2698 self.testPktsAgainstFlow(pkts, act, match)
2699
2700 testPacket("Basic MAC matching - IPv4 payload",
2701 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2702 scapy.Ether(dst=dl_dst, src=dl_src, type=0x800) / scapy.IP(),
2703 self.RESULT_MATCH
2704 )
2705 testPacket("Basic MAC matching - VMware beacon - no payload",
2706 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2707 scapy.Ether(dst=dl_dst, src=dl_src, type=0x8922),
2708 self.RESULT_MATCH
2709 )
2710 testPacket("Basic MAC matching - VMware beacon - with payload",
2711 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2712 scapy.Ether(dst=dl_dst, src=dl_src, type=0x8922)/ ("X" * 1),
2713 self.RESULT_MATCH
2714 )
2715 testPacket("Basic MAC matching - IPv6 payload",
2716 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2717 scapy.Ether(dst=dl_dst, src=dl_src) / scapy.IPv6(),
2718 self.RESULT_MATCH
2719 )
2720 testPacket("Basic MAC matching with VLAN tag present",
2721 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2722 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002723 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002724 scapy.IP(),
2725 self.RESULT_MATCH
2726 )
2727 testPacket("Basic MAC matching with VLAN tag present",
2728 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2729 dl_type=0x800),
2730 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002731 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002732 scapy.IP(),
2733 self.RESULT_MATCH
2734 )
2735 testPacket("Ether matching with VLAN tag present - No type match",
2736 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2737 dl_type=0x801),
2738 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002739 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002740 scapy.IP(),
2741 self.RESULT_NOMATCH
2742 )
2743 testPacket("Ether matching with VLAN tag present - No type match 0x8100",
2744 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2745 dl_type=0x8100),
2746 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002747 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002748 scapy.IP(),
2749 self.RESULT_NOMATCH
2750 )
2751 testPacket("Ether matching with double VLAN tag - Wrong type match",
2752 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2753 dl_type=0x800),
2754 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002755 scapy.Dot1Q(prio=5, vlan=1000)/ \
2756 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002757 scapy.IP(),
2758 self.RESULT_NOMATCH
2759 )
2760 testPacket("Ether matching with double VLAN tag - Type match",
2761 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2762 dl_type=0x8100),
2763 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002764 scapy.Dot1Q(prio=5, vlan=1000)/ \
2765 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002766 scapy.IP(),
2767 self.RESULT_MATCH
2768 )
2769 testPacket("IP matching - VLAN tag",
2770 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2771 dl_type=0x0800,
2772 nw_src=parse_ip(ip_src), nw_dst=parse_ip(ip_dst)),
2773 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002774 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002775 scapy.IP(src=ip_src, dst=ip_dst),
2776 self.RESULT_MATCH
2777 )
2778 # XXX:
2779 # - Matching on VLAN ID and Prio
2780 # - Actions
2781
2782
2783
Dan Talayco9f47f4d2010-06-03 13:54:37 -07002784if __name__ == "__main__":
2785 print "Please run through oft script: ./oft --test_spec=basic"