blob: 5a1bedf41793204bdfb0c91e8be778976f947edc [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")
Dan Talayco5eba8442010-03-10 13:58:43 -0800128 rv = self.controller.message_send(request)
129 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700130 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco5eba8442010-03-10 13:58:43 -0800131
Rich Lane9a003812012-10-04 17:17:59 -0700132 logging.info("Sending packet to dp port " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800133 str(ingress_port))
134 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700135
136 exp_pkt_arg = None
137 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700138 if config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700139 exp_pkt_arg = pkt
140 exp_port = egress_port
141
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700142 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700143 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800144 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700145 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800146 str(rcv_port))
147 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
148 self.assertEqual(str(pkt), str(rcv_pkt),
149 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700150
Rich Laneb90a1c42012-10-05 09:16:05 -0700151class DirectPacketController(base_tests.SimpleDataPlane):
Rich Lane51c23b32012-07-27 16:37:25 -0700152 """
153 Send packet to the controller port
154
155 Generate a packet
156 Generate and install a matching flow
157 Add action to direct the packet to the controller port
158 Send the packet to ingress dataplane port
159 Verify the packet is received at the controller port
160 """
161 def runTest(self):
162 self.handleFlow()
163
164 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700165 of_ports = config["port_map"].keys()
Rich Lane51c23b32012-07-27 16:37:25 -0700166 of_ports.sort()
167 self.assertTrue(len(of_ports) > 0, "Not enough ports for test")
168
169 if (pkttype == 'ICMP'):
170 pkt = simple_icmp_packet()
171 else:
172 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700173 match = packet_to_flow_match(self, pkt)
Rich Lane51c23b32012-07-27 16:37:25 -0700174 match.wildcards &= ~ofp.OFPFW_IN_PORT
175 self.assertTrue(match is not None,
176 "Could not generate flow match from pkt")
177 act = action.action_output()
178
Rich Lane9a003812012-10-04 17:17:59 -0700179 rv = delete_all_flows(self.controller)
Rich Lane51c23b32012-07-27 16:37:25 -0700180 self.assertEqual(rv, 0, "Failed to delete all flows")
181
182 ingress_port = of_ports[0]
183 match.in_port = ingress_port
184
185 request = message.flow_mod()
186 request.match = match
187
188 request.buffer_id = 0xffffffff
189 act.port = ofp.OFPP_CONTROLLER
190 act.max_len = 65535
Rich Lanee30455b2013-01-03 16:24:44 -0800191 request.actions.add(act)
Rich Lane51c23b32012-07-27 16:37:25 -0700192
Rich Lane9a003812012-10-04 17:17:59 -0700193 logging.info("Inserting flow")
Rich Lane51c23b32012-07-27 16:37:25 -0700194 rv = self.controller.message_send(request)
195 self.assertTrue(rv != -1, "Error installing flow mod")
196 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
197
Rich Lane9a003812012-10-04 17:17:59 -0700198 logging.info("Sending packet to dp port " +
Rich Lane51c23b32012-07-27 16:37:25 -0700199 str(ingress_port))
200 self.dataplane.send(ingress_port, str(pkt))
201
202 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
203
204 self.assertTrue(response is not None,
205 'Packet in message not received by controller')
206 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700207 logging.debug("Sent %s" % format_packet(pkt))
208 logging.debug("Resp %s" % format_packet(response.data))
Rich Lane51c23b32012-07-27 16:37:25 -0700209 self.assertTrue(False,
210 'Response packet does not match send packet' +
211 ' for controller port')
212
Howard Pershf97840f2012-04-10 16:30:42 -0700213
Rich Laneb90a1c42012-10-05 09:16:05 -0700214class DirectPacketQueue(base_tests.SimpleDataPlane):
Howard Pershf97840f2012-04-10 16:30:42 -0700215 """
216 Send packet to single queue on single egress port
217
218 Generate a packet
219 Generate and install a matching flow
220 Add action to direct the packet to an egress port and queue
221 Send the packet to ingress dataplane port
222 Verify the packet is received at the egress port only
223 """
224 def runTest(self):
225 self.handleFlow()
226
Howard Persh670b5672012-04-13 09:08:29 -0700227 def portQueuesGet(self, queue_stats, port_num):
228 result = []
229 for qs in queue_stats.stats:
230 if qs.port_no != port_num:
231 continue
232 result.append(qs.queue_id)
233 return result
234
Howard Pershf97840f2012-04-10 16:30:42 -0700235 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700236 of_ports = config["port_map"].keys()
Howard Pershf97840f2012-04-10 16:30:42 -0700237 of_ports.sort()
238 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
239
240 if (pkttype == 'ICMP'):
241 pkt = simple_icmp_packet()
242 else:
243 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700244 match = packet_to_flow_match(self, pkt)
Howard Pershf97840f2012-04-10 16:30:42 -0700245 match.wildcards &= ~ofp.OFPFW_IN_PORT
246 self.assertTrue(match is not None,
247 "Could not generate flow match from pkt")
248
Howard Persh670b5672012-04-13 09:08:29 -0700249 # Get queue stats from switch
250
251 request = message.queue_stats_request()
252 request.port_no = ofp.OFPP_ALL
253 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700254 (queue_stats, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700255 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
256
257 act = action.action_enqueue()
Howard Pershf97840f2012-04-10 16:30:42 -0700258
259 for idx in range(len(of_ports)):
Howard Pershf97840f2012-04-10 16:30:42 -0700260 ingress_port = of_ports[idx]
261 egress_port = of_ports[(idx + 1) % len(of_ports)]
Howard Pershf97840f2012-04-10 16:30:42 -0700262
Howard Persh670b5672012-04-13 09:08:29 -0700263 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700264 logging.info("Ingress " + str(ingress_port)
Howard Persh670b5672012-04-13 09:08:29 -0700265 + " to egress " + str(egress_port)
266 + " queue " + str(egress_queue_id)
267 )
Howard Pershf97840f2012-04-10 16:30:42 -0700268
Rich Lane9a003812012-10-04 17:17:59 -0700269 rv = delete_all_flows(self.controller)
Howard Persh670b5672012-04-13 09:08:29 -0700270 self.assertEqual(rv, 0, "Failed to delete all flows")
Howard Pershf97840f2012-04-10 16:30:42 -0700271
Howard Persh670b5672012-04-13 09:08:29 -0700272 match.in_port = ingress_port
273
274 request = message.flow_mod()
275 request.match = match
Howard Pershf97840f2012-04-10 16:30:42 -0700276
Howard Persh670b5672012-04-13 09:08:29 -0700277 request.buffer_id = 0xffffffff
278 act.port = egress_port
279 act.queue_id = egress_queue_id
Rich Lanee30455b2013-01-03 16:24:44 -0800280 request.actions.add(act)
Howard Pershf97840f2012-04-10 16:30:42 -0700281
Rich Lane9a003812012-10-04 17:17:59 -0700282 logging.info("Inserting flow")
Howard Persh670b5672012-04-13 09:08:29 -0700283 rv = self.controller.message_send(request)
284 self.assertTrue(rv != -1, "Error installing flow mod")
285 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Howard Pershf97840f2012-04-10 16:30:42 -0700286
Howard Persh670b5672012-04-13 09:08:29 -0700287 # Get current stats for selected egress queue
Howard Pershf97840f2012-04-10 16:30:42 -0700288
Howard Persh670b5672012-04-13 09:08:29 -0700289 request = message.queue_stats_request()
290 request.port_no = egress_port
291 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700292 (qs_before, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700293 self.assertNotEqual(qs_before, None, "Queue stats request failed")
294
Rich Lane9a003812012-10-04 17:17:59 -0700295 logging.info("Sending packet to dp port " +
Howard Persh670b5672012-04-13 09:08:29 -0700296 str(ingress_port))
297 self.dataplane.send(ingress_port, str(pkt))
298
299 exp_pkt_arg = None
300 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700301 if config["relax"]:
Howard Persh670b5672012-04-13 09:08:29 -0700302 exp_pkt_arg = pkt
303 exp_port = egress_port
304
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700305 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Howard Persh670b5672012-04-13 09:08:29 -0700306 exp_pkt=exp_pkt_arg)
307 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700308 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Howard Persh670b5672012-04-13 09:08:29 -0700309 str(rcv_port))
310 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
311 self.assertEqual(str(pkt), str(rcv_pkt),
312 'Response packet does not match send packet')
313
Ed Swierkb8a86512012-04-18 18:45:58 -0700314 # FIXME: instead of sleeping, keep requesting queue stats until
315 # the expected queue counter increases or some large timeout is
316 # reached
317 time.sleep(2)
318
Howard Persh670b5672012-04-13 09:08:29 -0700319 # Get current stats for selected egress queue again
320
321 request = message.queue_stats_request()
322 request.port_no = egress_port
323 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700324 (qs_after, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700325 self.assertNotEqual(qs_after, None, "Queue stats request failed")
326
327 # Make sure that tx packet counter for selected egress queue was
328 # incremented
329
Ed Swierk22f59152012-04-17 16:36:47 -0700330 self.assertEqual(qs_after.stats[0].tx_packets, \
331 qs_before.stats[0].tx_packets + 1, \
Howard Persh670b5672012-04-13 09:08:29 -0700332 "Verification of egress queue tx packet count failed"
333 )
334
335
Rich Laneb90a1c42012-10-05 09:16:05 -0700336class DirectPacketControllerQueue(base_tests.SimpleDataPlane):
Ken Chiang899ff8e2012-05-23 18:26:12 -0700337 """
338 Send a packet from each of the openflow ports
339 to each of the queues configured on the controller port.
340 If no queues have been configured, no packets are sent.
Howard Pershf97840f2012-04-10 16:30:42 -0700341
Ken Chiang899ff8e2012-05-23 18:26:12 -0700342 Generate a packet
343 Generate and install a matching flow
344 Add action to direct the packet to one of the controller port queues
345 Send the packet to ingress dataplane port
346 Verify the packet is received on the controller port queue
347 """
348 def runTest(self):
349 self.handleFlow()
350
351 def portQueuesGet(self, queue_stats, port_num):
352 result = []
353 for qs in queue_stats.stats:
354 if qs.port_no != port_num:
355 continue
356 result.append(qs.queue_id)
357 return result
358
359 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700360 of_ports = config["port_map"].keys()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700361 of_ports.sort()
362 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
363
364 if (pkttype == 'ICMP'):
365 pkt = simple_icmp_packet()
366 else:
367 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700368 match = packet_to_flow_match(self, pkt)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700369 match.wildcards &= ~ofp.OFPFW_IN_PORT
370 self.assertTrue(match is not None,
371 "Could not generate flow match from pkt")
372
373 # Get queue stats from switch
374
375 request = message.queue_stats_request()
376 request.port_no = ofp.OFPP_CONTROLLER
377 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700378 (queue_stats, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700379 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
Rich Laneb8c845a2012-12-31 17:23:51 -0800380 if queue_stats.header.type == ofp.OFPT_ERROR:
381 skip_message_emit(self, "Enqueue packet to controller")
382 return
Ken Chiang899ff8e2012-05-23 18:26:12 -0700383
384 act = action.action_enqueue()
385
386 for idx in range(len(of_ports)):
387 ingress_port = of_ports[idx]
388 egress_port = ofp.OFPP_CONTROLLER
389
Rich Lane9a003812012-10-04 17:17:59 -0700390 logging.info("Ingress port " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700391 + ", controller port queues "
392 + str(self.portQueuesGet(queue_stats, egress_port)))
393
394 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700395 logging.info("Ingress " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700396 + " to egress " + str(egress_port)
397 + " queue " + str(egress_queue_id)
398 )
399
Rich Lane9a003812012-10-04 17:17:59 -0700400 rv = delete_all_flows(self.controller)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700401 self.assertEqual(rv, 0, "Failed to delete all flows")
402
403 match.in_port = ingress_port
404
405 request = message.flow_mod()
406 request.match = match
407
408 request.buffer_id = 0xffffffff
409 act.port = egress_port
410 act.queue_id = egress_queue_id
Rich Lanee30455b2013-01-03 16:24:44 -0800411 request.actions.add(act)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700412
Rich Lane9a003812012-10-04 17:17:59 -0700413 logging.info("Inserting flow")
Ken Chiang899ff8e2012-05-23 18:26:12 -0700414 rv = self.controller.message_send(request)
415 self.assertTrue(rv != -1, "Error installing flow mod")
416 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
417
418 # Get current stats for selected egress queue
419
420 request = message.queue_stats_request()
421 request.port_no = egress_port
422 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700423 (qs_before, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700424 self.assertNotEqual(qs_before, None, "Queue stats request failed")
425
Rich Lane9a003812012-10-04 17:17:59 -0700426 logging.info("Sending packet to dp port " +
Ken Chiang899ff8e2012-05-23 18:26:12 -0700427 str(ingress_port))
428 self.dataplane.send(ingress_port, str(pkt))
429
430 exp_pkt_arg = None
431 exp_port = None
432
Rich Lanee5779d32012-10-05 17:56:04 -0700433 count = 0
Ken Chiang899ff8e2012-05-23 18:26:12 -0700434 while True:
Dan Talaycoc689a792012-09-28 14:22:53 -0700435 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700436 if not response: # Timeout
437 break
438 if dataplane.match_exp_pkt(pkt, response.data): # Got match
439 break
Rich Lane477f4812012-10-04 22:49:00 -0700440 if not config["relax"]: # Only one attempt to match
Ken Chiang899ff8e2012-05-23 18:26:12 -0700441 break
442 count += 1
443 if count > 10: # Too many tries
444 break
445
446 self.assertTrue(response is not None,
447 'Packet in message not received by controller')
448 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700449 logging.debug("Sent %s" % format_packet(pkt))
450 logging.debug("Resp %s" % format_packet(response.data))
Ken Chiang899ff8e2012-05-23 18:26:12 -0700451 self.assertTrue(False,
452 'Response packet does not match send packet' +
453 ' for controller port')
454
455 # FIXME: instead of sleeping, keep requesting queue stats until
456 # the expected queue counter increases or some large timeout is
457 # reached
458 time.sleep(2)
459
460 # Get current stats for selected egress queue again
461
462 request = message.queue_stats_request()
463 request.port_no = egress_port
464 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700465 (qs_after, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700466 self.assertNotEqual(qs_after, None, "Queue stats request failed")
467
468 # Make sure that tx packet counter for selected egress queue was
469 # incremented
470
471 self.assertEqual(qs_after.stats[0].tx_packets, \
472 qs_before.stats[0].tx_packets + 1, \
473 "Verification of egress queue tx packet count failed"
474 )
475
Howard Pershf97840f2012-04-10 16:30:42 -0700476
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700477class DirectPacketICMP(DirectPacket):
478 """
479 Send ICMP packet to single egress port
480
481 Generate a ICMP packet
482 Generate and install a matching flow
483 Add action to direct the packet to an egress port
484 Send the packet to ingress dataplane port
485 Verify the packet is received at the egress port only
486 Difference from DirectPacket test is that sent packet is ICMP
487 """
488 def runTest(self):
489 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700490
Rich Laneb90a1c42012-10-05 09:16:05 -0700491class DirectTwoPorts(base_tests.SimpleDataPlane):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700492 """
493 Send packet to two egress ports
494
495 Generate a packet
496 Generate and install a matching flow
497 Add action to direct the packet to two egress ports
498 Send the packet to ingress dataplane port
499 Verify the packet is received at the two egress ports
500 """
501 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700502 of_ports = config["port_map"].keys()
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700503 of_ports.sort()
504 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
505
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700506 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700507 match = packet_to_flow_match(self, pkt)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700508 match.wildcards &= ~ofp.OFPFW_IN_PORT
509 self.assertTrue(match is not None,
510 "Could not generate flow match from pkt")
511 act = action.action_output()
512
513 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700514 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700515 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700516
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700517 ingress_port = of_ports[idx]
518 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
519 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700520 logging.info("Ingress " + str(ingress_port) +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700521 " to egress " + str(egress_port1) + " and " +
522 str(egress_port2))
523
524 match.in_port = ingress_port
525
526 request = message.flow_mod()
527 request.match = match
528 request.buffer_id = 0xffffffff
529 act.port = egress_port1
Rich Lanee30455b2013-01-03 16:24:44 -0800530 request.actions.add(act)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700531 act.port = egress_port2
Rich Lanee30455b2013-01-03 16:24:44 -0800532 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700533 # logging.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700534
Rich Lane9a003812012-10-04 17:17:59 -0700535 logging.info("Inserting flow")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700536 rv = self.controller.message_send(request)
537 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700538 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700539
Rich Lane9a003812012-10-04 17:17:59 -0700540 logging.info("Sending packet to dp port " +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700541 str(ingress_port))
542 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700543 yes_ports = set([egress_port1, egress_port2])
544 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700545
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700546 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Rich Lane2014f9b2012-10-05 15:29:40 -0700547 self)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700548
Rich Laneb90a1c42012-10-05 09:16:05 -0700549class DirectMCNonIngress(base_tests.SimpleDataPlane):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700550 """
551 Multicast to all non-ingress ports
552
553 Generate a packet
554 Generate and install a matching flow
555 Add action to direct the packet to all non-ingress ports
556 Send the packet to ingress dataplane port
557 Verify the packet is received at all non-ingress ports
558
559 Does not use the flood action
560 """
561 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700562 of_ports = config["port_map"].keys()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700563 of_ports.sort()
564 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
565
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700566 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700567 match = packet_to_flow_match(self, pkt)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700568 match.wildcards &= ~ofp.OFPFW_IN_PORT
569 self.assertTrue(match is not None,
570 "Could not generate flow match from pkt")
571 act = action.action_output()
572
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700573 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700574 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700575 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700576
Rich Lane9a003812012-10-04 17:17:59 -0700577 logging.info("Ingress " + str(ingress_port) +
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700578 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700579 match.in_port = ingress_port
580
581 request = message.flow_mod()
582 request.match = match
583 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700584 for egress_port in of_ports:
585 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700586 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700587 act.port = egress_port
Rich Lanee30455b2013-01-03 16:24:44 -0800588 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700589 logging.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700590
Rich Lane9a003812012-10-04 17:17:59 -0700591 logging.info("Inserting flow")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700592 rv = self.controller.message_send(request)
593 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700594 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700595
Rich Lane9a003812012-10-04 17:17:59 -0700596 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700597 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700598 yes_ports = set(of_ports).difference([ingress_port])
599 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700600 self)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700601
Dan Talayco32fa6542010-05-11 15:54:08 -0700602
Rich Laneb90a1c42012-10-05 09:16:05 -0700603class DirectMC(base_tests.SimpleDataPlane):
Dan Talayco32fa6542010-05-11 15:54:08 -0700604 """
605 Multicast to all ports including ingress
606
607 Generate a packet
608 Generate and install a matching flow
609 Add action to direct the packet to all non-ingress ports
610 Send the packet to ingress dataplane port
611 Verify the packet is received at all ports
612
613 Does not use the flood action
614 """
615 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700616 of_ports = config["port_map"].keys()
Dan Talayco32fa6542010-05-11 15:54:08 -0700617 of_ports.sort()
618 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
619
Dan Talayco32fa6542010-05-11 15:54:08 -0700620 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700621 match = packet_to_flow_match(self, pkt)
Dan Talayco32fa6542010-05-11 15:54:08 -0700622 match.wildcards &= ~ofp.OFPFW_IN_PORT
623 self.assertTrue(match is not None,
624 "Could not generate flow match from pkt")
625 act = action.action_output()
626
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700627 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700628 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700629 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700630
Rich Lane9a003812012-10-04 17:17:59 -0700631 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700632 match.in_port = ingress_port
633
634 request = message.flow_mod()
635 request.match = match
636 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700637 for egress_port in of_ports:
638 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700639 act.port = ofp.OFPP_IN_PORT
640 else:
641 act.port = egress_port
Rich Lanee30455b2013-01-03 16:24:44 -0800642 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700643 # logging.info(request.show())
Dan Talayco2e77a842010-05-12 15:39:46 -0700644
Rich Lane9a003812012-10-04 17:17:59 -0700645 logging.info("Inserting flow")
Dan Talayco2e77a842010-05-12 15:39:46 -0700646 rv = self.controller.message_send(request)
647 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700648 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2e77a842010-05-12 15:39:46 -0700649
Rich Lane9a003812012-10-04 17:17:59 -0700650 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700651 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700652 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco2e77a842010-05-12 15:39:46 -0700653
Rich Laneb90a1c42012-10-05 09:16:05 -0700654class Flood(base_tests.SimpleDataPlane):
Dan Talayco2e77a842010-05-12 15:39:46 -0700655 """
656 Flood to all ports except ingress
657
658 Generate a packet
659 Generate and install a matching flow
660 Add action to flood the packet
661 Send the packet to ingress dataplane port
662 Verify the packet is received at all other ports
663 """
664 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700665 of_ports = config["port_map"].keys()
Dan Talayco2e77a842010-05-12 15:39:46 -0700666 of_ports.sort()
667 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
668
669 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700670 match = packet_to_flow_match(self, pkt)
Dan Talayco2e77a842010-05-12 15:39:46 -0700671 match.wildcards &= ~ofp.OFPFW_IN_PORT
672 self.assertTrue(match is not None,
673 "Could not generate flow match from pkt")
674 act = action.action_output()
675
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700676 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700677 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700678 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700679
Rich Lane9a003812012-10-04 17:17:59 -0700680 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700681 match.in_port = ingress_port
682
683 request = message.flow_mod()
684 request.match = match
685 request.buffer_id = 0xffffffff
686 act.port = ofp.OFPP_FLOOD
Rich Lanee30455b2013-01-03 16:24:44 -0800687 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700688 logging.info(request.show())
Dan Talayco32fa6542010-05-11 15:54:08 -0700689
Rich Lane9a003812012-10-04 17:17:59 -0700690 logging.info("Inserting flow")
Dan Talayco32fa6542010-05-11 15:54:08 -0700691 rv = self.controller.message_send(request)
692 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700693 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco32fa6542010-05-11 15:54:08 -0700694
Rich Lane9a003812012-10-04 17:17:59 -0700695 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco32fa6542010-05-11 15:54:08 -0700696 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700697 yes_ports = set(of_ports).difference([ingress_port])
698 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700699 self)
Dan Talayco3be5b062010-05-12 15:46:21 -0700700
Rich Laneb90a1c42012-10-05 09:16:05 -0700701class FloodPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco3be5b062010-05-12 15:46:21 -0700702 """
703 Flood to all ports plus send to ingress port
704
705 Generate a packet
706 Generate and install a matching flow
707 Add action to flood the packet
708 Add action to send to ingress port
709 Send the packet to ingress dataplane port
710 Verify the packet is received at all other ports
711 """
712 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700713 of_ports = config["port_map"].keys()
Dan Talayco3be5b062010-05-12 15:46:21 -0700714 of_ports.sort()
715 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
716
717 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700718 match = packet_to_flow_match(self, pkt)
Dan Talayco3be5b062010-05-12 15:46:21 -0700719 match.wildcards &= ~ofp.OFPFW_IN_PORT
720 self.assertTrue(match is not None,
721 "Could not generate flow match from pkt")
722 act = action.action_output()
723
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700724 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700725 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700726 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700727
Rich Lane9a003812012-10-04 17:17:59 -0700728 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700729 match.in_port = ingress_port
730
731 request = message.flow_mod()
732 request.match = match
733 request.buffer_id = 0xffffffff
734 act.port = ofp.OFPP_FLOOD
Rich Lanee30455b2013-01-03 16:24:44 -0800735 request.actions.add(act)
Dan Talayco4aa13122010-05-12 15:54:44 -0700736 act.port = ofp.OFPP_IN_PORT
Rich Lanee30455b2013-01-03 16:24:44 -0800737 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700738 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700739
Rich Lane9a003812012-10-04 17:17:59 -0700740 logging.info("Inserting flow")
Dan Talayco4aa13122010-05-12 15:54:44 -0700741 rv = self.controller.message_send(request)
742 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700743 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700744
Rich Lane9a003812012-10-04 17:17:59 -0700745 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700746 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700747 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco4aa13122010-05-12 15:54:44 -0700748
Rich Laneb90a1c42012-10-05 09:16:05 -0700749class All(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700750 """
751 Send to OFPP_ALL port
752
753 Generate a packet
754 Generate and install a matching flow
755 Add action to forward to OFPP_ALL
756 Send the packet to ingress dataplane port
757 Verify the packet is received at all other ports
758 """
759 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700760 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700761 of_ports.sort()
762 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
763
764 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700765 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700766 match.wildcards &= ~ofp.OFPFW_IN_PORT
767 self.assertTrue(match is not None,
768 "Could not generate flow match from pkt")
769 act = action.action_output()
770
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700771 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700772 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700773 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700774
Rich Lane9a003812012-10-04 17:17:59 -0700775 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700776 match.in_port = ingress_port
777
778 request = message.flow_mod()
779 request.match = match
780 request.buffer_id = 0xffffffff
781 act.port = ofp.OFPP_ALL
Rich Lanee30455b2013-01-03 16:24:44 -0800782 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700783 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700784
Rich Lane9a003812012-10-04 17:17:59 -0700785 logging.info("Inserting flow")
Dan Talayco4aa13122010-05-12 15:54:44 -0700786 rv = self.controller.message_send(request)
787 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700788 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700789
Rich Lane9a003812012-10-04 17:17:59 -0700790 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700791 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700792 yes_ports = set(of_ports).difference([ingress_port])
793 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700794 self)
Dan Talayco4aa13122010-05-12 15:54:44 -0700795
Rich Laneb90a1c42012-10-05 09:16:05 -0700796class AllPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700797 """
798 Send to OFPP_ALL port and ingress port
799
800 Generate a packet
801 Generate and install a matching flow
802 Add action to forward to OFPP_ALL
803 Add action to forward to ingress port
804 Send the packet to ingress dataplane port
805 Verify the packet is received at all other ports
806 """
807 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700808 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700809 of_ports.sort()
810 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
811
812 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700813 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700814 match.wildcards &= ~ofp.OFPFW_IN_PORT
815 self.assertTrue(match is not None,
816 "Could not generate flow match from pkt")
817 act = action.action_output()
818
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700819 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700820 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700821 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700822
Rich Lane9a003812012-10-04 17:17:59 -0700823 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700824 match.in_port = ingress_port
825
826 request = message.flow_mod()
827 request.match = match
828 request.buffer_id = 0xffffffff
829 act.port = ofp.OFPP_ALL
Rich Lanee30455b2013-01-03 16:24:44 -0800830 request.actions.add(act)
Dan Talayco3be5b062010-05-12 15:46:21 -0700831 act.port = ofp.OFPP_IN_PORT
Rich Lanee30455b2013-01-03 16:24:44 -0800832 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700833 logging.info(request.show())
Dan Talayco3be5b062010-05-12 15:46:21 -0700834
Rich Lane9a003812012-10-04 17:17:59 -0700835 logging.info("Inserting flow")
Dan Talayco3be5b062010-05-12 15:46:21 -0700836 rv = self.controller.message_send(request)
837 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700838 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco3be5b062010-05-12 15:46:21 -0700839
Rich Lane9a003812012-10-04 17:17:59 -0700840 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco3be5b062010-05-12 15:46:21 -0700841 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700842 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700843
Rich Laneb90a1c42012-10-05 09:16:05 -0700844class FloodMinusPort(base_tests.SimpleDataPlane):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700845 """
846 Config port with No_Flood and test Flood action
847
848 Generate a packet
849 Generate a matching flow
850 Add action to forward to OFPP_ALL
851 Set port to no-flood
852 Send the packet to ingress dataplane port
853 Verify the packet is received at all other ports except
854 the ingress port and the no_flood port
855 """
856 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700857 of_ports = config["port_map"].keys()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700858 of_ports.sort()
859 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
860
861 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700862 match = packet_to_flow_match(self, pkt)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700863 match.wildcards &= ~ofp.OFPFW_IN_PORT
864 self.assertTrue(match is not None,
865 "Could not generate flow match from pkt")
866 act = action.action_output()
867
Rich Lane4b9e38c2012-12-06 16:33:20 -0800868 # Clear OFPPC_NO_FLOOD on each port
869 for of_port in of_ports:
870 rv = port_config_set(self.controller, of_port,
871 0, ofp.OFPPC_NO_FLOOD)
872 self.assertEqual(rv, 0, "Failed to set port config")
873
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700874 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700875 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700876 self.assertEqual(rv, 0, "Failed to delete all flows")
877
878 ingress_port = of_ports[idx]
879 no_flood_idx = (idx + 1) % len(of_ports)
880 no_flood_port = of_ports[no_flood_idx]
881 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700882 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700883 self.assertEqual(rv, 0, "Failed to set port config")
884
885 match.in_port = ingress_port
886
887 request = message.flow_mod()
888 request.match = match
889 request.buffer_id = 0xffffffff
890 act.port = ofp.OFPP_FLOOD
Rich Lanee30455b2013-01-03 16:24:44 -0800891 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700892 logging.info(request.show())
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700893
Rich Lane9a003812012-10-04 17:17:59 -0700894 logging.info("Inserting flow")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700895 rv = self.controller.message_send(request)
896 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700897 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700898
Rich Lane9a003812012-10-04 17:17:59 -0700899 logging.info("Sending packet to dp port " + str(ingress_port))
900 logging.info("No flood port is " + str(no_flood_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700901 self.dataplane.send(ingress_port, str(pkt))
902 no_ports = set([ingress_port, no_flood_port])
903 yes_ports = set(of_ports).difference(no_ports)
Rich Lane2014f9b2012-10-05 15:29:40 -0700904 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700905
906 # Turn no flood off again
907 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700908 0, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700909 self.assertEqual(rv, 0, "Failed to reset port config")
Rich Lane4ecc1f42012-12-06 16:35:24 -0800910 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
911
912 # Check that packets are now flooded to no_flood_port
913 logging.info("Sending packet to dp port " + str(ingress_port))
914 self.dataplane.send(ingress_port, str(pkt))
915 no_ports = set([ingress_port])
916 yes_ports = set(of_ports).difference(no_ports)
917 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700918
919 #@todo Should check no other packets received
920
Dan Talayco21381562010-07-17 00:34:47 -0700921
922
Dan Talayco551befa2010-07-15 17:05:32 -0700923################################################################
924
Rich Laneb90a1c42012-10-05 09:16:05 -0700925class BaseMatchCase(base_tests.SimpleDataPlane):
Dan Talayco551befa2010-07-15 17:05:32 -0700926 def setUp(self):
Rich Laneb90a1c42012-10-05 09:16:05 -0700927 base_tests.SimpleDataPlane.setUp(self)
Dan Talayco551befa2010-07-15 17:05:32 -0700928 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -0700929 logging.info("BaseMatchCase")
Dan Talayco551befa2010-07-15 17:05:32 -0700930
931class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700932 """
Dan Talayco551befa2010-07-15 17:05:32 -0700933 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700934
935 Generate a packet
936 Generate and install a matching flow without wildcard mask
937 Add action to forward to a port
938 Send the packet to the port
939 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700940 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700941
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700942 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700943 flow_match_test(self, config["port_map"])
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700944
Dan Talayco551befa2010-07-15 17:05:32 -0700945class ExactMatchTagged(BaseMatchCase):
946 """
947 Exact match for all port pairs with tagged pkts
948 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700949
Dan Talayco551befa2010-07-15 17:05:32 -0700950 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -0700951 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Lane477f4812012-10-04 22:49:00 -0700952 flow_match_test(self, config["port_map"], dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700953
Dan Talayco551befa2010-07-15 17:05:32 -0700954class ExactMatchTaggedMany(BaseMatchCase):
955 """
956 ExactMatchTagged with many VLANS
957 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700958
Rich Laned1d9c282012-10-04 22:07:10 -0700959 priority = -1
960
Dan Talayco551befa2010-07-15 17:05:32 -0700961 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700962 for vid in range(2,100,10):
Rich Lane477f4812012-10-04 22:49:00 -0700963 flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
Dan Talayco551befa2010-07-15 17:05:32 -0700964 for vid in range(100,4000,389):
Rich Lane477f4812012-10-04 22:49:00 -0700965 flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
966 flow_match_test(self, config["port_map"], dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700967
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700968class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700969 """
970 SingleWildcardMatchPriority
971 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700972
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700973 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700974 self.pkt = simple_tcp_packet()
975 self.flowMsgs = {}
976
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700977 def _ClearTable(self):
Rich Lane9a003812012-10-04 17:17:59 -0700978 rc = delete_all_flows(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700979 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700980 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700981
982 def runTest(self):
983
984 self._Init()
Rich Lane477f4812012-10-04 22:49:00 -0700985 of_ports = config["port_map"].keys()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700986 of_ports.sort()
987
988 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700989 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700990
991 # Run several combinations, each at lower priority settings.
992 # At the end of each call to runPrioFlows(), the table should
993 # be empty. If its not, we'll catch it as the priorities decreases
994 portA = of_ports[0]
995 portB = of_ports[1]
996 portC = of_ports[2]
997
998 # TODO -- these priority numbers should be validated somehow?
999 self.runPrioFlows(portA, portB, portC, 1000, 999)
1000 self.runPrioFlows(portB, portC, portA, 998, 997)
1001 self.runPrioFlows(portC, portA, portB, 996, 995)
1002 self.runPrioFlows(portA, portC, portB, 994, 993)
1003
1004
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001005
1006 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
1007 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001008
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001009 if clearTable:
1010 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001011
1012 # Sanity check flow at lower priority from pA to pB
Rich Lane9a003812012-10-04 17:17:59 -07001013 logging.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001014 % (portA, portB, portC, prioHigher, prioLower))
1015
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001016 # Sanity check flow at lower priority from pA to pC
1017 self.installFlow(prioLower, portA, portC)
1018 self.verifyFlow(portA, portC)
1019 self.removeFlow(prioLower)
1020
1021 # Install and verify pA->pB @ prioLower
1022 self.installFlow(prioLower, portA, portB)
1023 self.verifyFlow(portA, portB)
1024
1025 # Install and verify pA->pC @ prioHigher, should override pA->pB
1026 self.installFlow(prioHigher, portA, portC)
1027 self.verifyFlow(portA, portC)
1028 # remove pA->pC
1029 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001030 # Old flow pA -> pB @ prioLower should still be active
1031 self.verifyFlow(portA, portB)
1032 self.removeFlow(prioLower)
1033
1034 # Table should be empty at this point, leave it alone as
1035 # an assumption for future test runs
1036
1037
1038
Ed Swierk99a74de2012-08-22 06:40:54 -07001039 def installFlow(self, prio, inp, egp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001040 wildcards=ofp.OFPFW_DL_SRC):
Ed Swierk99a74de2012-08-22 06:40:54 -07001041 wildcards |= required_wildcards(self)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001042 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001043 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001044 egr_ports=egp)
1045 request.priority = prio
Rich Lane9a003812012-10-04 17:17:59 -07001046 logging.debug("Install flow with priority " + str(prio))
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001047 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001048 self.flowMsgs[prio] = request
1049
1050 def removeFlow(self, prio):
1051 if self.flowMsgs.has_key(prio):
1052 msg = self.flowMsgs[prio]
1053 msg.command = ofp.OFPFC_DELETE_STRICT
1054 # This *must* be set for DELETE
1055 msg.out_port = ofp.OFPP_NONE
Rich Lane9a003812012-10-04 17:17:59 -07001056 logging.debug("Remove flow with priority " + str(prio))
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001057 self.controller.message_send(msg)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001058 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001059 else:
1060 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001061
1062
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001063 def verifyFlow(self, inp, egp, pkt=None):
1064 if pkt == None:
1065 pkt = self.pkt
1066
Rich Lane9a003812012-10-04 17:17:59 -07001067 logging.info("Pkt match test: " + str(inp) + " to " + str(egp))
1068 logging.debug("Send packet: " + str(inp) + " to " + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001069 self.dataplane.send(inp, str(pkt))
1070 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001071
1072
1073
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001074class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
1075
1076 def runTest(self):
1077
1078 self._Init()
1079
Rich Lane477f4812012-10-04 22:49:00 -07001080 of_ports = config["port_map"].keys()
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001081 of_ports.sort()
1082
1083 # Install an entry from 0 -> 1 @ prio 1000
1084 self._ClearTable()
1085 self.installFlow(1000, of_ports[0], of_ports[1])
1086 self.verifyFlow(of_ports[0], of_ports[1])
1087 self.installFlow(1000, of_ports[1], of_ports[0])
1088 self.verifyFlow(of_ports[1], of_ports[0])
1089 self.installFlow(1001, of_ports[0], of_ports[1])
1090 self.verifyFlow(of_ports[0], of_ports[1])
1091 self.installFlow(1001, of_ports[1], of_ports[0])
1092 self.verifyFlow(of_ports[1], of_ports[0])
1093 self.removeFlow(1001)
1094 self.verifyFlow(of_ports[0], of_ports[1])
1095 self.removeFlow(1000)
1096
1097
1098
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001099class WildcardPriority(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001100 """
1101 1. Add wildcard flow, verify packet received.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001102 2. Add wildcard flow with higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001103 on port specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001104 3. Add wildcard flow with lower priority, verify packet received
Rich Laneb8392082012-11-21 15:52:54 -08001105 on port specified by the highest priority flow.
Ken Chiang38d7a152012-05-24 15:33:50 -07001106 """
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001107
1108 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001109
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001110 self._Init()
1111
Rich Lane477f4812012-10-04 22:49:00 -07001112 of_ports = config["port_map"].keys()
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001113 of_ports.sort()
1114
1115 self._ClearTable()
Ken Chiang38d7a152012-05-24 15:33:50 -07001116
1117 # Install a flow with wildcards
1118 self.installFlow(999, of_ports[0], of_ports[1],
1119 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001120 self.verifyFlow(of_ports[0], of_ports[1])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001121 # Install a flow with wildcards with higher priority
1122 self.installFlow(1000, of_ports[0], of_ports[2],
1123 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001124 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001125 # Install a flow with wildcards with lower priority
Rich Laneb8392082012-11-21 15:52:54 -08001126 self.installFlow(999, of_ports[0], of_ports[1],
1127 wildcards=ofp.OFPFW_DL_SRC)
Rich Lane0a78fbd2012-12-31 16:25:04 -08001128 self.verifyFlow(of_ports[0], of_ports[2])
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001129
1130
Ken Chiang3978f242012-06-13 14:14:09 -07001131class WildcardPriorityWithDelete(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001132 """
Rich Lane0a78fbd2012-12-31 16:25:04 -08001133 1. Add wildcard match flow, verify packet received.
Ken Chiang38d7a152012-05-24 15:33:50 -07001134 2. Add wildcard flow with higher priority, verify packet received on port
1135 specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001136 3. Add wildcard flow with even higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001137 on port specified by this flow.
1138 4. Delete lowest priority flow, verify packet received on port specified
1139 by highest priority flow.
1140 5. Delete highest priority flow, verify packet received on port specified
1141 by remaining flow.
1142 """
1143
1144 def runTest(self):
1145
1146 self._Init()
1147
Rich Lane477f4812012-10-04 22:49:00 -07001148 of_ports = config["port_map"].keys()
Ken Chiang38d7a152012-05-24 15:33:50 -07001149 of_ports.sort()
1150
1151 self._ClearTable()
1152
Rich Lane0a78fbd2012-12-31 16:25:04 -08001153 # Install a flow with wildcards
1154 self.installFlow(250, of_ports[0], of_ports[1],
1155 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001156 self.verifyFlow(of_ports[0], of_ports[1])
1157 # Install a flow with wildcards of higher priority
1158 self.installFlow(1250, of_ports[0], of_ports[2],
1159 wildcards=ofp.OFPFW_DL_DST)
1160 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001161 # Install a flow with wildcards with even higher priority
1162 self.installFlow(2001, of_ports[0], of_ports[3],
1163 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001164 self.verifyFlow(of_ports[0], of_ports[3])
1165 # Delete lowest priority flow
1166 self.removeFlow(250)
1167 self.verifyFlow(of_ports[0], of_ports[3])
1168 # Delete highest priority flow
1169 self.removeFlow(2001)
1170 self.verifyFlow(of_ports[0], of_ports[2])
1171
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001172
Dan Talayco551befa2010-07-15 17:05:32 -07001173class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001174 """
1175 Exercise wildcard matching for all ports
1176
1177 Generate a packet
1178 Generate and install a matching flow with wildcard mask
1179 Add action to forward to a port
1180 Send the packet to the port
1181 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001182 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001183 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001184 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001185 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001186 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001187 wc |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001188 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001189 # Set nonzero VLAN id to avoid sending priority-tagged packet
1190 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001191 else:
1192 dl_vlan = -1
Rich Lane477f4812012-10-04 22:49:00 -07001193 flow_match_test(self, config["port_map"], wildcards=wc,
Dan Talayco4431d542012-03-21 16:42:16 -07001194 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001195
Dan Talayco551befa2010-07-15 17:05:32 -07001196class SingleWildcardMatchTagged(BaseMatchCase):
1197 """
1198 SingleWildcardMatch with tagged packets
1199 """
1200 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001201 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001202 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001203 wc |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001204 flow_match_test(self, config["port_map"], wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -07001205 max_test=10)
1206
1207class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001208 """
Dan Talayco80b54ed2010-07-13 09:48:35 -07001209 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001210
1211 Generate a packet
1212 Generate and install a matching flow with wildcard all except one filed
1213 Add action to forward to a port
1214 Send the packet to the port
1215 Verify the packet is received at all other ports (one port at a time)
1216 Verify flow_expiration message is correct when command option is set
1217 """
1218 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001219 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001220 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001221 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001222 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001223 # Set nonzero VLAN id to avoid sending priority-tagged packet
1224 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001225 else:
1226 dl_vlan = -1
Rich Lane477f4812012-10-04 22:49:00 -07001227 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Dan Talayco4431d542012-03-21 16:42:16 -07001228 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001229
Dan Talayco551befa2010-07-15 17:05:32 -07001230class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1231 """
1232 Match one field with tagged packets
1233 """
1234 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001235 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001236 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001237 all_exp_one_wildcard |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001238 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Dan Talayco21381562010-07-17 00:34:47 -07001239 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001240
1241class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001242 """
1243 Create Wildcard-all flow and exercise for all ports
1244
1245 Generate a packet
1246 Generate and install a matching flow with wildcard-all
1247 Add action to forward to a port
1248 Send the packet to the port
1249 Verify the packet is received at all other ports (one port at a time)
1250 Verify flow_expiration message is correct when command option is set
1251 """
1252 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001253 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001254
Dan Talayco551befa2010-07-15 17:05:32 -07001255class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001256 """
Dan Talayco551befa2010-07-15 17:05:32 -07001257 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001258 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001259 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001260 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Lane477f4812012-10-04 22:49:00 -07001261 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL,
Dan Talayco21381562010-07-17 00:34:47 -07001262 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001263
Dan Talaycoba3745c2010-07-21 21:51:08 -07001264
Dan Talayco551befa2010-07-15 17:05:32 -07001265class AddVLANTag(BaseMatchCase):
1266 """
1267 Add a VLAN tag to an untagged packet
1268 """
1269 def runTest(self):
1270 new_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001271 sup_acts = self.supported_actions
Dan Talayco551befa2010-07-15 17:05:32 -07001272 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001273 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001274 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001275
Dan Talayco551befa2010-07-15 17:05:32 -07001276 len = 100
1277 len_w_vid = 104
1278 pkt = simple_tcp_packet(pktlen=len)
1279 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1280 dl_vlan=new_vid)
1281 vid_act = action.action_set_vlan_vid()
1282 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001283
Rich Lane477f4812012-10-04 22:49:00 -07001284 flow_match_test(self, config["port_map"], pkt=pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001285 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001286
Rich Laneb90a1c42012-10-05 09:16:05 -07001287class PacketOnly(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001288 """
1289 Just send a packet thru the switch
1290 """
Rich Laned1d9c282012-10-04 22:07:10 -07001291
1292 priority = -1
1293
Dan Talayco551befa2010-07-15 17:05:32 -07001294 def runTest(self):
1295 pkt = simple_tcp_packet()
Rich Lane477f4812012-10-04 22:49:00 -07001296 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001297 of_ports.sort()
1298 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001299 logging.info("Sending packet to " + str(ing_port))
1300 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001301 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001302
Rich Laneb90a1c42012-10-05 09:16:05 -07001303class PacketOnlyTagged(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001304 """
1305 Just send a packet thru the switch
1306 """
Rich Laned1d9c282012-10-04 22:07:10 -07001307
1308 priority = -1
1309
Dan Talayco551befa2010-07-15 17:05:32 -07001310 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001311 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001312 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
Rich Lane477f4812012-10-04 22:49:00 -07001313 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001314 of_ports.sort()
1315 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001316 logging.info("Sending packet to " + str(ing_port))
1317 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001318 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001319
Dan Talayco551befa2010-07-15 17:05:32 -07001320class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001321 """
1322 Modify the VLAN ID in the VLAN tag of a tagged packet
1323 """
Dan Talaycoaf669322012-09-12 22:51:22 -07001324 def setUp(self):
1325 BaseMatchCase.setUp(self)
1326 self.ing_port=False
1327
Dan Talayco551befa2010-07-15 17:05:32 -07001328 def runTest(self):
1329 old_vid = 2
1330 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001331 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001332 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001333 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001334 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001335
Dan Talayco551befa2010-07-15 17:05:32 -07001336 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1337 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
1338 vid_act = action.action_set_vlan_vid()
1339 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001340
Rich Lane477f4812012-10-04 22:49:00 -07001341 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoaf669322012-09-12 22:51:22 -07001342 action_list=[vid_act], ing_port=self.ing_port)
1343
1344class ModifyVIDToIngress(ModifyVID):
1345 """
1346 Modify the VLAN ID in the VLAN tag of a tagged packet and send to
1347 ingress port
1348 """
1349 def setUp(self):
1350 BaseMatchCase.setUp(self)
1351 self.ing_port=True
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001352
Ken Chiange9a211d2012-04-20 14:52:11 -07001353class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1354 """
1355 With vlan ID and priority wildcarded, perform SET_VLAN_VID action.
1356 The same flow should match on both untagged and tagged packets.
1357 """
1358 def runTest(self):
1359 old_vid = 2
1360 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001361 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001362 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1363 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1364 return
1365
Rich Lane477f4812012-10-04 22:49:00 -07001366 of_ports = config["port_map"].keys()
Ken Chiange9a211d2012-04-20 14:52:11 -07001367 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1368 ing_port = of_ports[0]
1369 egr_ports = of_ports[1]
1370
Rich Lane9a003812012-10-04 17:17:59 -07001371 rv = delete_all_flows(self.controller)
Ken Chiange9a211d2012-04-20 14:52:11 -07001372 self.assertEqual(rv, 0, "Failed to delete all flows")
1373
1374 len_untagged = 100
1375 len_w_vid = 104
1376 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1377 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
1378 dl_vlan_enable=True, dl_vlan=old_vid)
1379 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1380 dl_vlan=new_vid)
Ed Swierk99a74de2012-08-22 06:40:54 -07001381 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1382 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001383 vid_act = action.action_set_vlan_vid()
1384 vid_act.vlan_vid = new_vid
1385 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
1386 wildcards=wildcards, egr_ports=egr_ports,
1387 action_list=[vid_act])
1388 flow_msg_install(self, request)
1389
Rich Lane9a003812012-10-04 17:17:59 -07001390 logging.debug("Send untagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001391 str(egr_ports))
1392 self.dataplane.send(ing_port, str(untagged_pkt))
1393 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1394
Rich Lane9a003812012-10-04 17:17:59 -07001395 logging.debug("Send tagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001396 str(egr_ports))
1397 self.dataplane.send(ing_port, str(tagged_pkt))
1398 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1399
Howard Pershc1199d52012-04-11 14:21:32 -07001400class ModifyVlanPcp(BaseMatchCase):
1401 """
1402 Modify the priority field of the VLAN tag of a tagged packet
1403 """
1404 def runTest(self):
1405 vid = 123
1406 old_vlan_pcp = 2
1407 new_vlan_pcp = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001408 sup_acts = self.supported_actions
Ed Swierk8c3af7f2012-04-24 14:19:17 -07001409 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_PCP):
1410 skip_message_emit(self, "Modify VLAN priority test")
Howard Pershc1199d52012-04-11 14:21:32 -07001411 return
1412
1413 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1414 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1415 vid_act = action.action_set_vlan_pcp()
1416 vid_act.vlan_pcp = new_vlan_pcp
1417
Rich Lane477f4812012-10-04 22:49:00 -07001418 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Howard Pershc1199d52012-04-11 14:21:32 -07001419 action_list=[vid_act])
1420
Dan Talayco551befa2010-07-15 17:05:32 -07001421class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001422 """
1423 Strip the VLAN tag from a tagged packet
1424 """
Dan Talayco551befa2010-07-15 17:05:32 -07001425 def runTest(self):
1426 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001427 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001428 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001429 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001430 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001431
Dan Talayco551befa2010-07-15 17:05:32 -07001432 len_w_vid = 104
1433 len = 100
1434 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1435 dl_vlan=old_vid)
1436 exp_pkt = simple_tcp_packet(pktlen=len)
1437 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001438
Rich Lane477f4812012-10-04 22:49:00 -07001439 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001440 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001441
Ken Chiange9a211d2012-04-20 14:52:11 -07001442class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1443 """
1444 Strip the VLAN tag from a tagged packet.
1445 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1446 """
1447 def runTest(self):
1448 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001449 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001450 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1451 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1452 return
1453
1454 len_w_vid = 104
1455 len_untagged = 100
1456 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1457 dl_vlan=old_vid)
1458 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
Ed Swierk99a74de2012-08-22 06:40:54 -07001459 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1460 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001461 vid_act = action.action_strip_vlan()
1462
Rich Lane477f4812012-10-04 22:49:00 -07001463 flow_match_test(self, config["port_map"],
Ed Swierk99a74de2012-08-22 06:40:54 -07001464 wildcards=wildcards,
Ken Chiange9a211d2012-04-20 14:52:11 -07001465 pkt=pkt, exp_pkt=exp_pkt,
1466 action_list=[vid_act])
1467
Dan Talayco4b2bee62010-07-20 14:10:05 -07001468def init_pkt_args():
1469 """
1470 Pass back a dictionary with default packet arguments
1471 """
1472 args = {}
1473 args["dl_src"] = '00:23:45:67:89:AB'
1474
1475 dl_vlan_enable=False
1476 dl_vlan=-1
Rich Lane477f4812012-10-04 22:49:00 -07001477 if config["test-params"]["vid"]:
Dan Talayco4b2bee62010-07-20 14:10:05 -07001478 dl_vlan_enable=True
Rich Lane477f4812012-10-04 22:49:00 -07001479 dl_vlan = config["test-params"]["vid"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001480
1481# Unpack operator is ** on a dictionary
1482
1483 return args
1484
Dan Talayco551befa2010-07-15 17:05:32 -07001485class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001486 """
1487 Modify the source MAC address (TP1)
1488 """
Dan Talayco551befa2010-07-15 17:05:32 -07001489 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001490 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001491 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001492 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001493 return
1494
1495 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1496 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001497 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001498 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001499
Dan Talayco551befa2010-07-15 17:05:32 -07001500class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001501 """
1502 Modify the dest MAC address (TP1)
1503 """
Dan Talayco551befa2010-07-15 17:05:32 -07001504 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001505 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001506 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001507 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001508 return
1509
1510 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1511 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001512 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001513 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001514
Dan Talayco551befa2010-07-15 17:05:32 -07001515class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001516 """
1517 Modify the source IP address of an IP packet (TP1)
1518 """
Dan Talayco551befa2010-07-15 17:05:32 -07001519 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001520 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001521 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001522 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001523 return
1524
1525 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1526 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001527 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001528 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001529
Dan Talayco551befa2010-07-15 17:05:32 -07001530class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001531 """
1532 Modify the dest IP address of an IP packet (TP1)
1533 """
Dan Talayco551befa2010-07-15 17:05:32 -07001534 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001535 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001536 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001537 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001538 return
1539
1540 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1541 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001542 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001543 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001544
1545class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001546 """
1547 Modify the source TCP port of a TCP packet (TP1)
1548 """
Dan Talayco551befa2010-07-15 17:05:32 -07001549 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001550 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001551 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001552 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001553 return
1554
1555 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1556 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001557 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001558 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001559
Rich Lane01c2b862012-10-26 16:26:25 -07001560class ModifyL4SrcUdp(BaseMatchCase):
1561 """
1562 Modify the source UDP port of a UDP packet
1563 """
1564 def runTest(self):
1565 sup_acts = self.supported_actions
1566 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1567 skip_message_emit(self, "ModifyL4SrcUdp test")
1568 return
1569
1570 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_sport'],
1571 check_test_params=True, tp="udp")
1572 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1573 action_list=acts, max_test=2)
1574
Dan Talayco551befa2010-07-15 17:05:32 -07001575class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001576 """
1577 Modify the dest TCP port of a TCP packet (TP1)
1578 """
Dan Talayco551befa2010-07-15 17:05:32 -07001579 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001580 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001581 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001582 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001583 return
1584
1585 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1586 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001587 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001588 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001589
Rich Lane01c2b862012-10-26 16:26:25 -07001590class ModifyL4DstUdp(BaseMatchCase):
1591 """
1592 Modify the dest UDP port of a UDP packet
1593 """
1594 def runTest(self):
1595 sup_acts = self.supported_actions
1596 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1597 skip_message_emit(self, "ModifyL4DstUdp test")
1598 return
1599
1600 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_dport'],
1601 check_test_params=True, tp="udp")
1602 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1603 action_list=acts, max_test=2)
1604
Dan Talayco551befa2010-07-15 17:05:32 -07001605class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001606 """
1607 Modify the IP type of service of an IP packet (TP1)
1608 """
Dan Talayco551befa2010-07-15 17:05:32 -07001609 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001610 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001611 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001612 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001613 return
Dan Talayco551befa2010-07-15 17:05:32 -07001614
Dan Talayco4b2bee62010-07-20 14:10:05 -07001615 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1616 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001617 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001618 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001619
Dan Talaycof6e76c02012-03-23 10:56:12 -07001620class ModifyL2DstMC(BaseMatchCase):
1621 """
1622 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001623 """
1624 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001625 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001626 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001627 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001628 return
1629
Dan Talaycof6e76c02012-03-23 10:56:12 -07001630 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1631 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001632 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001633 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001634
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001635class ModifyL2DstIngress(BaseMatchCase):
1636 """
1637 Modify the L2 dest and send to the ingress port
1638 """
1639 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001640 sup_acts = self.supported_actions
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001641 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001642 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001643 return
1644
1645 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1646 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001647 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001648 action_list=acts, max_test=2, egr_count=0,
1649 ing_port=True)
1650
Dan Talaycod8ae7582012-03-23 12:24:56 -07001651class ModifyL2DstIngressMC(BaseMatchCase):
1652 """
1653 Modify the L2 dest and send to the ingress port
1654 """
1655 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001656 sup_acts = self.supported_actions
Dan Talaycod8ae7582012-03-23 12:24:56 -07001657 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1658 skip_message_emit(self, "ModifyL2dstMC test")
1659 return
1660
1661 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1662 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001663 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001664 action_list=acts, max_test=2, egr_count=-1,
1665 ing_port=True)
1666
Dan Talaycof6e76c02012-03-23 10:56:12 -07001667class ModifyL2SrcMC(BaseMatchCase):
1668 """
1669 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001670 """
1671 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001672 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001673 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001674 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001675 return
1676
Dan Talaycof6e76c02012-03-23 10:56:12 -07001677 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1678 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001679 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001680 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001681
1682class ModifyL2SrcDstMC(BaseMatchCase):
1683 """
1684 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001685 """
1686 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001687 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001688 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1689 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1690 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001691 return
1692
Dan Talaycof6e76c02012-03-23 10:56:12 -07001693 mod_fields = ['dl_dst', 'dl_src']
1694 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1695 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001696 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001697 action_list=acts, max_test=2, egr_count=-1)
1698
1699class ModifyL2DstVIDMC(BaseMatchCase):
1700 """
1701 Modify the L2 dest and send to 2 ports
1702 """
1703 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001704 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001705 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1706 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1707 skip_message_emit(self, "ModifyL2DstVIDMC test")
1708 return
1709
1710 mod_fields = ['dl_dst', 'dl_vlan']
1711 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1712 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1713 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001714 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001715 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001716
Rich Lane22e74c12012-11-12 15:06:06 -08001717class ModifyAll(BaseMatchCase):
1718 """
1719 Modify all supported fields and output to a port
1720 """
1721 def runTest(self):
1722 sup_acts = self.supported_actions
1723
1724 sup_map = {
1725 "dl_dst" : ofp.OFPAT_SET_DL_DST,
1726 "dl_src" : ofp.OFPAT_SET_DL_SRC,
1727 "dl_vlan_enable" : ofp.OFPAT_SET_VLAN_VID,
1728 "dl_vlan" : ofp.OFPAT_SET_VLAN_VID,
1729 "dl_vlan_pcp" : ofp.OFPAT_SET_VLAN_PCP,
1730 "ip_src" : ofp.OFPAT_SET_NW_SRC,
1731 "ip_dst" : ofp.OFPAT_SET_NW_DST,
1732 "ip_tos" : ofp.OFPAT_SET_NW_TOS,
1733 "tcp_sport" : ofp.OFPAT_SET_TP_SRC,
1734 "tcp_dport" : ofp.OFPAT_SET_TP_DST,
1735 }
1736
1737 mod_fields = [field for (field, bit) in sup_map.items() if (sup_acts & 1 << bit)]
1738 random.shuffle(mod_fields)
1739 start_field_vals = { "dl_vlan_enable" : True }
1740 mod_field_vals = { "dl_vlan_enable" : True }
1741 logging.info("modifying fields: %s" % repr(mod_fields))
1742
1743 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1744 mod_fields=mod_fields,
1745 start_field_vals=start_field_vals,
1746 mod_field_vals=mod_field_vals,
1747 check_test_params=True)
1748 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1749 action_list=acts, max_test=2)
1750
Dan Talaycofa6454f2012-04-05 10:04:13 -07001751class FlowToggle(BaseMatchCase):
1752 """
1753 Add flows to the table and modify them repeatedly
Dan Talaycof7c41312012-07-23 12:53:19 -07001754
1755 This is done by using only "add" flow messages. Since the check overlap
1756 flag is not set, the switch is supposed to modify the existing flow if
1757 the match already exists.
1758
1759 Would probably be better to exercise more of the flow modify commands
1760 (add, modify, delete +/- strict).
Dan Talaycofa6454f2012-04-05 10:04:13 -07001761 """
1762 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001763 flow_count = test_param_get('ft_flow_count', default=20)
1764 iter_count = test_param_get('ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001765
Rich Lane9a003812012-10-04 17:17:59 -07001766 logging.info("Running flow toggle with %d flows, %d iterations" %
Dan Talaycofa6454f2012-04-05 10:04:13 -07001767 (flow_count, iter_count))
1768 acts = []
1769 acts.append(action.action_output())
1770 acts.append(action.action_output())
1771
Rich Lane477f4812012-10-04 22:49:00 -07001772 of_ports = config["port_map"].keys()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001773 if len(of_ports) < 3:
1774 self.assertTrue(False, "Too few ports for test")
1775
1776 for idx in range(2):
1777 acts[idx].port = of_ports[idx]
1778
1779 flows = []
1780 flows.append([])
1781 flows.append([])
1782
Ed Swierk99a74de2012-08-22 06:40:54 -07001783 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_SRC |
1784 ofp.OFPFW_DL_DST)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001785 # Create up the flows in an array
1786 for toggle in range(2):
1787 for f_idx in range(flow_count):
1788 pkt = simple_tcp_packet(tcp_sport=f_idx)
1789 msg = message.flow_mod()
Ed Swierk99a74de2012-08-22 06:40:54 -07001790 match = packet_to_flow_match(self, pkt)
Shudong Zhou031373c2012-07-19 17:37:42 -07001791 match.in_port = of_ports[2]
Dan Talayco50be7672012-04-05 11:38:08 -07001792 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001793 msg.match = match
1794 msg.buffer_id = 0xffffffff
Dan Talaycof7c41312012-07-23 12:53:19 -07001795 msg.command = ofp.OFPFC_ADD
Dan Talaycofa6454f2012-04-05 10:04:13 -07001796 msg.actions.add(acts[toggle])
1797 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001798
1799 # Show two sample flows
Rich Lane9a003812012-10-04 17:17:59 -07001800 logging.debug(flows[0][0].show())
1801 logging.debug(flows[1][0].show())
Dan Talayco50be7672012-04-05 11:38:08 -07001802
Dan Talaycofa6454f2012-04-05 10:04:13 -07001803 # Install the first set of flows
1804 for f_idx in range(flow_count):
1805 rv = self.controller.message_send(flows[0][f_idx])
1806 self.assertTrue(rv != -1, "Error installing flow %d" % f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001807 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycofa6454f2012-04-05 10:04:13 -07001808
Rich Lane9a003812012-10-04 17:17:59 -07001809 logging.info("Installed %d flows" % flow_count)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001810
1811 # Repeatedly modify all the flows back and forth
1812 updates = 0
1813 # Report status about 5 times
1814 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001815 start = time.time()
1816 for iter_idx in range(iter_count):
1817 if not iter_idx % mod_val:
Rich Lane9a003812012-10-04 17:17:59 -07001818 logging.info("Flow Toggle: iter %d of %d. " %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001819 (iter_idx, iter_count) +
1820 "%d updates in %d secs" %
1821 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001822 for toggle in range(2):
1823 t_idx = 1 - toggle
1824 for f_idx in range(flow_count):
1825 rv = self.controller.message_send(flows[t_idx][f_idx])
1826 updates += 1
1827 self.assertTrue(rv != -1, "Error modifying flow %d" %
1828 f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001829 self.assertEqual(do_barrier(self.controller), 0,
1830 "Barrier failed")
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001831
1832 end = time.time()
1833 divisor = end - start or (end - start + 1)
Rich Lane9a003812012-10-04 17:17:59 -07001834 logging.info("Flow toggle: %d iterations" % iter_count)
1835 logging.info(" %d flow mods in %d secs, %d mods/sec" %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001836 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001837
1838
Dan Talayco8a64e332012-03-28 14:53:20 -07001839# You can pick and choose these by commenting tests in or out
1840iter_classes = [
1841 basic.PacketIn,
1842 basic.PacketOut,
1843 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001844 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001845 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001846 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001847 AllWildcardMatch,
1848 AllWildcardMatchTagged,
1849 SingleWildcardMatch,
1850 SingleWildcardMatchTagged,
1851 ExactMatch,
1852 ExactMatchTagged,
1853 SingleWildcardMatch,
1854 ModifyL2Src,
1855 ModifyL2Dst,
1856 ModifyL2SrcMC,
1857 ModifyL2DstMC,
1858 ModifyL2SrcDstMC
1859 ]
1860
1861class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001862 """
1863 Iterate over a bunch of test cases
1864
1865 The cases come from the list above
1866 """
1867
Rich Laned1d9c282012-10-04 22:07:10 -07001868 priority = -1
1869
Dan Talayco8a64e332012-03-28 14:53:20 -07001870 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001871 count = test_param_get('iter_count', default=10)
Dan Talayco8a64e332012-03-28 14:53:20 -07001872 tests_done = 0
Rich Lane9a003812012-10-04 17:17:59 -07001873 logging.info("Running iteration test " + str(count) + " times")
Dan Talayco8a64e332012-03-28 14:53:20 -07001874 start = time.time()
1875 last = start
1876 for idx in range(count):
Rich Lane9a003812012-10-04 17:17:59 -07001877 logging.info("Iteration " + str(idx + 1))
Dan Talayco8a64e332012-03-28 14:53:20 -07001878 for cls in iter_classes:
1879 test = cls()
1880 test.inheritSetup(self)
1881 test.runTest()
1882 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001883 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001884 if time.time() - last > 60:
1885 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001886 logging.info(
Dan Talaycofa6454f2012-04-05 10:04:13 -07001887 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1888 (idx, count, tests_done, last - start) +
1889 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001890 stats = all_stats_get(self)
1891 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001892 logging.info("\nIterCases ran %d tests in %d seconds." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001893 (tests_done, last - start))
Rich Lane9a003812012-10-04 17:17:59 -07001894 logging.info(" flows: %d. packets: %d. bytes: %d" %
Dan Talayco8a64e332012-03-28 14:53:20 -07001895 (stats["flows"], stats["packets"], stats["bytes"]))
Rich Lane9a003812012-10-04 17:17:59 -07001896 logging.info(" active: %d. lookups: %d. matched %d." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001897 (stats["active"], stats["lookups"], stats["matched"]))
1898
Dan Talayco4b2bee62010-07-20 14:10:05 -07001899#@todo Need to implement tagged versions of the above tests
1900#
1901#@todo Implement a test case that strips tag 2, adds tag 3
1902# and modifies tag 4 to tag 5. Then verify (in addition) that
1903# tag 6 does not get modified.
1904
1905class MixedVLAN(BaseMatchCase):
1906 """
1907 Test mixture of VLAN tag actions
1908
1909 Strip tag 2 on port 1, send to port 2
1910 Add tag 3 on port 1, send to port 2
1911 Modify tag 4 to 5 on port 1, send to port 2
1912 All other traffic from port 1, send to port 3
1913 All traffic from port 2 sent to port 4
1914 Use exact matches with different packets for all mods
1915 Verify the following: (port, vid)
1916 (port 1, vid 2) => VLAN tag stripped, out port 2
1917 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1918 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1919 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1920 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1921 (port 2, no tag) => untagged packet out port 4
1922 (port 2, vid 2-6) => unmodified packet out port 4
1923
1924 Variation: Might try sending VID 5 to port 3 and check.
1925 If only VID 5 distinguishes pkt, this will fail on some platforms
1926 """
1927
Rich Laned1d9c282012-10-04 22:07:10 -07001928 priority = -1
Rich Lane8d6ab272012-09-23 18:06:20 -07001929
Rich Laneb90a1c42012-10-05 09:16:05 -07001930class MatchEach(base_tests.SimpleDataPlane):
Rich Lane8d6ab272012-09-23 18:06:20 -07001931 """
1932 Check that each match field is actually matched on.
1933 Installs two flows that differ in one field. The flow that should not
1934 match has a higher priority, so if that field is ignored during matching
1935 the packet will be sent out the wrong port.
1936
1937 TODO test UDP, ARP, ICMP, etc.
1938 """
1939 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001940 of_ports = config["port_map"].keys()
Rich Lane8d6ab272012-09-23 18:06:20 -07001941 of_ports.sort()
1942 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1943
Rich Lane9a003812012-10-04 17:17:59 -07001944 delete_all_flows(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001945
Ed Swierk7040a8d2012-12-11 16:30:13 -08001946 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=2)
Rich Lane8d6ab272012-09-23 18:06:20 -07001947 ingress_port = of_ports[0]
1948 egress_port = of_ports[1]
1949
1950 def testField(field, mask):
Rich Lane9a003812012-10-04 17:17:59 -07001951 logging.info("Testing field %s" % field)
Rich Lane8d6ab272012-09-23 18:06:20 -07001952
1953 def addFlow(matching, priority, output_port):
1954 match = packet_to_flow_match(self, pkt)
1955 self.assertTrue(match is not None, "Could not generate flow match from pkt")
1956 match.wildcards &= ~ofp.OFPFW_IN_PORT
1957 match.in_port = ingress_port
1958 if not matching:
1959 # Make sure flow doesn't match
1960 orig = getattr(match, field)
1961 if isinstance(orig, list):
1962 new = map(lambda a: ~a[0] & a[1], zip(orig, mask))
1963 else:
1964 new = ~orig & mask
1965 setattr(match, field, new)
1966 request = message.flow_mod()
1967 request.match = match
1968 request.buffer_id = 0xffffffff
1969 request.priority = priority
1970 act = action.action_output()
1971 act.port = output_port
Rich Lanee30455b2013-01-03 16:24:44 -08001972 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -07001973 logging.info("Inserting flow")
Rich Lane8d6ab272012-09-23 18:06:20 -07001974 self.controller.message_send(request)
1975
1976 # This flow should match.
1977 addFlow(matching=True, priority=0, output_port=egress_port)
1978 # This flow should not match, but it has a higher priority.
1979 addFlow(matching=False, priority=1, output_port=ofp.OFPP_IN_PORT)
1980
1981 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
1982
Rich Lane9a003812012-10-04 17:17:59 -07001983 logging.info("Sending packet to dp port " + str(ingress_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001984 self.dataplane.send(ingress_port, str(pkt))
1985
1986 exp_pkt_arg = None
1987 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -07001988 if config["relax"]:
Rich Lane8d6ab272012-09-23 18:06:20 -07001989 exp_pkt_arg = pkt
1990 exp_port = egress_port
1991
1992 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
1993 exp_pkt=exp_pkt_arg)
1994 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -07001995 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001996 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
1997 self.assertEqual(str(pkt), str(rcv_pkt), 'Response packet does not match send packet')
1998
Ed Swierkb603b192012-12-12 15:38:49 -08001999 wildcards = required_wildcards(self)
Rich Lane8d6ab272012-09-23 18:06:20 -07002000 # TODO in_port
Ed Swierkb603b192012-12-12 15:38:49 -08002001 if not (wildcards & ofp.OFPFW_DL_SRC):
2002 testField("dl_src", [0xff]*6)
2003 if not (wildcards & ofp.OFPFW_DL_DST):
2004 testField("dl_dst", [0xff]*6)
2005 if not (wildcards & ofp.OFPFW_DL_TYPE):
2006 testField("dl_type", 0xffff)
2007 if not (wildcards & ofp.OFPFW_DL_VLAN):
2008 testField("dl_vlan", 0xfff)
Rich Lane8d6ab272012-09-23 18:06:20 -07002009 # TODO dl_vlan_pcp
Ed Swierkb603b192012-12-12 15:38:49 -08002010 if not (wildcards & ofp.OFPFW_NW_SRC_ALL):
2011 testField("nw_src", 0xffffffff)
2012 if not (wildcards & ofp.OFPFW_NW_DST_ALL):
2013 testField("nw_dst", 0xffffffff)
2014 if not (wildcards & ofp.OFPFW_NW_TOS):
2015 testField("nw_tos", 0x3f)
2016 if not (wildcards & ofp.OFPFW_NW_PROTO):
2017 testField("nw_proto", 0xff)
2018 if not (wildcards & ofp.OFPFW_TP_SRC):
2019 testField("tp_src", 0xffff)
2020 if not (wildcards & ofp.OFPFW_TP_DST):
2021 testField("tp_dst", 0xffff)
Rich Lane8d6ab272012-09-23 18:06:20 -07002022
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002023class DirectBadPacketBase(base_tests.SimpleDataPlane):
2024 """
2025 Base class for sending single packets with single flow table entries.
2026 Used to verify matching of unusual packets and parsing/matching of
2027 corrupted packets.
2028
2029 The idea is to generate packets that may either be totally malformed or
2030 malformed just enough to trick the flow matcher into making mistakes.
2031
2032 Generate a 'bad' packet
2033 Generate and install a matching flow
2034 Add action to direct the packet to an egress port
2035 Send the packet to ingress dataplane port
2036 Verify the packet is received at the egress port only
2037 """
2038
2039 RESULT_MATCH = "MATCH"
2040 RESULT_NOMATCH = "NO MATCH"
2041 RESULT_ANY = "ANY MATCH"
2042
2043 def runTest(self):
2044 pass
2045 # TODO:
2046 # - ICMP?
2047 # - VLAN?
2048 # - action
2049
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002050 def createMatch(self, **kwargs):
2051 match = ofp.ofp_match()
2052 match.wildcards = ofp.OFPFW_ALL
2053 fields = {
2054 'dl_dst': ofp.OFPFW_DL_DST,
2055 'dl_src': ofp.OFPFW_DL_SRC,
2056 'dl_type': ofp.OFPFW_DL_TYPE,
2057 'dl_vlan': ofp.OFPFW_DL_VLAN,
2058 'nw_src': ofp.OFPFW_NW_SRC_MASK,
2059 'nw_dst': ofp.OFPFW_NW_DST_MASK,
2060 'nw_tos': ofp.OFPFW_NW_TOS,
2061 'nw_proto': ofp.OFPFW_NW_PROTO,
2062 'tp_src': ofp.OFPFW_TP_SRC,
2063 'tp_dst': ofp.OFPFW_TP_DST,
2064 }
2065 for key in kwargs:
2066 setattr(match, key, kwargs[key])
2067 match.wildcards &= ~fields[key]
2068 return match
2069
2070 def testPktsAgainstFlow(self, pkts, acts, match):
2071 if type(acts) != list:
2072 acts = [acts]
2073 for info in pkts:
2074 title, pkt, expected_result = info
2075 self.testPktAgainstFlow(title, pkt, acts, match, expected_result)
2076
2077 def testPktAgainstFlow(self, title, pkt, acts, match, expected_result):
2078 of_ports = config["port_map"].keys()
2079 of_ports.sort()
2080 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
2081
2082 rv = delete_all_flows(self.controller)
2083 self.assertEqual(rv, 0, "Failed to delete all flows")
2084
2085 ingress_port = of_ports[0]
2086 egress_port = of_ports[1]
2087
2088 logging.info("Testing packet '%s', expect result %s" %
2089 (title, expected_result))
2090 logging.info("Ingress %s to egress %s" %
2091 (str(ingress_port), str(egress_port)))
2092 logging.info("Packet:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002093 logging.info(inspect_packet(pkt))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002094
2095 match.in_port = ingress_port
2096
2097 request = message.flow_mod()
2098 request.match = match
Rich Lane44cf12d2012-10-15 11:10:45 -07002099 request.priority = 1
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002100
2101 request.buffer_id = 0xffffffff
2102 for act in acts:
2103 act.port = egress_port
Rich Lanee30455b2013-01-03 16:24:44 -08002104 request.actions.add(act)
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002105
2106 logging.info("Inserting flow")
2107 rv = self.controller.message_send(request)
2108 self.assertTrue(rv != -1, "Error installing flow mod")
Rich Lane44cf12d2012-10-15 11:10:45 -07002109
2110 # This flow speeds up negative tests
2111 logging.info("Inserting catch-all flow")
2112 request2 = message.flow_mod()
2113 request2.match = self.createMatch()
2114 request2.priority = 0
2115 act = action.action_output()
2116 act.port = ofp.OFPP_IN_PORT
2117 request2.actions.add(act)
2118 rv = self.controller.message_send(request2)
2119 self.assertTrue(rv != -1, "Error installing flow mod")
2120
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002121 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
2122
2123 logging.info("Sending packet to dp port " +
2124 str(ingress_port))
2125 self.dataplane.send(ingress_port, str(pkt))
2126
2127 exp_pkt_arg = None
2128 exp_port = None
2129 if config["relax"]:
2130 exp_pkt_arg = pkt
2131 exp_port = egress_port
2132
Rich Lane44cf12d2012-10-15 11:10:45 -07002133 if expected_result == self.RESULT_MATCH:
2134 timeout = -1 # default timeout
2135 else:
2136 timeout = 1 # short timeout for negative tests
2137
2138 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(exp_pkt=exp_pkt_arg,
2139 timeout=timeout)
2140 if rcv_port == ingress_port:
2141 logging.debug("Packet matched catch-all flow")
2142 rcv_pkt = None
2143
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002144 if expected_result == self.RESULT_MATCH:
2145 self.assertTrue(rcv_pkt is not None,
2146 "Did not receive packet, expected a match")
2147 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
2148 str(rcv_port))
2149 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
2150 str_pkt = str(pkt)
2151 str_rcv_pkt = str(rcv_pkt)
2152 str_rcv_pkt = str_rcv_pkt[0:len(str_pkt)]
2153 if str_pkt != str_rcv_pkt:
2154 logging.error("Response packet does not match send packet")
2155 logging.info("Response:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002156 logging.info(inspect_packet(scapy.Ether(rcv_pkt)))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002157 self.assertEqual(str_pkt, str_rcv_pkt,
2158 'Response packet does not match send packet')
2159 elif expected_result == self.RESULT_NOMATCH:
2160 self.assertTrue(rcv_pkt is None, "Received packet, expected drop")
2161 else:
2162 logging.debug("Match or drop accepted. Result = %s" %
2163 ("match" if rcv_pkt is not None else "drop"))
2164
2165
2166class DirectBadIpTcpPacketsBase(DirectBadPacketBase):
2167 """
2168 Base class for TCP and UDP parsing/matching verification under corruptions
2169 """
2170 def runTest(self):
2171 pass
2172
2173 def runTestWithProto(self, protoName = 'TCP'):
2174 dl_dst='00:01:02:03:04:05'
2175 dl_src='00:06:07:08:09:0a'
2176 ip_src='192.168.0.1'
2177 ip_dst='192.168.0.2'
2178 ip_tos=0
2179 tcp_sport=1234
2180 tcp_dport=80
2181
2182 # Generate a proper packet for constructing a match
2183 tp = None
2184 if protoName == 'TCP':
2185 tp = scapy.TCP
2186 proto = 6
2187 elif protoName == 'UDP':
2188 tp = scapy.UDP
2189 proto = 17
2190 else:
2191 raise Exception("Passed in unknown proto name")
2192
2193 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
2194 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2195 tp(sport=tcp_sport, dport=tcp_dport)
2196 match = packet_to_flow_match(self, match_pkt)
2197 self.assertTrue(match is not None,
2198 "Could not generate flow match from pkt")
2199 match.wildcards &= ~ofp.OFPFW_IN_PORT
2200
2201 def testPacket(title, pkt, result):
2202 act = action.action_output()
2203 pkts = [
2204 [title, pkt, result]
2205 ]
2206 self.testPktsAgainstFlow(pkts, act, match)
2207
2208 # Try incomplete IP headers
2209 testPacket("Incomplete IP header (1 bytes)",
2210 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2211 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:1],
2212 self.RESULT_NOMATCH,
2213 )
2214 testPacket("Incomplete IP header (2 bytes)",
2215 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2216 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:2],
2217 self.RESULT_NOMATCH,
2218 )
2219 testPacket("Incomplete IP header (3 bytes)",
2220 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2221 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:3],
2222 self.RESULT_NOMATCH,
2223 )
2224 testPacket("Incomplete IP header (12 bytes)",
2225 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2226 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:12],
2227 self.RESULT_NOMATCH,
2228 )
2229 testPacket("Incomplete IP header (16 bytes)",
2230 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2231 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:16],
2232 self.RESULT_NOMATCH,
2233 )
2234 testPacket("Incomplete IP header (19 bytes)",
2235 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2236 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:19],
2237 self.RESULT_NOMATCH,
2238 )
2239
2240 # Try variations where the TCP header is missing or incomplete. As we
2241 # saw bugs before where buffers were reused and lengths weren't honored,
2242 # we initiatlize once with a non-matching full packet and once with a
2243 # matching full packet.
2244 testPacket("Non-Matching TCP packet, warming buffer",
2245 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2246 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2247 tp(sport=tcp_sport, dport=tcp_dport + 1),
2248 self.RESULT_NOMATCH,
2249 )
2250 testPacket("Missing TCP header, buffer warmed with non-match",
2251 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2252 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2253 self.RESULT_NOMATCH,
2254 )
2255 testPacket("Matching TCP packet, warming buffer",
2256 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2257 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2258 tp(sport=tcp_sport, dport=tcp_dport),
2259 self.RESULT_MATCH,
2260 )
2261 testPacket("Missing TCP header, buffer warmed with match",
2262 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2263 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2264 self.RESULT_NOMATCH,
2265 )
2266 testPacket("Truncated TCP header: 2 bytes",
2267 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2268 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2269 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:2]),
2270 self.RESULT_NOMATCH,
2271 )
2272
2273 # Play with IP header length values that put the start of TCP either
2274 # inside the generated TCP header or beyond. In some cases it may even
2275 # be beyond the packet boundary. Also play with IP options and more
2276 # importantly IP total length corruptions.
2277 testPacket("TCP packet, corrupt ihl (0x6)",
2278 simple_tcp_packet(ip_ihl=6),
2279 self.RESULT_NOMATCH,
2280 )
2281 testPacket("TCP packet, corrupt ihl (0xf)",
2282 simple_tcp_packet(ip_ihl=0xf), # ihl = 15 * 4 = 60
2283 self.RESULT_NOMATCH,
2284 )
2285 testPacket("TCP packet, corrupt ihl and total length",
2286 simple_tcp_packet(ip_ihl=0xf, pktlen=56), # ihl = 15 * 4 = 60,
2287 self.RESULT_NOMATCH,
2288 )
2289 testPacket("Corrupt IPoption: First 4 bytes of matching TCP header",
2290 simple_tcp_packet(
2291 ip_options=scapy.IPOption('\x04\xd2\x00\x50'),
2292 tcp_dport=2, tcp_sport=2
2293 ),
2294 self.RESULT_NOMATCH,
2295 )
2296 testPacket("Missing TCP header, corrupt ihl",
2297 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2298 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto),
2299 self.RESULT_NOMATCH,
2300 )
2301 testPacket("Missing TCP header, corrupt total length",
2302 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2303 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, len= 100),
2304 self.RESULT_NOMATCH,
2305 )
2306 testPacket("Missing TCP header, corrupt ihl and total length",
2307 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2308 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto, len=43),
2309 self.RESULT_NOMATCH,
2310 )
2311 testPacket("Incomplete IP header (12 bytes), corrupt ihl and total length",
2312 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2313 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:12],
2314 self.RESULT_NOMATCH,
2315 )
2316 testPacket("Incomplete IP header (16 bytes), corrupt ihl and total length",
2317 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2318 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:16],
2319 self.RESULT_NOMATCH,
2320 )
2321
2322 # Try an incomplete TCP header that has enough bytes to carry source and
2323 # destination ports. As that is all we care about during matching, some
2324 # implementations may match and some may drop the packet
2325 testPacket("Incomplete TCP header: src/dst port present",
2326 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2327 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2328 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:4]),
2329 self.RESULT_ANY,
2330 )
2331
2332 for i in range(1):
2333 for length in range(40 / 4): # IPv4 options are a maximum of 40 in length
2334 bytes = "".join([("%c" % random.randint(0, 255)) for x in range(length * 4)])
2335 eth = scapy.Ether(dst=dl_dst, src=dl_src)
2336 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2337 tcp = tp(sport=tcp_sport, dport=tcp_dport+1)
2338 pkt = eth / ip
2339 pkt = pkt / bytes
2340 pkt = pkt / str(tcp)
2341 testPacket("Random IP options len = %d - TP match must fail" % length * 4,
2342 pkt,
2343 self.RESULT_NOMATCH
2344 )
2345
2346 eth = scapy.Ether(dst=dl_dst, src=dl_src)
2347 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2348 tcp = tp(sport=tcp_sport, dport=tcp_dport)
2349 pkt = eth / ip
2350 pkt = pkt / bytes
2351 pkt = pkt / str(tcp)
2352
2353 testPacket("Random IP options len = %d - May match",
2354 pkt,
2355 self.RESULT_ANY
2356 )
2357
2358
2359class DirectBadIpTcpPackets(DirectBadIpTcpPacketsBase):
2360 """
2361 Verify IP/TCP parsing and matching. Focus on packet corruptions
2362 """
2363 def runTest(self):
2364 self.runTestWithProto(protoName = 'TCP')
2365
2366class DirectBadIpUdpPackets(DirectBadIpTcpPacketsBase):
2367 """
2368 Verify IP/UDP parsing and matching. Focus on packet corruptions
2369 """
2370 def runTest(self):
2371 self.runTestWithProto(protoName = 'UDP')
2372
2373class DirectBadLlcPackets(DirectBadPacketBase):
2374 """
2375 Verify LLC/SNAP parsing and matching. Focus on packet corruptions
2376 """
2377 def runTest(self):
2378 dl_dst='00:01:02:03:04:05'
2379 dl_src='00:06:07:08:09:0a'
2380 ip_src='192.168.0.1'
2381 ip_dst='192.168.0.2'
2382 ip_tos=0
2383 tcp_sport=1234
2384 tcp_dport=80
2385
2386 IS_SNAP_IP = 1
2387 IS_SNAP_IP_CORRUPT = 2
2388 IS_NOT_SNAP_IP = 3
2389
2390 def testPacketTcpMatch(title, llc):
2391 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
2392 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2393 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
2394 match = packet_to_flow_match(self, match_pkt)
2395 self.assertTrue(match is not None,
2396 "Could not generate flow match from pkt")
2397 match.wildcards &= ~ofp.OFPFW_IN_PORT
2398 act = action.action_output()
2399
2400 self.testPktsAgainstFlow(
2401 [[
2402 "TCP match - LLC frame correct length - %s" % title,
2403 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2404 self.RESULT_ANY,
2405 ]],
2406 act, match
2407 )
2408
2409 # Corrupt length field
2410 ethLen = random.randint(0, 1535)
2411 self.testPktsAgainstFlow(
2412 [[
2413 "TCP match - LLC frame corrupted length - %s" % title,
2414 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
2415 self.RESULT_ANY,
2416 ]],
2417 act, match
2418 )
2419
2420 def testPacketEthSrcDstMatch(title, llc):
2421 # Matching based on Ethernet source and destination
2422 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)
2423 match = packet_to_flow_match(self, match_pkt)
2424 self.assertTrue(match is not None,
2425 "Could not generate flow match from pkt")
2426 match.wildcards &= ~ofp.OFPFW_IN_PORT
2427 match.wildcards |= ofp.OFPFW_DL_TYPE
2428 self.testPktsAgainstFlow(
2429 [[
2430 "Eth addr match - LLC frame correct length- %s" % title,
2431 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2432 self.RESULT_MATCH,
2433 ]],
2434 action.action_output(), match
2435 )
2436
2437 # Corrupt length field
2438 ethLen = random.randint(0, 1535)
2439 self.testPktsAgainstFlow(
2440 [[
2441 "Eth addr match - LLC frame corrupted length- %s" % title,
2442 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
2443 self.RESULT_ANY,
2444 ]],
2445 action.action_output(), match
2446 )
2447
2448 def testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip):
2449 # Matching based on Ethernet source, destination and type
2450 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src, type=0x800)
2451 match = packet_to_flow_match(self, match_pkt)
2452 self.assertTrue(match is not None,
2453 "Could not generate flow match from pkt")
2454 match.wildcards &= ~ofp.OFPFW_IN_PORT
2455 if is_snap_ip == IS_SNAP_IP:
2456 is_match = self.RESULT_MATCH
2457 elif is_snap_ip == IS_SNAP_IP_CORRUPT:
2458 is_match = self.RESULT_ANY
2459 else:
2460 is_match = self.RESULT_NOMATCH
2461 self.testPktsAgainstFlow(
2462 [[
2463 "Eth addr+type match - LLC frame correct length - %s" % title,
2464 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2465 is_match,
2466 ]],
2467 action.action_output(), match
2468 )
2469
2470 # Corrupt length field
2471 ethLen = random.randint(0, 1535)
2472 self.testPktsAgainstFlow(
2473 [[
2474 "Eth addr+type match - LLC frame corrupted length - %s" % title,
2475 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
Christian Dickmanne9b6d252012-10-08 22:56:50 -07002476 self.RESULT_ANY,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002477 ]],
2478 action.action_output(), match
2479 )
2480
2481 def testPacket(title, llc, is_snap_ip):
2482 testPacketTcpMatch(title, llc)
2483 testPacketEthSrcDstMatch(title, llc)
2484 testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip)
2485
2486 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002487 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002488 IS_NOT_SNAP_IP,
2489 )
2490 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002491 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002492 IS_NOT_SNAP_IP,
2493 )
2494 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002495 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002496 IS_NOT_SNAP_IP,
2497 )
2498 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002499 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002500 IS_NOT_SNAP_IP,
2501 )
2502 testPacket("LLC - SNAP - Small bogus payload",
2503 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2504 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2505 IS_SNAP_IP_CORRUPT,
2506 )
2507 testPacket("LLC - SNAP - Max -1 bogus payload",
2508 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2509 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2510 IS_NOT_SNAP_IP,
2511 )
2512 testPacket("LLC - SNAP - Max bogus payload",
2513 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2514 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2515 IS_NOT_SNAP_IP,
2516 )
2517 testPacket("LLC - SNAP - IP - TCP",
2518 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2519 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2520 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2521 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2522 IS_SNAP_IP,
2523 )
2524
2525
2526class DirectLlcPackets(DirectBadPacketBase):
2527 """
2528 Verify LLC/SNAP parsing (valid and corrupted packets) and matching
2529 """
2530 def runTest(self):
2531 dl_dst='00:01:02:03:04:05'
2532 dl_src='00:06:07:08:09:0a'
2533 ip_src='192.168.0.1'
2534 ip_dst='192.168.0.2'
2535 ip_tos=0
2536 tcp_sport=1234
2537 tcp_dport=80
2538
2539 # Test ethertype in face of LLC/SNAP and OFP_DL_TYPE_NOT_ETH_TYPE
2540 IS_SNAP_NOT_IP = 1
2541 IS_SNAP_AND_IP = 2
2542 IS_NOT_SNAP = 3
2543
2544 def testPacketEthTypeIP(title, llc, is_snap):
2545 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src, type=0x800)
2546 match = packet_to_flow_match(self, match_pkt)
2547 self.assertTrue(match is not None,
2548 "Could not generate flow match from pkt")
2549 match.wildcards &= ~ofp.OFPFW_IN_PORT
2550 pkts = []
2551 if is_snap == IS_NOT_SNAP or is_snap == IS_SNAP_NOT_IP:
2552 result = self.RESULT_NOMATCH
2553 else:
2554 result = self.RESULT_MATCH
2555 pkts.append([
2556 "Ether type 0x800 match - %s" % title,
2557 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2558 result,
2559 ])
2560 act = action.action_output()
2561 self.testPktsAgainstFlow(pkts, act, match)
2562
2563 def testPacketEthTypeNotEth(title, llc, is_snap):
2564 match_pkt = scapy.Ether(dst = dl_dst, src = dl_src,
2565 type = ofp.OFP_DL_TYPE_NOT_ETH_TYPE)
2566 match = packet_to_flow_match(self, match_pkt)
2567 self.assertTrue(match is not None,
2568 "Could not generate flow match from pkt")
2569 match.wildcards &= ~ofp.OFPFW_IN_PORT
2570 pkts = []
2571 if is_snap == IS_NOT_SNAP:
2572 result = self.RESULT_MATCH
2573 else:
2574 result = self.RESULT_NOMATCH
2575 pkts.append([
2576 "Ether type OFP_DL_TYPE_NOT_ETH_TYPE match - %s" % title,
2577 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2578 result,
2579 ])
2580 act = action.action_output()
2581 self.testPktsAgainstFlow(pkts, act, match)
2582
2583 def testPacket(title, llc, is_snap):
2584 testPacketEthTypeIP(title, llc, is_snap)
2585 testPacketEthTypeNotEth(title, llc, is_snap)
2586
2587 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002588 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
2589 IS_NOT_SNAP,
2590 )
2591 testPacket("LLC (with information field) - No SNAP - No Payload",
2592 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x12) / "S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002593 IS_NOT_SNAP,
2594 )
2595 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002596 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002597 IS_NOT_SNAP,
2598 )
2599 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002600 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002601 IS_NOT_SNAP,
2602 )
2603 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002604 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002605 IS_NOT_SNAP,
2606 )
2607 testPacket("LLC - SNAP - Non-default OUI",
2608 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2609 scapy.SNAP(OUI=0x000001, code=0x800) / ("S" * 10),
2610 IS_NOT_SNAP,
2611 )
2612 testPacket("LLC - SNAP - Default OUI",
2613 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2614 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2615 IS_SNAP_AND_IP,
2616 )
2617 testPacket("LLC - SNAP - Max -1 bogus payload",
2618 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2619 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2620 IS_SNAP_NOT_IP,
2621 )
2622 testPacket("LLC - SNAP - Max bogus payload",
2623 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2624 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2625 IS_SNAP_NOT_IP,
2626 )
2627 testPacket("LLC - SNAP - IP - TCP",
2628 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2629 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2630 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2631 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2632 IS_SNAP_AND_IP,
2633 )
2634
2635
2636class DirectArpPackets(DirectBadPacketBase):
2637 """
2638 Verify ARP parsing (valid and corrupted packets) and ARP matching
2639 """
2640 def runTest(self):
2641 self.testArpHandling()
2642
2643 def testArpHandling(self):
2644 dl_dst='00:01:02:03:04:05'
2645 dl_src='00:06:07:08:09:0a'
2646 ip_src='192.168.0.1'
2647 ip_dst='192.168.0.2'
2648 ip_src2='192.168.1.1'
2649 ip_dst2='192.168.1.2'
2650 ip_tos=0
2651 tcp_sport=1234
2652 tcp_dport=80
2653
2654 def testPacket(title, arp_match, arp_pkt, result):
2655 pkts = []
2656
2657 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src) / arp_match
2658 match = packet_to_flow_match(self, match_pkt)
2659 self.assertTrue(match is not None,
2660 "Could not generate flow match from pkt")
2661 match.wildcards &= ~ofp.OFPFW_IN_PORT
2662
2663 pkts.append([
2664 title,
2665 scapy.Ether(dst=dl_dst, src=dl_src) / arp_pkt,
2666 result,
2667 ])
2668
2669 act = action.action_output()
2670 self.testPktsAgainstFlow(pkts, act, match)
2671
2672 testPacket("Basic ARP",
2673 scapy.ARP(psrc=ip_src, pdst=ip_dst, op = 1),
2674 scapy.ARP(hwdst = '00:00:00:00:00:00', hwsrc = dl_src,
2675 psrc = ip_src, pdst = ip_dst, hwlen = 6, plen = 4,
2676 ptype = 0x800, hwtype = 1, op = 1),
2677 self.RESULT_MATCH
2678 )
2679 # More stuff:
2680 # - Non matches on any property
2681 # - Corrupted hwlen and plen
2682 # - Other hwtype, ptype
2683 # - Truncated ARP pkt
2684
2685
2686class DirectVlanPackets(DirectBadPacketBase):
2687 """
2688 Verify VLAN parsing (valid and corrupted packets) and ARP matching
2689 """
2690 def runTest(self):
2691 dl_dst='00:01:02:03:04:05'
2692 dl_src='00:06:07:08:09:0a'
2693 ip_src='192.168.0.1'
2694 ip_dst='192.168.0.2'
2695 ip_src2='192.168.1.1'
2696 ip_dst2='192.168.1.2'
2697 ip_tos=0
2698 tcp_sport=1234
2699 tcp_dport=80
2700
2701 def testPacket(title, match, pkt, result):
2702 pkts = []
2703
2704 self.assertTrue(match is not None,
2705 "Could not generate flow match from pkt")
2706 match.wildcards &= ~ofp.OFPFW_IN_PORT
2707
2708 pkts.append([
2709 "%s" % title,
2710 pkt,
2711 result,
2712 ])
2713
2714 act = action.action_output()
2715 self.testPktsAgainstFlow(pkts, act, match)
2716
2717 testPacket("Basic MAC matching - IPv4 payload",
2718 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2719 scapy.Ether(dst=dl_dst, src=dl_src, type=0x800) / scapy.IP(),
2720 self.RESULT_MATCH
2721 )
2722 testPacket("Basic MAC matching - VMware beacon - no payload",
2723 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2724 scapy.Ether(dst=dl_dst, src=dl_src, type=0x8922),
2725 self.RESULT_MATCH
2726 )
2727 testPacket("Basic MAC matching - VMware beacon - with payload",
2728 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2729 scapy.Ether(dst=dl_dst, src=dl_src, type=0x8922)/ ("X" * 1),
2730 self.RESULT_MATCH
2731 )
2732 testPacket("Basic MAC matching - IPv6 payload",
2733 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2734 scapy.Ether(dst=dl_dst, src=dl_src) / scapy.IPv6(),
2735 self.RESULT_MATCH
2736 )
2737 testPacket("Basic MAC matching with VLAN tag present",
2738 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2739 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002740 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002741 scapy.IP(),
2742 self.RESULT_MATCH
2743 )
2744 testPacket("Basic MAC matching with VLAN tag present",
2745 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2746 dl_type=0x800),
2747 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002748 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002749 scapy.IP(),
2750 self.RESULT_MATCH
2751 )
2752 testPacket("Ether matching with VLAN tag present - No type match",
2753 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2754 dl_type=0x801),
2755 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002756 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002757 scapy.IP(),
2758 self.RESULT_NOMATCH
2759 )
2760 testPacket("Ether matching with VLAN tag present - No type match 0x8100",
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)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002765 scapy.IP(),
2766 self.RESULT_NOMATCH
2767 )
2768 testPacket("Ether matching with double VLAN tag - Wrong type match",
2769 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2770 dl_type=0x800),
2771 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002772 scapy.Dot1Q(prio=5, vlan=1000)/ \
2773 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002774 scapy.IP(),
2775 self.RESULT_NOMATCH
2776 )
2777 testPacket("Ether matching with double VLAN tag - Type match",
2778 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2779 dl_type=0x8100),
2780 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002781 scapy.Dot1Q(prio=5, vlan=1000)/ \
2782 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002783 scapy.IP(),
2784 self.RESULT_MATCH
2785 )
2786 testPacket("IP matching - VLAN tag",
2787 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2788 dl_type=0x0800,
2789 nw_src=parse_ip(ip_src), nw_dst=parse_ip(ip_dst)),
2790 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002791 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002792 scapy.IP(src=ip_src, dst=ip_dst),
2793 self.RESULT_MATCH
2794 )
2795 # XXX:
2796 # - Matching on VLAN ID and Prio
2797 # - Actions
2798
2799
2800
Dan Talayco9f47f4d2010-06-03 13:54:37 -07002801if __name__ == "__main__":
2802 print "Please run through oft script: ./oft --test_spec=basic"