blob: 0165597545b65292ff46bddff697cf7bb63d556c [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 Lane97e99652013-01-02 17:23:20 -080081@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -070082class DirectPacket(base_tests.SimpleDataPlane):
Dan Talayco5eba8442010-03-10 13:58:43 -080083 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -070084 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -080085
86 Generate a packet
87 Generate and install a matching flow
88 Add action to direct the packet to an egress port
89 Send the packet to ingress dataplane port
90 Verify the packet is received at the egress port only
91 """
92 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -070093 self.handleFlow()
94
95 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -070096 of_ports = config["port_map"].keys()
Dan Talayco5eba8442010-03-10 13:58:43 -080097 of_ports.sort()
98 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
99
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700100 if (pkttype == 'ICMP'):
101 pkt = simple_icmp_packet()
102 else:
103 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700104 match = packet_to_flow_match(self, pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700105 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800106 self.assertTrue(match is not None,
107 "Could not generate flow match from pkt")
108 act = action.action_output()
109
110 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700111 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700112 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700113
Dan Talayco5eba8442010-03-10 13:58:43 -0800114 ingress_port = of_ports[idx]
115 egress_port = of_ports[(idx + 1) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700116 logging.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700117 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800118
119 match.in_port = ingress_port
120
121 request = message.flow_mod()
122 request.match = match
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700123
Dan Talayco5eba8442010-03-10 13:58:43 -0800124 request.buffer_id = 0xffffffff
125 act.port = egress_port
126 self.assertTrue(request.actions.add(act), "Could not add action")
127
Rich Lane9a003812012-10-04 17:17:59 -0700128 logging.info("Inserting flow")
Dan Talayco5eba8442010-03-10 13:58:43 -0800129 rv = self.controller.message_send(request)
130 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700131 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco5eba8442010-03-10 13:58:43 -0800132
Rich Lane9a003812012-10-04 17:17:59 -0700133 logging.info("Sending packet to dp port " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800134 str(ingress_port))
135 self.dataplane.send(ingress_port, str(pkt))
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700136
137 exp_pkt_arg = None
138 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700139 if config["relax"]:
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700140 exp_pkt_arg = pkt
141 exp_port = egress_port
142
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700143 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Dan Talaycocf26b7a2011-08-05 10:15:35 -0700144 exp_pkt=exp_pkt_arg)
Dan Talayco5eba8442010-03-10 13:58:43 -0800145 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700146 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800147 str(rcv_port))
148 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
149 self.assertEqual(str(pkt), str(rcv_pkt),
150 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700151
Rich Lane97e99652013-01-02 17:23:20 -0800152@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -0700153class DirectPacketController(base_tests.SimpleDataPlane):
Rich Lane51c23b32012-07-27 16:37:25 -0700154 """
155 Send packet to the controller port
156
157 Generate a packet
158 Generate and install a matching flow
159 Add action to direct the packet to the controller port
160 Send the packet to ingress dataplane port
161 Verify the packet is received at the controller port
162 """
163 def runTest(self):
164 self.handleFlow()
165
166 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700167 of_ports = config["port_map"].keys()
Rich Lane51c23b32012-07-27 16:37:25 -0700168 of_ports.sort()
169 self.assertTrue(len(of_ports) > 0, "Not enough ports for test")
170
171 if (pkttype == 'ICMP'):
172 pkt = simple_icmp_packet()
173 else:
174 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700175 match = packet_to_flow_match(self, pkt)
Rich Lane51c23b32012-07-27 16:37:25 -0700176 match.wildcards &= ~ofp.OFPFW_IN_PORT
177 self.assertTrue(match is not None,
178 "Could not generate flow match from pkt")
179 act = action.action_output()
180
Rich Lane9a003812012-10-04 17:17:59 -0700181 rv = delete_all_flows(self.controller)
Rich Lane51c23b32012-07-27 16:37:25 -0700182 self.assertEqual(rv, 0, "Failed to delete all flows")
183
184 ingress_port = of_ports[0]
185 match.in_port = ingress_port
186
187 request = message.flow_mod()
188 request.match = match
189
190 request.buffer_id = 0xffffffff
191 act.port = ofp.OFPP_CONTROLLER
192 act.max_len = 65535
193 self.assertTrue(request.actions.add(act), "Could not add action")
194
Rich Lane9a003812012-10-04 17:17:59 -0700195 logging.info("Inserting flow")
Rich Lane51c23b32012-07-27 16:37:25 -0700196 rv = self.controller.message_send(request)
197 self.assertTrue(rv != -1, "Error installing flow mod")
198 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
199
Rich Lane9a003812012-10-04 17:17:59 -0700200 logging.info("Sending packet to dp port " +
Rich Lane51c23b32012-07-27 16:37:25 -0700201 str(ingress_port))
202 self.dataplane.send(ingress_port, str(pkt))
203
204 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
205
206 self.assertTrue(response is not None,
207 'Packet in message not received by controller')
208 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700209 logging.debug("Sent %s" % format_packet(pkt))
210 logging.debug("Resp %s" % format_packet(response.data))
Rich Lane51c23b32012-07-27 16:37:25 -0700211 self.assertTrue(False,
212 'Response packet does not match send packet' +
213 ' for controller port')
214
Howard Pershf97840f2012-04-10 16:30:42 -0700215
Rich Laneb90a1c42012-10-05 09:16:05 -0700216class DirectPacketQueue(base_tests.SimpleDataPlane):
Howard Pershf97840f2012-04-10 16:30:42 -0700217 """
218 Send packet to single queue on single egress port
219
220 Generate a packet
221 Generate and install a matching flow
222 Add action to direct the packet to an egress port and queue
223 Send the packet to ingress dataplane port
224 Verify the packet is received at the egress port only
225 """
226 def runTest(self):
227 self.handleFlow()
228
Howard Persh670b5672012-04-13 09:08:29 -0700229 def portQueuesGet(self, queue_stats, port_num):
230 result = []
231 for qs in queue_stats.stats:
232 if qs.port_no != port_num:
233 continue
234 result.append(qs.queue_id)
235 return result
236
Howard Pershf97840f2012-04-10 16:30:42 -0700237 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700238 of_ports = config["port_map"].keys()
Howard Pershf97840f2012-04-10 16:30:42 -0700239 of_ports.sort()
240 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
241
242 if (pkttype == 'ICMP'):
243 pkt = simple_icmp_packet()
244 else:
245 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700246 match = packet_to_flow_match(self, pkt)
Howard Pershf97840f2012-04-10 16:30:42 -0700247 match.wildcards &= ~ofp.OFPFW_IN_PORT
248 self.assertTrue(match is not None,
249 "Could not generate flow match from pkt")
250
Howard Persh670b5672012-04-13 09:08:29 -0700251 # Get queue stats from switch
252
253 request = message.queue_stats_request()
254 request.port_no = ofp.OFPP_ALL
255 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700256 (queue_stats, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700257 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
258
259 act = action.action_enqueue()
Howard Pershf97840f2012-04-10 16:30:42 -0700260
261 for idx in range(len(of_ports)):
Howard Pershf97840f2012-04-10 16:30:42 -0700262 ingress_port = of_ports[idx]
263 egress_port = of_ports[(idx + 1) % len(of_ports)]
Howard Pershf97840f2012-04-10 16:30:42 -0700264
Howard Persh670b5672012-04-13 09:08:29 -0700265 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700266 logging.info("Ingress " + str(ingress_port)
Howard Persh670b5672012-04-13 09:08:29 -0700267 + " to egress " + str(egress_port)
268 + " queue " + str(egress_queue_id)
269 )
Howard Pershf97840f2012-04-10 16:30:42 -0700270
Rich Lane9a003812012-10-04 17:17:59 -0700271 rv = delete_all_flows(self.controller)
Howard Persh670b5672012-04-13 09:08:29 -0700272 self.assertEqual(rv, 0, "Failed to delete all flows")
Howard Pershf97840f2012-04-10 16:30:42 -0700273
Howard Persh670b5672012-04-13 09:08:29 -0700274 match.in_port = ingress_port
275
276 request = message.flow_mod()
277 request.match = match
Howard Pershf97840f2012-04-10 16:30:42 -0700278
Howard Persh670b5672012-04-13 09:08:29 -0700279 request.buffer_id = 0xffffffff
280 act.port = egress_port
281 act.queue_id = egress_queue_id
282 self.assertTrue(request.actions.add(act), "Could not add action")
Howard Pershf97840f2012-04-10 16:30:42 -0700283
Rich Lane9a003812012-10-04 17:17:59 -0700284 logging.info("Inserting flow")
Howard Persh670b5672012-04-13 09:08:29 -0700285 rv = self.controller.message_send(request)
286 self.assertTrue(rv != -1, "Error installing flow mod")
287 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Howard Pershf97840f2012-04-10 16:30:42 -0700288
Howard Persh670b5672012-04-13 09:08:29 -0700289 # Get current stats for selected egress queue
Howard Pershf97840f2012-04-10 16:30:42 -0700290
Howard Persh670b5672012-04-13 09:08:29 -0700291 request = message.queue_stats_request()
292 request.port_no = egress_port
293 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700294 (qs_before, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700295 self.assertNotEqual(qs_before, None, "Queue stats request failed")
296
Rich Lane9a003812012-10-04 17:17:59 -0700297 logging.info("Sending packet to dp port " +
Howard Persh670b5672012-04-13 09:08:29 -0700298 str(ingress_port))
299 self.dataplane.send(ingress_port, str(pkt))
300
301 exp_pkt_arg = None
302 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -0700303 if config["relax"]:
Howard Persh670b5672012-04-13 09:08:29 -0700304 exp_pkt_arg = pkt
305 exp_port = egress_port
306
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700307 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
Howard Persh670b5672012-04-13 09:08:29 -0700308 exp_pkt=exp_pkt_arg)
309 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -0700310 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Howard Persh670b5672012-04-13 09:08:29 -0700311 str(rcv_port))
312 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
313 self.assertEqual(str(pkt), str(rcv_pkt),
314 'Response packet does not match send packet')
315
Ed Swierkb8a86512012-04-18 18:45:58 -0700316 # FIXME: instead of sleeping, keep requesting queue stats until
317 # the expected queue counter increases or some large timeout is
318 # reached
319 time.sleep(2)
320
Howard Persh670b5672012-04-13 09:08:29 -0700321 # Get current stats for selected egress queue again
322
323 request = message.queue_stats_request()
324 request.port_no = egress_port
325 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700326 (qs_after, p) = self.controller.transact(request)
Howard Persh670b5672012-04-13 09:08:29 -0700327 self.assertNotEqual(qs_after, None, "Queue stats request failed")
328
329 # Make sure that tx packet counter for selected egress queue was
330 # incremented
331
Ed Swierk22f59152012-04-17 16:36:47 -0700332 self.assertEqual(qs_after.stats[0].tx_packets, \
333 qs_before.stats[0].tx_packets + 1, \
Howard Persh670b5672012-04-13 09:08:29 -0700334 "Verification of egress queue tx packet count failed"
335 )
336
337
Rich Laneb90a1c42012-10-05 09:16:05 -0700338class DirectPacketControllerQueue(base_tests.SimpleDataPlane):
Ken Chiang899ff8e2012-05-23 18:26:12 -0700339 """
340 Send a packet from each of the openflow ports
341 to each of the queues configured on the controller port.
342 If no queues have been configured, no packets are sent.
Howard Pershf97840f2012-04-10 16:30:42 -0700343
Ken Chiang899ff8e2012-05-23 18:26:12 -0700344 Generate a packet
345 Generate and install a matching flow
346 Add action to direct the packet to one of the controller port queues
347 Send the packet to ingress dataplane port
348 Verify the packet is received on the controller port queue
349 """
350 def runTest(self):
351 self.handleFlow()
352
353 def portQueuesGet(self, queue_stats, port_num):
354 result = []
355 for qs in queue_stats.stats:
356 if qs.port_no != port_num:
357 continue
358 result.append(qs.queue_id)
359 return result
360
361 def handleFlow(self, pkttype='TCP'):
Rich Lane477f4812012-10-04 22:49:00 -0700362 of_ports = config["port_map"].keys()
Ken Chiang899ff8e2012-05-23 18:26:12 -0700363 of_ports.sort()
364 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
365
366 if (pkttype == 'ICMP'):
367 pkt = simple_icmp_packet()
368 else:
369 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700370 match = packet_to_flow_match(self, pkt)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700371 match.wildcards &= ~ofp.OFPFW_IN_PORT
372 self.assertTrue(match is not None,
373 "Could not generate flow match from pkt")
374
375 # Get queue stats from switch
376
377 request = message.queue_stats_request()
378 request.port_no = ofp.OFPP_CONTROLLER
379 request.queue_id = ofp.OFPQ_ALL
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700380 (queue_stats, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700381 self.assertNotEqual(queue_stats, None, "Queue stats request failed")
Rich Laneb8c845a2012-12-31 17:23:51 -0800382 if queue_stats.header.type == ofp.OFPT_ERROR:
383 skip_message_emit(self, "Enqueue packet to controller")
384 return
Ken Chiang899ff8e2012-05-23 18:26:12 -0700385
386 act = action.action_enqueue()
387
388 for idx in range(len(of_ports)):
389 ingress_port = of_ports[idx]
390 egress_port = ofp.OFPP_CONTROLLER
391
Rich Lane9a003812012-10-04 17:17:59 -0700392 logging.info("Ingress port " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700393 + ", controller port queues "
394 + str(self.portQueuesGet(queue_stats, egress_port)))
395
396 for egress_queue_id in self.portQueuesGet(queue_stats, egress_port):
Rich Lane9a003812012-10-04 17:17:59 -0700397 logging.info("Ingress " + str(ingress_port)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700398 + " to egress " + str(egress_port)
399 + " queue " + str(egress_queue_id)
400 )
401
Rich Lane9a003812012-10-04 17:17:59 -0700402 rv = delete_all_flows(self.controller)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700403 self.assertEqual(rv, 0, "Failed to delete all flows")
404
405 match.in_port = ingress_port
406
407 request = message.flow_mod()
408 request.match = match
409
410 request.buffer_id = 0xffffffff
411 act.port = egress_port
412 act.queue_id = egress_queue_id
413 self.assertTrue(request.actions.add(act), "Could not add action")
414
Rich Lane9a003812012-10-04 17:17:59 -0700415 logging.info("Inserting flow")
Ken Chiang899ff8e2012-05-23 18:26:12 -0700416 rv = self.controller.message_send(request)
417 self.assertTrue(rv != -1, "Error installing flow mod")
418 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
419
420 # Get current stats for selected egress queue
421
422 request = message.queue_stats_request()
423 request.port_no = egress_port
424 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700425 (qs_before, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700426 self.assertNotEqual(qs_before, None, "Queue stats request failed")
427
Rich Lane9a003812012-10-04 17:17:59 -0700428 logging.info("Sending packet to dp port " +
Ken Chiang899ff8e2012-05-23 18:26:12 -0700429 str(ingress_port))
430 self.dataplane.send(ingress_port, str(pkt))
431
432 exp_pkt_arg = None
433 exp_port = None
434
Rich Lanee5779d32012-10-05 17:56:04 -0700435 count = 0
Ken Chiang899ff8e2012-05-23 18:26:12 -0700436 while True:
Dan Talaycoc689a792012-09-28 14:22:53 -0700437 (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700438 if not response: # Timeout
439 break
440 if dataplane.match_exp_pkt(pkt, response.data): # Got match
441 break
Rich Lane477f4812012-10-04 22:49:00 -0700442 if not config["relax"]: # Only one attempt to match
Ken Chiang899ff8e2012-05-23 18:26:12 -0700443 break
444 count += 1
445 if count > 10: # Too many tries
446 break
447
448 self.assertTrue(response is not None,
449 'Packet in message not received by controller')
450 if not dataplane.match_exp_pkt(pkt, response.data):
Rich Lane9a003812012-10-04 17:17:59 -0700451 logging.debug("Sent %s" % format_packet(pkt))
452 logging.debug("Resp %s" % format_packet(response.data))
Ken Chiang899ff8e2012-05-23 18:26:12 -0700453 self.assertTrue(False,
454 'Response packet does not match send packet' +
455 ' for controller port')
456
457 # FIXME: instead of sleeping, keep requesting queue stats until
458 # the expected queue counter increases or some large timeout is
459 # reached
460 time.sleep(2)
461
462 # Get current stats for selected egress queue again
463
464 request = message.queue_stats_request()
465 request.port_no = egress_port
466 request.queue_id = egress_queue_id
Rich Lanec8aaa3e2012-07-26 19:28:02 -0700467 (qs_after, p) = self.controller.transact(request)
Ken Chiang899ff8e2012-05-23 18:26:12 -0700468 self.assertNotEqual(qs_after, None, "Queue stats request failed")
469
470 # Make sure that tx packet counter for selected egress queue was
471 # incremented
472
473 self.assertEqual(qs_after.stats[0].tx_packets, \
474 qs_before.stats[0].tx_packets + 1, \
475 "Verification of egress queue tx packet count failed"
476 )
477
Howard Pershf97840f2012-04-10 16:30:42 -0700478
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700479class DirectPacketICMP(DirectPacket):
480 """
481 Send ICMP packet to single egress port
482
483 Generate a ICMP packet
484 Generate and install a matching flow
485 Add action to direct the packet to an egress port
486 Send the packet to ingress dataplane port
487 Verify the packet is received at the egress port only
488 Difference from DirectPacket test is that sent packet is ICMP
489 """
490 def runTest(self):
491 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700492
Rich Laneb90a1c42012-10-05 09:16:05 -0700493class DirectTwoPorts(base_tests.SimpleDataPlane):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700494 """
495 Send packet to two egress ports
496
497 Generate a packet
498 Generate and install a matching flow
499 Add action to direct the packet to two egress ports
500 Send the packet to ingress dataplane port
501 Verify the packet is received at the two egress ports
502 """
503 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700504 of_ports = config["port_map"].keys()
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700505 of_ports.sort()
506 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
507
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700508 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700509 match = packet_to_flow_match(self, pkt)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700510 match.wildcards &= ~ofp.OFPFW_IN_PORT
511 self.assertTrue(match is not None,
512 "Could not generate flow match from pkt")
513 act = action.action_output()
514
515 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700516 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700517 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700518
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700519 ingress_port = of_ports[idx]
520 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
521 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
Rich Lane9a003812012-10-04 17:17:59 -0700522 logging.info("Ingress " + str(ingress_port) +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700523 " to egress " + str(egress_port1) + " and " +
524 str(egress_port2))
525
526 match.in_port = ingress_port
527
528 request = message.flow_mod()
529 request.match = match
530 request.buffer_id = 0xffffffff
531 act.port = egress_port1
532 self.assertTrue(request.actions.add(act), "Could not add action1")
533 act.port = egress_port2
534 self.assertTrue(request.actions.add(act), "Could not add action2")
Rich Lane9a003812012-10-04 17:17:59 -0700535 # logging.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700536
Rich Lane9a003812012-10-04 17:17:59 -0700537 logging.info("Inserting flow")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700538 rv = self.controller.message_send(request)
539 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700540 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700541
Rich Lane9a003812012-10-04 17:17:59 -0700542 logging.info("Sending packet to dp port " +
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700543 str(ingress_port))
544 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700545 yes_ports = set([egress_port1, egress_port2])
546 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700547
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700548 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
Rich Lane2014f9b2012-10-05 15:29:40 -0700549 self)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700550
Rich Laneb90a1c42012-10-05 09:16:05 -0700551class DirectMCNonIngress(base_tests.SimpleDataPlane):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700552 """
553 Multicast to all non-ingress ports
554
555 Generate a packet
556 Generate and install a matching flow
557 Add action to direct the packet to all non-ingress ports
558 Send the packet to ingress dataplane port
559 Verify the packet is received at all non-ingress ports
560
561 Does not use the flood action
562 """
563 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700564 of_ports = config["port_map"].keys()
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700565 of_ports.sort()
566 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
567
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700568 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700569 match = packet_to_flow_match(self, pkt)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700570 match.wildcards &= ~ofp.OFPFW_IN_PORT
571 self.assertTrue(match is not None,
572 "Could not generate flow match from pkt")
573 act = action.action_output()
574
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700575 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700576 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700577 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700578
Rich Lane9a003812012-10-04 17:17:59 -0700579 logging.info("Ingress " + str(ingress_port) +
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700580 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700581 match.in_port = ingress_port
582
583 request = message.flow_mod()
584 request.match = match
585 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700586 for egress_port in of_ports:
587 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700588 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700589 act.port = egress_port
590 self.assertTrue(request.actions.add(act),
591 "Could not add output to " + str(egress_port))
Rich Lane9a003812012-10-04 17:17:59 -0700592 logging.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700593
Rich Lane9a003812012-10-04 17:17:59 -0700594 logging.info("Inserting flow")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700595 rv = self.controller.message_send(request)
596 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700597 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700598
Rich Lane9a003812012-10-04 17:17:59 -0700599 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700600 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700601 yes_ports = set(of_ports).difference([ingress_port])
602 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700603 self)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700604
Dan Talayco32fa6542010-05-11 15:54:08 -0700605
Rich Laneb90a1c42012-10-05 09:16:05 -0700606class DirectMC(base_tests.SimpleDataPlane):
Dan Talayco32fa6542010-05-11 15:54:08 -0700607 """
608 Multicast to all ports including ingress
609
610 Generate a packet
611 Generate and install a matching flow
612 Add action to direct the packet to all non-ingress ports
613 Send the packet to ingress dataplane port
614 Verify the packet is received at all ports
615
616 Does not use the flood action
617 """
618 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700619 of_ports = config["port_map"].keys()
Dan Talayco32fa6542010-05-11 15:54:08 -0700620 of_ports.sort()
621 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
622
Dan Talayco32fa6542010-05-11 15:54:08 -0700623 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700624 match = packet_to_flow_match(self, pkt)
Dan Talayco32fa6542010-05-11 15:54:08 -0700625 match.wildcards &= ~ofp.OFPFW_IN_PORT
626 self.assertTrue(match is not None,
627 "Could not generate flow match from pkt")
628 act = action.action_output()
629
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700630 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700631 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700632 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700633
Rich Lane9a003812012-10-04 17:17:59 -0700634 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700635 match.in_port = ingress_port
636
637 request = message.flow_mod()
638 request.match = match
639 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700640 for egress_port in of_ports:
641 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700642 act.port = ofp.OFPP_IN_PORT
643 else:
644 act.port = egress_port
645 self.assertTrue(request.actions.add(act),
646 "Could not add output to " + str(egress_port))
Rich Lane9a003812012-10-04 17:17:59 -0700647 # logging.info(request.show())
Dan Talayco2e77a842010-05-12 15:39:46 -0700648
Rich Lane9a003812012-10-04 17:17:59 -0700649 logging.info("Inserting flow")
Dan Talayco2e77a842010-05-12 15:39:46 -0700650 rv = self.controller.message_send(request)
651 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700652 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco2e77a842010-05-12 15:39:46 -0700653
Rich Lane9a003812012-10-04 17:17:59 -0700654 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700655 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700656 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco2e77a842010-05-12 15:39:46 -0700657
Rich Laneb90a1c42012-10-05 09:16:05 -0700658class Flood(base_tests.SimpleDataPlane):
Dan Talayco2e77a842010-05-12 15:39:46 -0700659 """
660 Flood to all ports except ingress
661
662 Generate a packet
663 Generate and install a matching flow
664 Add action to flood the packet
665 Send the packet to ingress dataplane port
666 Verify the packet is received at all other ports
667 """
668 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700669 of_ports = config["port_map"].keys()
Dan Talayco2e77a842010-05-12 15:39:46 -0700670 of_ports.sort()
671 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
672
673 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700674 match = packet_to_flow_match(self, pkt)
Dan Talayco2e77a842010-05-12 15:39:46 -0700675 match.wildcards &= ~ofp.OFPFW_IN_PORT
676 self.assertTrue(match is not None,
677 "Could not generate flow match from pkt")
678 act = action.action_output()
679
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700680 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700681 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700682 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700683
Rich Lane9a003812012-10-04 17:17:59 -0700684 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700685 match.in_port = ingress_port
686
687 request = message.flow_mod()
688 request.match = match
689 request.buffer_id = 0xffffffff
690 act.port = ofp.OFPP_FLOOD
691 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700692 "Could not add flood port action")
Rich Lane9a003812012-10-04 17:17:59 -0700693 logging.info(request.show())
Dan Talayco32fa6542010-05-11 15:54:08 -0700694
Rich Lane9a003812012-10-04 17:17:59 -0700695 logging.info("Inserting flow")
Dan Talayco32fa6542010-05-11 15:54:08 -0700696 rv = self.controller.message_send(request)
697 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700698 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco32fa6542010-05-11 15:54:08 -0700699
Rich Lane9a003812012-10-04 17:17:59 -0700700 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco32fa6542010-05-11 15:54:08 -0700701 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700702 yes_ports = set(of_ports).difference([ingress_port])
703 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700704 self)
Dan Talayco3be5b062010-05-12 15:46:21 -0700705
Rich Laneb90a1c42012-10-05 09:16:05 -0700706class FloodPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco3be5b062010-05-12 15:46:21 -0700707 """
708 Flood to all ports plus send to ingress port
709
710 Generate a packet
711 Generate and install a matching flow
712 Add action to flood the packet
713 Add action to send to ingress port
714 Send the packet to ingress dataplane port
715 Verify the packet is received at all other ports
716 """
717 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700718 of_ports = config["port_map"].keys()
Dan Talayco3be5b062010-05-12 15:46:21 -0700719 of_ports.sort()
720 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
721
722 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700723 match = packet_to_flow_match(self, pkt)
Dan Talayco3be5b062010-05-12 15:46:21 -0700724 match.wildcards &= ~ofp.OFPFW_IN_PORT
725 self.assertTrue(match is not None,
726 "Could not generate flow match from pkt")
727 act = action.action_output()
728
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700729 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700730 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700731 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700732
Rich Lane9a003812012-10-04 17:17:59 -0700733 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700734 match.in_port = ingress_port
735
736 request = message.flow_mod()
737 request.match = match
738 request.buffer_id = 0xffffffff
739 act.port = ofp.OFPP_FLOOD
740 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700741 "Could not add flood port action")
742 act.port = ofp.OFPP_IN_PORT
743 self.assertTrue(request.actions.add(act),
744 "Could not add ingress port for output")
Rich Lane9a003812012-10-04 17:17:59 -0700745 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700746
Rich Lane9a003812012-10-04 17:17:59 -0700747 logging.info("Inserting flow")
Dan Talayco4aa13122010-05-12 15:54:44 -0700748 rv = self.controller.message_send(request)
749 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700750 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700751
Rich Lane9a003812012-10-04 17:17:59 -0700752 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700753 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700754 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco4aa13122010-05-12 15:54:44 -0700755
Rich Laneb90a1c42012-10-05 09:16:05 -0700756class All(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700757 """
758 Send to OFPP_ALL port
759
760 Generate a packet
761 Generate and install a matching flow
762 Add action to forward to OFPP_ALL
763 Send the packet to ingress dataplane port
764 Verify the packet is received at all other ports
765 """
766 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700767 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700768 of_ports.sort()
769 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
770
771 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700772 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700773 match.wildcards &= ~ofp.OFPFW_IN_PORT
774 self.assertTrue(match is not None,
775 "Could not generate flow match from pkt")
776 act = action.action_output()
777
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700778 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700779 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700780 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700781
Rich Lane9a003812012-10-04 17:17:59 -0700782 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700783 match.in_port = ingress_port
784
785 request = message.flow_mod()
786 request.match = match
787 request.buffer_id = 0xffffffff
788 act.port = ofp.OFPP_ALL
789 self.assertTrue(request.actions.add(act),
790 "Could not add ALL port action")
Rich Lane9a003812012-10-04 17:17:59 -0700791 logging.info(request.show())
Dan Talayco4aa13122010-05-12 15:54:44 -0700792
Rich Lane9a003812012-10-04 17:17:59 -0700793 logging.info("Inserting flow")
Dan Talayco4aa13122010-05-12 15:54:44 -0700794 rv = self.controller.message_send(request)
795 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700796 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco4aa13122010-05-12 15:54:44 -0700797
Rich Lane9a003812012-10-04 17:17:59 -0700798 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco4aa13122010-05-12 15:54:44 -0700799 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700800 yes_ports = set(of_ports).difference([ingress_port])
801 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
Rich Lane2014f9b2012-10-05 15:29:40 -0700802 self)
Dan Talayco4aa13122010-05-12 15:54:44 -0700803
Rich Laneb90a1c42012-10-05 09:16:05 -0700804class AllPlusIngress(base_tests.SimpleDataPlane):
Dan Talayco4aa13122010-05-12 15:54:44 -0700805 """
806 Send to OFPP_ALL port and ingress port
807
808 Generate a packet
809 Generate and install a matching flow
810 Add action to forward to OFPP_ALL
811 Add action to forward to ingress port
812 Send the packet to ingress dataplane port
813 Verify the packet is received at all other ports
814 """
815 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700816 of_ports = config["port_map"].keys()
Dan Talayco4aa13122010-05-12 15:54:44 -0700817 of_ports.sort()
818 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
819
820 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700821 match = packet_to_flow_match(self, pkt)
Dan Talayco4aa13122010-05-12 15:54:44 -0700822 match.wildcards &= ~ofp.OFPFW_IN_PORT
823 self.assertTrue(match is not None,
824 "Could not generate flow match from pkt")
825 act = action.action_output()
826
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700827 for ingress_port in of_ports:
Rich Lane9a003812012-10-04 17:17:59 -0700828 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700829 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700830
Rich Lane9a003812012-10-04 17:17:59 -0700831 logging.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700832 match.in_port = ingress_port
833
834 request = message.flow_mod()
835 request.match = match
836 request.buffer_id = 0xffffffff
837 act.port = ofp.OFPP_ALL
838 self.assertTrue(request.actions.add(act),
839 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700840 act.port = ofp.OFPP_IN_PORT
841 self.assertTrue(request.actions.add(act),
842 "Could not add ingress port for output")
Rich Lane9a003812012-10-04 17:17:59 -0700843 logging.info(request.show())
Dan Talayco3be5b062010-05-12 15:46:21 -0700844
Rich Lane9a003812012-10-04 17:17:59 -0700845 logging.info("Inserting flow")
Dan Talayco3be5b062010-05-12 15:46:21 -0700846 rv = self.controller.message_send(request)
847 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700848 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco3be5b062010-05-12 15:46:21 -0700849
Rich Lane9a003812012-10-04 17:17:59 -0700850 logging.info("Sending packet to dp port " + str(ingress_port))
Dan Talayco3be5b062010-05-12 15:46:21 -0700851 self.dataplane.send(ingress_port, str(pkt))
Rich Lane2014f9b2012-10-05 15:29:40 -0700852 receive_pkt_check(self.dataplane, pkt, of_ports, [], self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700853
Rich Laneb90a1c42012-10-05 09:16:05 -0700854class FloodMinusPort(base_tests.SimpleDataPlane):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700855 """
856 Config port with No_Flood and test Flood action
857
858 Generate a packet
859 Generate a matching flow
860 Add action to forward to OFPP_ALL
861 Set port to no-flood
862 Send the packet to ingress dataplane port
863 Verify the packet is received at all other ports except
864 the ingress port and the no_flood port
865 """
866 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700867 of_ports = config["port_map"].keys()
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700868 of_ports.sort()
869 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
870
871 pkt = simple_tcp_packet()
Ed Swierk99a74de2012-08-22 06:40:54 -0700872 match = packet_to_flow_match(self, pkt)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700873 match.wildcards &= ~ofp.OFPFW_IN_PORT
874 self.assertTrue(match is not None,
875 "Could not generate flow match from pkt")
876 act = action.action_output()
877
Rich Lane4b9e38c2012-12-06 16:33:20 -0800878 # Clear OFPPC_NO_FLOOD on each port
879 for of_port in of_ports:
880 rv = port_config_set(self.controller, of_port,
881 0, ofp.OFPPC_NO_FLOOD)
882 self.assertEqual(rv, 0, "Failed to set port config")
883
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700884 for idx in range(len(of_ports)):
Rich Lane9a003812012-10-04 17:17:59 -0700885 rv = delete_all_flows(self.controller)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700886 self.assertEqual(rv, 0, "Failed to delete all flows")
887
888 ingress_port = of_ports[idx]
889 no_flood_idx = (idx + 1) % len(of_ports)
890 no_flood_port = of_ports[no_flood_idx]
891 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700892 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700893 self.assertEqual(rv, 0, "Failed to set port config")
894
895 match.in_port = ingress_port
896
897 request = message.flow_mod()
898 request.match = match
899 request.buffer_id = 0xffffffff
900 act.port = ofp.OFPP_FLOOD
901 self.assertTrue(request.actions.add(act),
902 "Could not add flood port action")
Rich Lane9a003812012-10-04 17:17:59 -0700903 logging.info(request.show())
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700904
Rich Lane9a003812012-10-04 17:17:59 -0700905 logging.info("Inserting flow")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700906 rv = self.controller.message_send(request)
907 self.assertTrue(rv != -1, "Error installing flow mod")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700908 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700909
Rich Lane9a003812012-10-04 17:17:59 -0700910 logging.info("Sending packet to dp port " + str(ingress_port))
911 logging.info("No flood port is " + str(no_flood_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700912 self.dataplane.send(ingress_port, str(pkt))
913 no_ports = set([ingress_port, no_flood_port])
914 yes_ports = set(of_ports).difference(no_ports)
Rich Lane2014f9b2012-10-05 15:29:40 -0700915 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700916
917 # Turn no flood off again
918 rv = port_config_set(self.controller, no_flood_port,
Rich Lane9a003812012-10-04 17:17:59 -0700919 0, ofp.OFPPC_NO_FLOOD)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700920 self.assertEqual(rv, 0, "Failed to reset port config")
Rich Lane4ecc1f42012-12-06 16:35:24 -0800921 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
922
923 # Check that packets are now flooded to no_flood_port
924 logging.info("Sending packet to dp port " + str(ingress_port))
925 self.dataplane.send(ingress_port, str(pkt))
926 no_ports = set([ingress_port])
927 yes_ports = set(of_ports).difference(no_ports)
928 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self)
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700929
930 #@todo Should check no other packets received
931
Dan Talayco21381562010-07-17 00:34:47 -0700932
933
Dan Talayco551befa2010-07-15 17:05:32 -0700934################################################################
935
Rich Laneb90a1c42012-10-05 09:16:05 -0700936class BaseMatchCase(base_tests.SimpleDataPlane):
Dan Talayco551befa2010-07-15 17:05:32 -0700937 def setUp(self):
Rich Laneb90a1c42012-10-05 09:16:05 -0700938 base_tests.SimpleDataPlane.setUp(self)
Dan Talayco551befa2010-07-15 17:05:32 -0700939 def runTest(self):
Rich Lane9a003812012-10-04 17:17:59 -0700940 logging.info("BaseMatchCase")
Dan Talayco551befa2010-07-15 17:05:32 -0700941
942class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700943 """
Dan Talayco551befa2010-07-15 17:05:32 -0700944 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700945
946 Generate a packet
947 Generate and install a matching flow without wildcard mask
948 Add action to forward to a port
949 Send the packet to the port
950 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700951 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700952
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700953 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -0700954 flow_match_test(self, config["port_map"])
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700955
Dan Talayco551befa2010-07-15 17:05:32 -0700956class ExactMatchTagged(BaseMatchCase):
957 """
958 Exact match for all port pairs with tagged pkts
959 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700960
Dan Talayco551befa2010-07-15 17:05:32 -0700961 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -0700962 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Lane477f4812012-10-04 22:49:00 -0700963 flow_match_test(self, config["port_map"], dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700964
Rich Lane0a4f6372013-01-02 14:40:22 -0800965@disabled
Dan Talayco551befa2010-07-15 17:05:32 -0700966class ExactMatchTaggedMany(BaseMatchCase):
967 """
968 ExactMatchTagged with many VLANS
969 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700970
Dan Talayco551befa2010-07-15 17:05:32 -0700971 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700972 for vid in range(2,100,10):
Rich Lane477f4812012-10-04 22:49:00 -0700973 flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
Dan Talayco551befa2010-07-15 17:05:32 -0700974 for vid in range(100,4000,389):
Rich Lane477f4812012-10-04 22:49:00 -0700975 flow_match_test(self, config["port_map"], dl_vlan=vid, max_test=5)
976 flow_match_test(self, config["port_map"], dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700977
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700978class SingleWildcardMatchPriority(BaseMatchCase):
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700979 """
980 SingleWildcardMatchPriority
981 """
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700982
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700983 def _Init(self):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700984 self.pkt = simple_tcp_packet()
985 self.flowMsgs = {}
986
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700987 def _ClearTable(self):
Rich Lane9a003812012-10-04 17:17:59 -0700988 rc = delete_all_flows(self.controller)
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700989 self.assertEqual(rc, 0, "Failed to delete all flows")
Dan Talayco0fc08bd2012-04-09 16:56:18 -0700990 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700991
992 def runTest(self):
993
994 self._Init()
Rich Lane477f4812012-10-04 22:49:00 -0700995 of_ports = config["port_map"].keys()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -0700996 of_ports.sort()
997
998 # Delete the initial flow table
Jeffrey Townsend50c82462012-03-28 18:26:14 -0700999 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001000
1001 # Run several combinations, each at lower priority settings.
1002 # At the end of each call to runPrioFlows(), the table should
1003 # be empty. If its not, we'll catch it as the priorities decreases
1004 portA = of_ports[0]
1005 portB = of_ports[1]
1006 portC = of_ports[2]
1007
1008 # TODO -- these priority numbers should be validated somehow?
1009 self.runPrioFlows(portA, portB, portC, 1000, 999)
1010 self.runPrioFlows(portB, portC, portA, 998, 997)
1011 self.runPrioFlows(portC, portA, portB, 996, 995)
1012 self.runPrioFlows(portA, portC, portB, 994, 993)
1013
1014
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001015
1016 def runPrioFlows(self, portA, portB, portC, prioHigher, prioLower,
1017 clearTable=False):
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001018
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001019 if clearTable:
1020 self._ClearTable()
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001021
1022 # Sanity check flow at lower priority from pA to pB
Rich Lane9a003812012-10-04 17:17:59 -07001023 logging.info("runPrioFlows(pA=%d,pB=%d,pC=%d,ph=%d,pl=%d"
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001024 % (portA, portB, portC, prioHigher, prioLower))
1025
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001026 # Sanity check flow at lower priority from pA to pC
1027 self.installFlow(prioLower, portA, portC)
1028 self.verifyFlow(portA, portC)
1029 self.removeFlow(prioLower)
1030
1031 # Install and verify pA->pB @ prioLower
1032 self.installFlow(prioLower, portA, portB)
1033 self.verifyFlow(portA, portB)
1034
1035 # Install and verify pA->pC @ prioHigher, should override pA->pB
1036 self.installFlow(prioHigher, portA, portC)
1037 self.verifyFlow(portA, portC)
1038 # remove pA->pC
1039 self.removeFlow(prioHigher)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001040 # Old flow pA -> pB @ prioLower should still be active
1041 self.verifyFlow(portA, portB)
1042 self.removeFlow(prioLower)
1043
1044 # Table should be empty at this point, leave it alone as
1045 # an assumption for future test runs
1046
1047
1048
Ed Swierk99a74de2012-08-22 06:40:54 -07001049 def installFlow(self, prio, inp, egp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001050 wildcards=ofp.OFPFW_DL_SRC):
Ed Swierk99a74de2012-08-22 06:40:54 -07001051 wildcards |= required_wildcards(self)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001052 request = flow_msg_create(self, self.pkt, ing_port=inp,
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001053 wildcards=wildcards,
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001054 egr_ports=egp)
1055 request.priority = prio
Rich Lane9a003812012-10-04 17:17:59 -07001056 logging.debug("Install flow with priority " + str(prio))
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001057 flow_msg_install(self, request, clear_table_override=False)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001058 self.flowMsgs[prio] = request
1059
1060 def removeFlow(self, prio):
1061 if self.flowMsgs.has_key(prio):
1062 msg = self.flowMsgs[prio]
1063 msg.command = ofp.OFPFC_DELETE_STRICT
1064 # This *must* be set for DELETE
1065 msg.out_port = ofp.OFPP_NONE
Rich Lane9a003812012-10-04 17:17:59 -07001066 logging.debug("Remove flow with priority " + str(prio))
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001067 self.controller.message_send(msg)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001068 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001069 else:
1070 raise Exception("Not initialized")
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001071
1072
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001073 def verifyFlow(self, inp, egp, pkt=None):
1074 if pkt == None:
1075 pkt = self.pkt
1076
Rich Lane9a003812012-10-04 17:17:59 -07001077 logging.info("Pkt match test: " + str(inp) + " to " + str(egp))
1078 logging.debug("Send packet: " + str(inp) + " to " + str(egp))
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001079 self.dataplane.send(inp, str(pkt))
1080 receive_pkt_verify(self, egp, pkt, inp)
Jeffrey Townsend2a300e42012-03-28 17:24:02 -07001081
1082
1083
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001084class SingleWildcardMatchPriorityInsertModifyDelete(SingleWildcardMatchPriority):
1085
1086 def runTest(self):
1087
1088 self._Init()
1089
Rich Lane477f4812012-10-04 22:49:00 -07001090 of_ports = config["port_map"].keys()
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001091 of_ports.sort()
1092
1093 # Install an entry from 0 -> 1 @ prio 1000
1094 self._ClearTable()
1095 self.installFlow(1000, of_ports[0], of_ports[1])
1096 self.verifyFlow(of_ports[0], of_ports[1])
1097 self.installFlow(1000, of_ports[1], of_ports[0])
1098 self.verifyFlow(of_ports[1], of_ports[0])
1099 self.installFlow(1001, of_ports[0], of_ports[1])
1100 self.verifyFlow(of_ports[0], of_ports[1])
1101 self.installFlow(1001, of_ports[1], of_ports[0])
1102 self.verifyFlow(of_ports[1], of_ports[0])
1103 self.removeFlow(1001)
1104 self.verifyFlow(of_ports[0], of_ports[1])
1105 self.removeFlow(1000)
1106
1107
1108
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001109class WildcardPriority(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001110 """
1111 1. Add wildcard flow, verify packet received.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001112 2. Add wildcard flow with higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001113 on port specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001114 3. Add wildcard flow with lower priority, verify packet received
Rich Laneb8392082012-11-21 15:52:54 -08001115 on port specified by the highest priority flow.
Ken Chiang38d7a152012-05-24 15:33:50 -07001116 """
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001117
1118 def runTest(self):
Jeffrey Townsend50c82462012-03-28 18:26:14 -07001119
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001120 self._Init()
1121
Rich Lane477f4812012-10-04 22:49:00 -07001122 of_ports = config["port_map"].keys()
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001123 of_ports.sort()
1124
1125 self._ClearTable()
Ken Chiang38d7a152012-05-24 15:33:50 -07001126
1127 # Install a flow with wildcards
1128 self.installFlow(999, of_ports[0], of_ports[1],
1129 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001130 self.verifyFlow(of_ports[0], of_ports[1])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001131 # Install a flow with wildcards with higher priority
1132 self.installFlow(1000, of_ports[0], of_ports[2],
1133 wildcards=ofp.OFPFW_DL_DST)
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001134 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001135 # Install a flow with wildcards with lower priority
Rich Laneb8392082012-11-21 15:52:54 -08001136 self.installFlow(999, of_ports[0], of_ports[1],
1137 wildcards=ofp.OFPFW_DL_SRC)
Rich Lane0a78fbd2012-12-31 16:25:04 -08001138 self.verifyFlow(of_ports[0], of_ports[2])
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001139
1140
Rich Lane97e99652013-01-02 17:23:20 -08001141@group("smoke")
Ken Chiang3978f242012-06-13 14:14:09 -07001142class WildcardPriorityWithDelete(SingleWildcardMatchPriority):
Ken Chiang38d7a152012-05-24 15:33:50 -07001143 """
Rich Lane0a78fbd2012-12-31 16:25:04 -08001144 1. Add wildcard match flow, verify packet received.
Ken Chiang38d7a152012-05-24 15:33:50 -07001145 2. Add wildcard flow with higher priority, verify packet received on port
1146 specified by this flow.
Rich Lane0a78fbd2012-12-31 16:25:04 -08001147 3. Add wildcard flow with even higher priority, verify packet received
Ken Chiang38d7a152012-05-24 15:33:50 -07001148 on port specified by this flow.
1149 4. Delete lowest priority flow, verify packet received on port specified
1150 by highest priority flow.
1151 5. Delete highest priority flow, verify packet received on port specified
1152 by remaining flow.
1153 """
1154
1155 def runTest(self):
1156
1157 self._Init()
1158
Rich Lane477f4812012-10-04 22:49:00 -07001159 of_ports = config["port_map"].keys()
Ken Chiang38d7a152012-05-24 15:33:50 -07001160 of_ports.sort()
1161
1162 self._ClearTable()
1163
Rich Lane0a78fbd2012-12-31 16:25:04 -08001164 # Install a flow with wildcards
1165 self.installFlow(250, of_ports[0], of_ports[1],
1166 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001167 self.verifyFlow(of_ports[0], of_ports[1])
1168 # Install a flow with wildcards of higher priority
1169 self.installFlow(1250, of_ports[0], of_ports[2],
1170 wildcards=ofp.OFPFW_DL_DST)
1171 self.verifyFlow(of_ports[0], of_ports[2])
Rich Lane0a78fbd2012-12-31 16:25:04 -08001172 # Install a flow with wildcards with even higher priority
1173 self.installFlow(2001, of_ports[0], of_ports[3],
1174 wildcards=ofp.OFPFW_DL_DST)
Ken Chiang38d7a152012-05-24 15:33:50 -07001175 self.verifyFlow(of_ports[0], of_ports[3])
1176 # Delete lowest priority flow
1177 self.removeFlow(250)
1178 self.verifyFlow(of_ports[0], of_ports[3])
1179 # Delete highest priority flow
1180 self.removeFlow(2001)
1181 self.verifyFlow(of_ports[0], of_ports[2])
1182
Jeffrey Townsend8364b162012-04-12 13:45:40 -07001183
Dan Talayco551befa2010-07-15 17:05:32 -07001184class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001185 """
1186 Exercise wildcard matching for all ports
1187
1188 Generate a packet
1189 Generate and install a matching flow with wildcard mask
1190 Add action to forward to a port
1191 Send the packet to the port
1192 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001193 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -07001194 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -07001195 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001196 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001197 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001198 wc |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001199 if wc & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001200 # Set nonzero VLAN id to avoid sending priority-tagged packet
1201 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001202 else:
1203 dl_vlan = -1
Rich Lane477f4812012-10-04 22:49:00 -07001204 flow_match_test(self, config["port_map"], wildcards=wc,
Dan Talayco4431d542012-03-21 16:42:16 -07001205 dl_vlan=dl_vlan, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001206
Dan Talayco551befa2010-07-15 17:05:32 -07001207class SingleWildcardMatchTagged(BaseMatchCase):
1208 """
1209 SingleWildcardMatch with tagged packets
1210 """
1211 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001212 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001213 for wc in WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001214 wc |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001215 flow_match_test(self, config["port_map"], wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -07001216 max_test=10)
1217
1218class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001219 """
Dan Talayco80b54ed2010-07-13 09:48:35 -07001220 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -07001221
1222 Generate a packet
1223 Generate and install a matching flow with wildcard all except one filed
1224 Add action to forward to a port
1225 Send the packet to the port
1226 Verify the packet is received at all other ports (one port at a time)
1227 Verify flow_expiration message is correct when command option is set
1228 """
1229 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001230 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001231 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001232 all_exp_one_wildcard |= required_wildcards(self)
Dan Talayco4431d542012-03-21 16:42:16 -07001233 if all_exp_one_wildcard & ofp.OFPFW_DL_VLAN:
Ken Chiang5be06dd2012-04-03 10:03:50 -07001234 # Set nonzero VLAN id to avoid sending priority-tagged packet
1235 dl_vlan = vid
Dan Talayco4431d542012-03-21 16:42:16 -07001236 else:
1237 dl_vlan = -1
Rich Lane477f4812012-10-04 22:49:00 -07001238 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Dan Talayco4431d542012-03-21 16:42:16 -07001239 dl_vlan=dl_vlan)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001240
Dan Talayco551befa2010-07-15 17:05:32 -07001241class AllExceptOneWildcardMatchTagged(BaseMatchCase):
1242 """
1243 Match one field with tagged packets
1244 """
1245 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001246 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco488fbc52012-04-09 16:30:41 -07001247 for all_exp_one_wildcard in NO_WILDCARD_VALUES:
Ed Swierk99a74de2012-08-22 06:40:54 -07001248 all_exp_one_wildcard |= required_wildcards(self)
Rich Lane477f4812012-10-04 22:49:00 -07001249 flow_match_test(self, config["port_map"], wildcards=all_exp_one_wildcard,
Dan Talayco21381562010-07-17 00:34:47 -07001250 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -07001251
1252class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -07001253 """
1254 Create Wildcard-all flow and exercise for all ports
1255
1256 Generate a packet
1257 Generate and install a matching flow with wildcard-all
1258 Add action to forward to a port
1259 Send the packet to the port
1260 Verify the packet is received at all other ports (one port at a time)
1261 Verify flow_expiration message is correct when command option is set
1262 """
1263 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001264 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001265
Dan Talayco551befa2010-07-15 17:05:32 -07001266class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001267 """
Dan Talayco551befa2010-07-15 17:05:32 -07001268 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001269 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001270 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001271 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Rich Lane477f4812012-10-04 22:49:00 -07001272 flow_match_test(self, config["port_map"], wildcards=ofp.OFPFW_ALL,
Dan Talayco21381562010-07-17 00:34:47 -07001273 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001274
Rich Lane97e99652013-01-02 17:23:20 -08001275@group('smoke')
Dan Talayco551befa2010-07-15 17:05:32 -07001276class AddVLANTag(BaseMatchCase):
1277 """
1278 Add a VLAN tag to an untagged packet
1279 """
1280 def runTest(self):
1281 new_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001282 sup_acts = self.supported_actions
Dan Talayco551befa2010-07-15 17:05:32 -07001283 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001284 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -07001285 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -07001286
Dan Talayco551befa2010-07-15 17:05:32 -07001287 len = 100
1288 len_w_vid = 104
1289 pkt = simple_tcp_packet(pktlen=len)
1290 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1291 dl_vlan=new_vid)
1292 vid_act = action.action_set_vlan_vid()
1293 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001294
Rich Lane477f4812012-10-04 22:49:00 -07001295 flow_match_test(self, config["port_map"], pkt=pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001296 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001297
Rich Lane0a4f6372013-01-02 14:40:22 -08001298@disabled
Rich Laneb90a1c42012-10-05 09:16:05 -07001299class PacketOnly(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001300 """
1301 Just send a packet thru the switch
1302 """
Rich Laned1d9c282012-10-04 22:07:10 -07001303
Dan Talayco551befa2010-07-15 17:05:32 -07001304 def runTest(self):
1305 pkt = simple_tcp_packet()
Rich Lane477f4812012-10-04 22:49:00 -07001306 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001307 of_ports.sort()
1308 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001309 logging.info("Sending packet to " + str(ing_port))
1310 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001311 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001312
Rich Lane0a4f6372013-01-02 14:40:22 -08001313@disabled
Rich Laneb90a1c42012-10-05 09:16:05 -07001314class PacketOnlyTagged(base_tests.DataPlaneOnly):
Dan Talayco551befa2010-07-15 17:05:32 -07001315 """
1316 Just send a packet thru the switch
1317 """
Rich Laned1d9c282012-10-04 22:07:10 -07001318
Dan Talayco551befa2010-07-15 17:05:32 -07001319 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001320 vid = test_param_get('vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -07001321 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
Rich Lane477f4812012-10-04 22:49:00 -07001322 of_ports = config["port_map"].keys()
Dan Talayco551befa2010-07-15 17:05:32 -07001323 of_ports.sort()
1324 ing_port = of_ports[0]
Rich Lane9a003812012-10-04 17:17:59 -07001325 logging.info("Sending packet to " + str(ing_port))
1326 logging.debug("Data: " + str(pkt).encode('hex'))
Dan Talayco551befa2010-07-15 17:05:32 -07001327 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001328
Dan Talayco551befa2010-07-15 17:05:32 -07001329class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001330 """
1331 Modify the VLAN ID in the VLAN tag of a tagged packet
1332 """
Dan Talaycoaf669322012-09-12 22:51:22 -07001333 def setUp(self):
1334 BaseMatchCase.setUp(self)
1335 self.ing_port=False
1336
Dan Talayco551befa2010-07-15 17:05:32 -07001337 def runTest(self):
1338 old_vid = 2
1339 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001340 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001341 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001342 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001343 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001344
Dan Talayco551befa2010-07-15 17:05:32 -07001345 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
1346 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
1347 vid_act = action.action_set_vlan_vid()
1348 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001349
Rich Lane477f4812012-10-04 22:49:00 -07001350 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoaf669322012-09-12 22:51:22 -07001351 action_list=[vid_act], ing_port=self.ing_port)
1352
1353class ModifyVIDToIngress(ModifyVID):
1354 """
1355 Modify the VLAN ID in the VLAN tag of a tagged packet and send to
1356 ingress port
1357 """
1358 def setUp(self):
1359 BaseMatchCase.setUp(self)
1360 self.ing_port=True
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001361
Ken Chiange9a211d2012-04-20 14:52:11 -07001362class ModifyVIDWithTagMatchWildcarded(BaseMatchCase):
1363 """
1364 With vlan ID and priority wildcarded, perform SET_VLAN_VID action.
1365 The same flow should match on both untagged and tagged packets.
1366 """
1367 def runTest(self):
1368 old_vid = 2
1369 new_vid = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001370 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001371 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
1372 skip_message_emit(self, "ModifyVIDWithTagWildcarded test")
1373 return
1374
Rich Lane477f4812012-10-04 22:49:00 -07001375 of_ports = config["port_map"].keys()
Ken Chiange9a211d2012-04-20 14:52:11 -07001376 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1377 ing_port = of_ports[0]
1378 egr_ports = of_ports[1]
1379
Rich Lane9a003812012-10-04 17:17:59 -07001380 rv = delete_all_flows(self.controller)
Ken Chiange9a211d2012-04-20 14:52:11 -07001381 self.assertEqual(rv, 0, "Failed to delete all flows")
1382
1383 len_untagged = 100
1384 len_w_vid = 104
1385 untagged_pkt = simple_tcp_packet(pktlen=len_untagged)
1386 tagged_pkt = simple_tcp_packet(pktlen=len_w_vid,
1387 dl_vlan_enable=True, dl_vlan=old_vid)
1388 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1389 dl_vlan=new_vid)
Ed Swierk99a74de2012-08-22 06:40:54 -07001390 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1391 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001392 vid_act = action.action_set_vlan_vid()
1393 vid_act.vlan_vid = new_vid
1394 request = flow_msg_create(self, untagged_pkt, ing_port=ing_port,
1395 wildcards=wildcards, egr_ports=egr_ports,
1396 action_list=[vid_act])
1397 flow_msg_install(self, request)
1398
Rich Lane9a003812012-10-04 17:17:59 -07001399 logging.debug("Send untagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001400 str(egr_ports))
1401 self.dataplane.send(ing_port, str(untagged_pkt))
1402 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1403
Rich Lane9a003812012-10-04 17:17:59 -07001404 logging.debug("Send tagged packet: " + str(ing_port) + " to " +
Ken Chiange9a211d2012-04-20 14:52:11 -07001405 str(egr_ports))
1406 self.dataplane.send(ing_port, str(tagged_pkt))
1407 receive_pkt_verify(self, egr_ports, exp_pkt, ing_port)
1408
Howard Pershc1199d52012-04-11 14:21:32 -07001409class ModifyVlanPcp(BaseMatchCase):
1410 """
1411 Modify the priority field of the VLAN tag of a tagged packet
1412 """
1413 def runTest(self):
1414 vid = 123
1415 old_vlan_pcp = 2
1416 new_vlan_pcp = 3
Ed Swierkc7193a22012-08-22 06:51:02 -07001417 sup_acts = self.supported_actions
Ed Swierk8c3af7f2012-04-24 14:19:17 -07001418 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_PCP):
1419 skip_message_emit(self, "Modify VLAN priority test")
Howard Pershc1199d52012-04-11 14:21:32 -07001420 return
1421
1422 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=old_vlan_pcp)
1423 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid, dl_vlan_pcp=new_vlan_pcp)
1424 vid_act = action.action_set_vlan_pcp()
1425 vid_act.vlan_pcp = new_vlan_pcp
1426
Rich Lane477f4812012-10-04 22:49:00 -07001427 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Howard Pershc1199d52012-04-11 14:21:32 -07001428 action_list=[vid_act])
1429
Dan Talayco551befa2010-07-15 17:05:32 -07001430class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001431 """
1432 Strip the VLAN tag from a tagged packet
1433 """
Dan Talayco551befa2010-07-15 17:05:32 -07001434 def runTest(self):
1435 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001436 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001437 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001438 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -07001439 return
Dan Talaycof36f1082010-07-13 13:57:17 -07001440
Dan Talayco551befa2010-07-15 17:05:32 -07001441 len_w_vid = 104
1442 len = 100
1443 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1444 dl_vlan=old_vid)
1445 exp_pkt = simple_tcp_packet(pktlen=len)
1446 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001447
Rich Lane477f4812012-10-04 22:49:00 -07001448 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco551befa2010-07-15 17:05:32 -07001449 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001450
Ken Chiange9a211d2012-04-20 14:52:11 -07001451class StripVLANTagWithTagMatchWildcarded(BaseMatchCase):
1452 """
1453 Strip the VLAN tag from a tagged packet.
1454 Differs from StripVLANTag in that VID and PCP are both wildcarded.
1455 """
1456 def runTest(self):
1457 old_vid = 2
Ed Swierkc7193a22012-08-22 06:51:02 -07001458 sup_acts = self.supported_actions
Ken Chiange9a211d2012-04-20 14:52:11 -07001459 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
1460 skip_message_emit(self, "StripVLANTagWithTagWildcarded test")
1461 return
1462
1463 len_w_vid = 104
1464 len_untagged = 100
1465 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
1466 dl_vlan=old_vid)
1467 exp_pkt = simple_tcp_packet(pktlen=len_untagged)
Ed Swierk99a74de2012-08-22 06:40:54 -07001468 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_VLAN |
1469 ofp.OFPFW_DL_VLAN_PCP)
Ken Chiange9a211d2012-04-20 14:52:11 -07001470 vid_act = action.action_strip_vlan()
1471
Rich Lane477f4812012-10-04 22:49:00 -07001472 flow_match_test(self, config["port_map"],
Ed Swierk99a74de2012-08-22 06:40:54 -07001473 wildcards=wildcards,
Ken Chiange9a211d2012-04-20 14:52:11 -07001474 pkt=pkt, exp_pkt=exp_pkt,
1475 action_list=[vid_act])
1476
Dan Talayco4b2bee62010-07-20 14:10:05 -07001477def init_pkt_args():
1478 """
1479 Pass back a dictionary with default packet arguments
1480 """
1481 args = {}
1482 args["dl_src"] = '00:23:45:67:89:AB'
1483
1484 dl_vlan_enable=False
1485 dl_vlan=-1
Rich Lane477f4812012-10-04 22:49:00 -07001486 if config["test-params"]["vid"]:
Dan Talayco4b2bee62010-07-20 14:10:05 -07001487 dl_vlan_enable=True
Rich Lane477f4812012-10-04 22:49:00 -07001488 dl_vlan = config["test-params"]["vid"]
Dan Talayco4b2bee62010-07-20 14:10:05 -07001489
1490# Unpack operator is ** on a dictionary
1491
1492 return args
1493
Dan Talayco551befa2010-07-15 17:05:32 -07001494class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001495 """
1496 Modify the source MAC address (TP1)
1497 """
Dan Talayco551befa2010-07-15 17:05:32 -07001498 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001499 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001500 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001501 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001502 return
1503
1504 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1505 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001506 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001507 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001508
Dan Talayco551befa2010-07-15 17:05:32 -07001509class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001510 """
1511 Modify the dest MAC address (TP1)
1512 """
Dan Talayco551befa2010-07-15 17:05:32 -07001513 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001514 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001515 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001516 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001517 return
1518
1519 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1520 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001521 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001522 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001523
Dan Talayco551befa2010-07-15 17:05:32 -07001524class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001525 """
1526 Modify the source IP address of an IP packet (TP1)
1527 """
Dan Talayco551befa2010-07-15 17:05:32 -07001528 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001529 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001530 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001531 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001532 return
1533
1534 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
1535 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001536 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001537 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001538
Dan Talayco551befa2010-07-15 17:05:32 -07001539class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001540 """
1541 Modify the dest IP address of an IP packet (TP1)
1542 """
Dan Talayco551befa2010-07-15 17:05:32 -07001543 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001544 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001545 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001546 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001547 return
1548
1549 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
1550 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001551 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001552 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001553
1554class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001555 """
1556 Modify the source TCP port of a TCP packet (TP1)
1557 """
Dan Talayco551befa2010-07-15 17:05:32 -07001558 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001559 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001560 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001561 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001562 return
1563
1564 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
1565 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001566 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001567 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001568
Rich Lane01c2b862012-10-26 16:26:25 -07001569class ModifyL4SrcUdp(BaseMatchCase):
1570 """
1571 Modify the source UDP port of a UDP packet
1572 """
1573 def runTest(self):
1574 sup_acts = self.supported_actions
1575 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1576 skip_message_emit(self, "ModifyL4SrcUdp test")
1577 return
1578
1579 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_sport'],
1580 check_test_params=True, tp="udp")
1581 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1582 action_list=acts, max_test=2)
1583
Dan Talayco551befa2010-07-15 17:05:32 -07001584class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001585 """
1586 Modify the dest TCP port of a TCP packet (TP1)
1587 """
Dan Talayco551befa2010-07-15 17:05:32 -07001588 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001589 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001590 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001591 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001592 return
1593
1594 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
1595 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001596 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talayco4b2bee62010-07-20 14:10:05 -07001597 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -07001598
Rich Lane01c2b862012-10-26 16:26:25 -07001599class ModifyL4DstUdp(BaseMatchCase):
1600 """
1601 Modify the dest UDP port of a UDP packet
1602 """
1603 def runTest(self):
1604 sup_acts = self.supported_actions
1605 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
1606 skip_message_emit(self, "ModifyL4DstUdp test")
1607 return
1608
1609 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['udp_dport'],
1610 check_test_params=True, tp="udp")
1611 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1612 action_list=acts, max_test=2)
1613
Dan Talayco551befa2010-07-15 17:05:32 -07001614class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -07001615 """
1616 Modify the IP type of service of an IP packet (TP1)
1617 """
Dan Talayco551befa2010-07-15 17:05:32 -07001618 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001619 sup_acts = self.supported_actions
Dan Talayco4b2bee62010-07-20 14:10:05 -07001620 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -07001621 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -07001622 return
Dan Talayco551befa2010-07-15 17:05:32 -07001623
Dan Talayco4b2bee62010-07-20 14:10:05 -07001624 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
1625 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001626 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001627 action_list=acts, max_test=2, egr_count=-1)
Dan Talayco551befa2010-07-15 17:05:32 -07001628
Dan Talaycof6e76c02012-03-23 10:56:12 -07001629class ModifyL2DstMC(BaseMatchCase):
1630 """
1631 Modify the L2 dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001632 """
1633 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001634 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001635 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001636 skip_message_emit(self, "ModifyL2dstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001637 return
1638
Dan Talaycof6e76c02012-03-23 10:56:12 -07001639 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1640 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001641 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001642 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001643
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001644class ModifyL2DstIngress(BaseMatchCase):
1645 """
1646 Modify the L2 dest and send to the ingress port
1647 """
1648 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001649 sup_acts = self.supported_actions
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001650 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001651 skip_message_emit(self, "ModifyL2dstIngress test")
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001652 return
1653
1654 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1655 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001656 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycoc948d0b2012-03-23 12:17:54 -07001657 action_list=acts, max_test=2, egr_count=0,
1658 ing_port=True)
1659
Dan Talaycod8ae7582012-03-23 12:24:56 -07001660class ModifyL2DstIngressMC(BaseMatchCase):
1661 """
1662 Modify the L2 dest and send to the ingress port
1663 """
1664 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001665 sup_acts = self.supported_actions
Dan Talaycod8ae7582012-03-23 12:24:56 -07001666 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
1667 skip_message_emit(self, "ModifyL2dstMC test")
1668 return
1669
1670 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
1671 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001672 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycod8ae7582012-03-23 12:24:56 -07001673 action_list=acts, max_test=2, egr_count=-1,
1674 ing_port=True)
1675
Dan Talaycof6e76c02012-03-23 10:56:12 -07001676class ModifyL2SrcMC(BaseMatchCase):
1677 """
1678 Modify the source MAC address (TP1) and send to multiple
Dan Talaycof6e76c02012-03-23 10:56:12 -07001679 """
1680 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001681 sup_acts = self.supported_actions
Dan Talaycof6e76c02012-03-23 10:56:12 -07001682 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycocfa172f2012-03-23 12:03:00 -07001683 skip_message_emit(self, "ModifyL2SrcMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001684 return
1685
Dan Talaycof6e76c02012-03-23 10:56:12 -07001686 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
1687 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001688 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001689 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001690
1691class ModifyL2SrcDstMC(BaseMatchCase):
1692 """
1693 Modify the L2 source and dest and send to 2 ports
Dan Talaycof6e76c02012-03-23 10:56:12 -07001694 """
1695 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001696 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001697 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1698 not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC)):
1699 skip_message_emit(self, "ModifyL2SrcDstMC test")
Dan Talaycof6e76c02012-03-23 10:56:12 -07001700 return
1701
Dan Talaycof6e76c02012-03-23 10:56:12 -07001702 mod_fields = ['dl_dst', 'dl_src']
1703 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=mod_fields,
1704 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001705 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001706 action_list=acts, max_test=2, egr_count=-1)
1707
1708class ModifyL2DstVIDMC(BaseMatchCase):
1709 """
1710 Modify the L2 dest and send to 2 ports
1711 """
1712 def runTest(self):
Ed Swierkc7193a22012-08-22 06:51:02 -07001713 sup_acts = self.supported_actions
Dan Talaycocfa172f2012-03-23 12:03:00 -07001714 if (not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST) or
1715 not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID)):
1716 skip_message_emit(self, "ModifyL2DstVIDMC test")
1717 return
1718
1719 mod_fields = ['dl_dst', 'dl_vlan']
1720 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1721 start_field_vals={'dl_vlan_enable':True}, mod_fields=mod_fields,
1722 check_test_params=True)
Rich Lane477f4812012-10-04 22:49:00 -07001723 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
Dan Talaycocfa172f2012-03-23 12:03:00 -07001724 action_list=acts, max_test=2, egr_count=-1)
Dan Talaycof6e76c02012-03-23 10:56:12 -07001725
Rich Lane97e99652013-01-02 17:23:20 -08001726@group("smoke")
Rich Lane22e74c12012-11-12 15:06:06 -08001727class ModifyAll(BaseMatchCase):
1728 """
1729 Modify all supported fields and output to a port
1730 """
1731 def runTest(self):
1732 sup_acts = self.supported_actions
1733
1734 sup_map = {
1735 "dl_dst" : ofp.OFPAT_SET_DL_DST,
1736 "dl_src" : ofp.OFPAT_SET_DL_SRC,
1737 "dl_vlan_enable" : ofp.OFPAT_SET_VLAN_VID,
1738 "dl_vlan" : ofp.OFPAT_SET_VLAN_VID,
1739 "dl_vlan_pcp" : ofp.OFPAT_SET_VLAN_PCP,
1740 "ip_src" : ofp.OFPAT_SET_NW_SRC,
1741 "ip_dst" : ofp.OFPAT_SET_NW_DST,
1742 "ip_tos" : ofp.OFPAT_SET_NW_TOS,
1743 "tcp_sport" : ofp.OFPAT_SET_TP_SRC,
1744 "tcp_dport" : ofp.OFPAT_SET_TP_DST,
1745 }
1746
1747 mod_fields = [field for (field, bit) in sup_map.items() if (sup_acts & 1 << bit)]
1748 random.shuffle(mod_fields)
1749 start_field_vals = { "dl_vlan_enable" : True }
1750 mod_field_vals = { "dl_vlan_enable" : True }
1751 logging.info("modifying fields: %s" % repr(mod_fields))
1752
1753 (pkt, exp_pkt, acts) = pkt_action_setup(self,
1754 mod_fields=mod_fields,
1755 start_field_vals=start_field_vals,
1756 mod_field_vals=mod_field_vals,
1757 check_test_params=True)
1758 flow_match_test(self, config["port_map"], pkt=pkt, exp_pkt=exp_pkt,
1759 action_list=acts, max_test=2)
1760
Dan Talaycofa6454f2012-04-05 10:04:13 -07001761class FlowToggle(BaseMatchCase):
1762 """
1763 Add flows to the table and modify them repeatedly
Dan Talaycof7c41312012-07-23 12:53:19 -07001764
1765 This is done by using only "add" flow messages. Since the check overlap
1766 flag is not set, the switch is supposed to modify the existing flow if
1767 the match already exists.
1768
1769 Would probably be better to exercise more of the flow modify commands
1770 (add, modify, delete +/- strict).
Dan Talaycofa6454f2012-04-05 10:04:13 -07001771 """
1772 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001773 flow_count = test_param_get('ft_flow_count', default=20)
1774 iter_count = test_param_get('ft_iter_count', default=10)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001775
Rich Lane9a003812012-10-04 17:17:59 -07001776 logging.info("Running flow toggle with %d flows, %d iterations" %
Dan Talaycofa6454f2012-04-05 10:04:13 -07001777 (flow_count, iter_count))
1778 acts = []
1779 acts.append(action.action_output())
1780 acts.append(action.action_output())
1781
Rich Lane477f4812012-10-04 22:49:00 -07001782 of_ports = config["port_map"].keys()
Dan Talaycofa6454f2012-04-05 10:04:13 -07001783 if len(of_ports) < 3:
1784 self.assertTrue(False, "Too few ports for test")
1785
1786 for idx in range(2):
1787 acts[idx].port = of_ports[idx]
1788
1789 flows = []
1790 flows.append([])
1791 flows.append([])
1792
Ed Swierk99a74de2012-08-22 06:40:54 -07001793 wildcards = (required_wildcards(self) | ofp.OFPFW_DL_SRC |
1794 ofp.OFPFW_DL_DST)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001795 # Create up the flows in an array
1796 for toggle in range(2):
1797 for f_idx in range(flow_count):
1798 pkt = simple_tcp_packet(tcp_sport=f_idx)
1799 msg = message.flow_mod()
Ed Swierk99a74de2012-08-22 06:40:54 -07001800 match = packet_to_flow_match(self, pkt)
Shudong Zhou031373c2012-07-19 17:37:42 -07001801 match.in_port = of_ports[2]
Dan Talayco50be7672012-04-05 11:38:08 -07001802 match.wildcards = wildcards
Dan Talaycofa6454f2012-04-05 10:04:13 -07001803 msg.match = match
1804 msg.buffer_id = 0xffffffff
Dan Talaycof7c41312012-07-23 12:53:19 -07001805 msg.command = ofp.OFPFC_ADD
Dan Talaycofa6454f2012-04-05 10:04:13 -07001806 msg.actions.add(acts[toggle])
1807 flows[toggle].append(msg)
Dan Talayco50be7672012-04-05 11:38:08 -07001808
1809 # Show two sample flows
Rich Lane9a003812012-10-04 17:17:59 -07001810 logging.debug(flows[0][0].show())
1811 logging.debug(flows[1][0].show())
Dan Talayco50be7672012-04-05 11:38:08 -07001812
Dan Talaycofa6454f2012-04-05 10:04:13 -07001813 # Install the first set of flows
1814 for f_idx in range(flow_count):
1815 rv = self.controller.message_send(flows[0][f_idx])
1816 self.assertTrue(rv != -1, "Error installing flow %d" % f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001817 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
Dan Talaycofa6454f2012-04-05 10:04:13 -07001818
Rich Lane9a003812012-10-04 17:17:59 -07001819 logging.info("Installed %d flows" % flow_count)
Dan Talaycofa6454f2012-04-05 10:04:13 -07001820
1821 # Repeatedly modify all the flows back and forth
1822 updates = 0
1823 # Report status about 5 times
1824 mod_val = (iter_count / 4) + 1
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001825 start = time.time()
1826 for iter_idx in range(iter_count):
1827 if not iter_idx % mod_val:
Rich Lane9a003812012-10-04 17:17:59 -07001828 logging.info("Flow Toggle: iter %d of %d. " %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001829 (iter_idx, iter_count) +
1830 "%d updates in %d secs" %
1831 (updates, time.time() - start))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001832 for toggle in range(2):
1833 t_idx = 1 - toggle
1834 for f_idx in range(flow_count):
1835 rv = self.controller.message_send(flows[t_idx][f_idx])
1836 updates += 1
1837 self.assertTrue(rv != -1, "Error modifying flow %d" %
1838 f_idx)
Dan Talayco0fc08bd2012-04-09 16:56:18 -07001839 self.assertEqual(do_barrier(self.controller), 0,
1840 "Barrier failed")
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001841
1842 end = time.time()
1843 divisor = end - start or (end - start + 1)
Rich Lane9a003812012-10-04 17:17:59 -07001844 logging.info("Flow toggle: %d iterations" % iter_count)
1845 logging.info(" %d flow mods in %d secs, %d mods/sec" %
Dan Talaycoabbfdbb2012-04-05 10:29:26 -07001846 (updates, end - start, updates/divisor))
Dan Talaycofa6454f2012-04-05 10:04:13 -07001847
1848
Dan Talayco8a64e332012-03-28 14:53:20 -07001849# You can pick and choose these by commenting tests in or out
1850iter_classes = [
1851 basic.PacketIn,
1852 basic.PacketOut,
1853 DirectPacket,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001854 FlowToggle,
Dan Talayco8a64e332012-03-28 14:53:20 -07001855 DirectTwoPorts,
Dan Talaycofa6454f2012-04-05 10:04:13 -07001856 DirectMCNonIngress,
Dan Talayco8a64e332012-03-28 14:53:20 -07001857 AllWildcardMatch,
1858 AllWildcardMatchTagged,
1859 SingleWildcardMatch,
1860 SingleWildcardMatchTagged,
1861 ExactMatch,
1862 ExactMatchTagged,
1863 SingleWildcardMatch,
1864 ModifyL2Src,
1865 ModifyL2Dst,
1866 ModifyL2SrcMC,
1867 ModifyL2DstMC,
1868 ModifyL2SrcDstMC
1869 ]
1870
Rich Lane0a4f6372013-01-02 14:40:22 -08001871@disabled
Dan Talayco8a64e332012-03-28 14:53:20 -07001872class IterCases(BaseMatchCase):
Dan Talaycofa6454f2012-04-05 10:04:13 -07001873 """
1874 Iterate over a bunch of test cases
1875
1876 The cases come from the list above
1877 """
1878
Dan Talayco8a64e332012-03-28 14:53:20 -07001879 def runTest(self):
Rich Lane2014f9b2012-10-05 15:29:40 -07001880 count = test_param_get('iter_count', default=10)
Dan Talayco8a64e332012-03-28 14:53:20 -07001881 tests_done = 0
Rich Lane9a003812012-10-04 17:17:59 -07001882 logging.info("Running iteration test " + str(count) + " times")
Dan Talayco8a64e332012-03-28 14:53:20 -07001883 start = time.time()
1884 last = start
1885 for idx in range(count):
Rich Lane9a003812012-10-04 17:17:59 -07001886 logging.info("Iteration " + str(idx + 1))
Dan Talayco8a64e332012-03-28 14:53:20 -07001887 for cls in iter_classes:
1888 test = cls()
1889 test.inheritSetup(self)
1890 test.runTest()
1891 tests_done += 1
Dan Talaycofa6454f2012-04-05 10:04:13 -07001892 # Report update about every minute, between tests
Dan Talayco8a64e332012-03-28 14:53:20 -07001893 if time.time() - last > 60:
1894 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001895 logging.info(
Dan Talaycofa6454f2012-04-05 10:04:13 -07001896 "IterCases: Iter %d of %d; Ran %d tests in %d " %
1897 (idx, count, tests_done, last - start) +
1898 "seconds so far")
Dan Talayco8a64e332012-03-28 14:53:20 -07001899 stats = all_stats_get(self)
1900 last = time.time()
Rich Lane9a003812012-10-04 17:17:59 -07001901 logging.info("\nIterCases ran %d tests in %d seconds." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001902 (tests_done, last - start))
Rich Lane9a003812012-10-04 17:17:59 -07001903 logging.info(" flows: %d. packets: %d. bytes: %d" %
Dan Talayco8a64e332012-03-28 14:53:20 -07001904 (stats["flows"], stats["packets"], stats["bytes"]))
Rich Lane9a003812012-10-04 17:17:59 -07001905 logging.info(" active: %d. lookups: %d. matched %d." %
Dan Talayco8a64e332012-03-28 14:53:20 -07001906 (stats["active"], stats["lookups"], stats["matched"]))
1907
Dan Talayco4b2bee62010-07-20 14:10:05 -07001908#@todo Need to implement tagged versions of the above tests
1909#
1910#@todo Implement a test case that strips tag 2, adds tag 3
1911# and modifies tag 4 to tag 5. Then verify (in addition) that
1912# tag 6 does not get modified.
1913
Rich Lane0a4f6372013-01-02 14:40:22 -08001914@disabled
Dan Talayco4b2bee62010-07-20 14:10:05 -07001915class MixedVLAN(BaseMatchCase):
1916 """
1917 Test mixture of VLAN tag actions
1918
1919 Strip tag 2 on port 1, send to port 2
1920 Add tag 3 on port 1, send to port 2
1921 Modify tag 4 to 5 on port 1, send to port 2
1922 All other traffic from port 1, send to port 3
1923 All traffic from port 2 sent to port 4
1924 Use exact matches with different packets for all mods
1925 Verify the following: (port, vid)
1926 (port 1, vid 2) => VLAN tag stripped, out port 2
1927 (port 1, no tag) => tagged packet w/ vid 2 out port 2
1928 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
1929 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
1930 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
1931 (port 2, no tag) => untagged packet out port 4
1932 (port 2, vid 2-6) => unmodified packet out port 4
1933
1934 Variation: Might try sending VID 5 to port 3 and check.
1935 If only VID 5 distinguishes pkt, this will fail on some platforms
1936 """
1937
Rich Lane97e99652013-01-02 17:23:20 -08001938@group('smoke')
Rich Laneb90a1c42012-10-05 09:16:05 -07001939class MatchEach(base_tests.SimpleDataPlane):
Rich Lane8d6ab272012-09-23 18:06:20 -07001940 """
1941 Check that each match field is actually matched on.
1942 Installs two flows that differ in one field. The flow that should not
1943 match has a higher priority, so if that field is ignored during matching
1944 the packet will be sent out the wrong port.
1945
1946 TODO test UDP, ARP, ICMP, etc.
1947 """
1948 def runTest(self):
Rich Lane477f4812012-10-04 22:49:00 -07001949 of_ports = config["port_map"].keys()
Rich Lane8d6ab272012-09-23 18:06:20 -07001950 of_ports.sort()
1951 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
1952
Rich Lane9a003812012-10-04 17:17:59 -07001953 delete_all_flows(self.controller)
Rich Lane8d6ab272012-09-23 18:06:20 -07001954
Ed Swierk7040a8d2012-12-11 16:30:13 -08001955 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=2)
Rich Lane8d6ab272012-09-23 18:06:20 -07001956 ingress_port = of_ports[0]
1957 egress_port = of_ports[1]
1958
1959 def testField(field, mask):
Rich Lane9a003812012-10-04 17:17:59 -07001960 logging.info("Testing field %s" % field)
Rich Lane8d6ab272012-09-23 18:06:20 -07001961
1962 def addFlow(matching, priority, output_port):
1963 match = packet_to_flow_match(self, pkt)
1964 self.assertTrue(match is not None, "Could not generate flow match from pkt")
1965 match.wildcards &= ~ofp.OFPFW_IN_PORT
1966 match.in_port = ingress_port
1967 if not matching:
1968 # Make sure flow doesn't match
1969 orig = getattr(match, field)
1970 if isinstance(orig, list):
1971 new = map(lambda a: ~a[0] & a[1], zip(orig, mask))
1972 else:
1973 new = ~orig & mask
1974 setattr(match, field, new)
1975 request = message.flow_mod()
1976 request.match = match
1977 request.buffer_id = 0xffffffff
1978 request.priority = priority
1979 act = action.action_output()
1980 act.port = output_port
1981 self.assertTrue(request.actions.add(act), "Could not add action")
Rich Lane9a003812012-10-04 17:17:59 -07001982 logging.info("Inserting flow")
Rich Lane8d6ab272012-09-23 18:06:20 -07001983 self.controller.message_send(request)
1984
1985 # This flow should match.
1986 addFlow(matching=True, priority=0, output_port=egress_port)
1987 # This flow should not match, but it has a higher priority.
1988 addFlow(matching=False, priority=1, output_port=ofp.OFPP_IN_PORT)
1989
1990 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
1991
Rich Lane9a003812012-10-04 17:17:59 -07001992 logging.info("Sending packet to dp port " + str(ingress_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07001993 self.dataplane.send(ingress_port, str(pkt))
1994
1995 exp_pkt_arg = None
1996 exp_port = None
Rich Lane477f4812012-10-04 22:49:00 -07001997 if config["relax"]:
Rich Lane8d6ab272012-09-23 18:06:20 -07001998 exp_pkt_arg = pkt
1999 exp_port = egress_port
2000
2001 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(port_number=exp_port,
2002 exp_pkt=exp_pkt_arg)
2003 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Rich Lane9a003812012-10-04 17:17:59 -07002004 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " + str(rcv_port))
Rich Lane8d6ab272012-09-23 18:06:20 -07002005 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
2006 self.assertEqual(str(pkt), str(rcv_pkt), 'Response packet does not match send packet')
2007
Ed Swierkb603b192012-12-12 15:38:49 -08002008 wildcards = required_wildcards(self)
Rich Lane8d6ab272012-09-23 18:06:20 -07002009 # TODO in_port
Ed Swierkb603b192012-12-12 15:38:49 -08002010 if not (wildcards & ofp.OFPFW_DL_SRC):
2011 testField("dl_src", [0xff]*6)
2012 if not (wildcards & ofp.OFPFW_DL_DST):
2013 testField("dl_dst", [0xff]*6)
2014 if not (wildcards & ofp.OFPFW_DL_TYPE):
2015 testField("dl_type", 0xffff)
2016 if not (wildcards & ofp.OFPFW_DL_VLAN):
2017 testField("dl_vlan", 0xfff)
Rich Lane8d6ab272012-09-23 18:06:20 -07002018 # TODO dl_vlan_pcp
Ed Swierkb603b192012-12-12 15:38:49 -08002019 if not (wildcards & ofp.OFPFW_NW_SRC_ALL):
2020 testField("nw_src", 0xffffffff)
2021 if not (wildcards & ofp.OFPFW_NW_DST_ALL):
2022 testField("nw_dst", 0xffffffff)
2023 if not (wildcards & ofp.OFPFW_NW_TOS):
2024 testField("nw_tos", 0x3f)
2025 if not (wildcards & ofp.OFPFW_NW_PROTO):
2026 testField("nw_proto", 0xff)
2027 if not (wildcards & ofp.OFPFW_TP_SRC):
2028 testField("tp_src", 0xffff)
2029 if not (wildcards & ofp.OFPFW_TP_DST):
2030 testField("tp_dst", 0xffff)
Rich Lane8d6ab272012-09-23 18:06:20 -07002031
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002032class DirectBadPacketBase(base_tests.SimpleDataPlane):
2033 """
2034 Base class for sending single packets with single flow table entries.
2035 Used to verify matching of unusual packets and parsing/matching of
2036 corrupted packets.
2037
2038 The idea is to generate packets that may either be totally malformed or
2039 malformed just enough to trick the flow matcher into making mistakes.
2040
2041 Generate a 'bad' packet
2042 Generate and install a matching flow
2043 Add action to direct the packet to an egress port
2044 Send the packet to ingress dataplane port
2045 Verify the packet is received at the egress port only
2046 """
2047
2048 RESULT_MATCH = "MATCH"
2049 RESULT_NOMATCH = "NO MATCH"
2050 RESULT_ANY = "ANY MATCH"
2051
2052 def runTest(self):
2053 pass
2054 # TODO:
2055 # - ICMP?
2056 # - VLAN?
2057 # - action
2058
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002059 def createMatch(self, **kwargs):
2060 match = ofp.ofp_match()
2061 match.wildcards = ofp.OFPFW_ALL
2062 fields = {
2063 'dl_dst': ofp.OFPFW_DL_DST,
2064 'dl_src': ofp.OFPFW_DL_SRC,
2065 'dl_type': ofp.OFPFW_DL_TYPE,
2066 'dl_vlan': ofp.OFPFW_DL_VLAN,
2067 'nw_src': ofp.OFPFW_NW_SRC_MASK,
2068 'nw_dst': ofp.OFPFW_NW_DST_MASK,
2069 'nw_tos': ofp.OFPFW_NW_TOS,
2070 'nw_proto': ofp.OFPFW_NW_PROTO,
2071 'tp_src': ofp.OFPFW_TP_SRC,
2072 'tp_dst': ofp.OFPFW_TP_DST,
2073 }
2074 for key in kwargs:
2075 setattr(match, key, kwargs[key])
2076 match.wildcards &= ~fields[key]
2077 return match
2078
2079 def testPktsAgainstFlow(self, pkts, acts, match):
2080 if type(acts) != list:
2081 acts = [acts]
2082 for info in pkts:
2083 title, pkt, expected_result = info
2084 self.testPktAgainstFlow(title, pkt, acts, match, expected_result)
2085
2086 def testPktAgainstFlow(self, title, pkt, acts, match, expected_result):
2087 of_ports = config["port_map"].keys()
2088 of_ports.sort()
2089 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
2090
2091 rv = delete_all_flows(self.controller)
2092 self.assertEqual(rv, 0, "Failed to delete all flows")
2093
2094 ingress_port = of_ports[0]
2095 egress_port = of_ports[1]
2096
2097 logging.info("Testing packet '%s', expect result %s" %
2098 (title, expected_result))
2099 logging.info("Ingress %s to egress %s" %
2100 (str(ingress_port), str(egress_port)))
2101 logging.info("Packet:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002102 logging.info(inspect_packet(pkt))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002103
2104 match.in_port = ingress_port
2105
2106 request = message.flow_mod()
2107 request.match = match
Rich Lane44cf12d2012-10-15 11:10:45 -07002108 request.priority = 1
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002109
2110 request.buffer_id = 0xffffffff
2111 for act in acts:
2112 act.port = egress_port
2113 rv = request.actions.add(act)
2114 self.assertTrue(rv, "Could not add action")
2115
2116 logging.info("Inserting flow")
2117 rv = self.controller.message_send(request)
2118 self.assertTrue(rv != -1, "Error installing flow mod")
Rich Lane44cf12d2012-10-15 11:10:45 -07002119
2120 # This flow speeds up negative tests
2121 logging.info("Inserting catch-all flow")
2122 request2 = message.flow_mod()
2123 request2.match = self.createMatch()
2124 request2.priority = 0
2125 act = action.action_output()
2126 act.port = ofp.OFPP_IN_PORT
2127 request2.actions.add(act)
2128 rv = self.controller.message_send(request2)
2129 self.assertTrue(rv != -1, "Error installing flow mod")
2130
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002131 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
2132
2133 logging.info("Sending packet to dp port " +
2134 str(ingress_port))
2135 self.dataplane.send(ingress_port, str(pkt))
2136
2137 exp_pkt_arg = None
2138 exp_port = None
2139 if config["relax"]:
2140 exp_pkt_arg = pkt
2141 exp_port = egress_port
2142
Rich Lane44cf12d2012-10-15 11:10:45 -07002143 if expected_result == self.RESULT_MATCH:
2144 timeout = -1 # default timeout
2145 else:
2146 timeout = 1 # short timeout for negative tests
2147
2148 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(exp_pkt=exp_pkt_arg,
2149 timeout=timeout)
2150 if rcv_port == ingress_port:
2151 logging.debug("Packet matched catch-all flow")
2152 rcv_pkt = None
2153
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002154 if expected_result == self.RESULT_MATCH:
2155 self.assertTrue(rcv_pkt is not None,
2156 "Did not receive packet, expected a match")
2157 logging.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
2158 str(rcv_port))
2159 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
2160 str_pkt = str(pkt)
2161 str_rcv_pkt = str(rcv_pkt)
2162 str_rcv_pkt = str_rcv_pkt[0:len(str_pkt)]
2163 if str_pkt != str_rcv_pkt:
2164 logging.error("Response packet does not match send packet")
2165 logging.info("Response:")
Rich Lane5d7e89a2012-10-26 16:43:13 -07002166 logging.info(inspect_packet(scapy.Ether(rcv_pkt)))
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002167 self.assertEqual(str_pkt, str_rcv_pkt,
2168 'Response packet does not match send packet')
2169 elif expected_result == self.RESULT_NOMATCH:
2170 self.assertTrue(rcv_pkt is None, "Received packet, expected drop")
2171 else:
2172 logging.debug("Match or drop accepted. Result = %s" %
2173 ("match" if rcv_pkt is not None else "drop"))
2174
2175
2176class DirectBadIpTcpPacketsBase(DirectBadPacketBase):
2177 """
2178 Base class for TCP and UDP parsing/matching verification under corruptions
2179 """
2180 def runTest(self):
2181 pass
2182
2183 def runTestWithProto(self, protoName = 'TCP'):
2184 dl_dst='00:01:02:03:04:05'
2185 dl_src='00:06:07:08:09:0a'
2186 ip_src='192.168.0.1'
2187 ip_dst='192.168.0.2'
2188 ip_tos=0
2189 tcp_sport=1234
2190 tcp_dport=80
2191
2192 # Generate a proper packet for constructing a match
2193 tp = None
2194 if protoName == 'TCP':
2195 tp = scapy.TCP
2196 proto = 6
2197 elif protoName == 'UDP':
2198 tp = scapy.UDP
2199 proto = 17
2200 else:
2201 raise Exception("Passed in unknown proto name")
2202
2203 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
2204 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2205 tp(sport=tcp_sport, dport=tcp_dport)
2206 match = packet_to_flow_match(self, match_pkt)
2207 self.assertTrue(match is not None,
2208 "Could not generate flow match from pkt")
2209 match.wildcards &= ~ofp.OFPFW_IN_PORT
2210
2211 def testPacket(title, pkt, result):
2212 act = action.action_output()
2213 pkts = [
2214 [title, pkt, result]
2215 ]
2216 self.testPktsAgainstFlow(pkts, act, match)
2217
2218 # Try incomplete IP headers
2219 testPacket("Incomplete IP header (1 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:1],
2222 self.RESULT_NOMATCH,
2223 )
2224 testPacket("Incomplete IP header (2 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:2],
2227 self.RESULT_NOMATCH,
2228 )
2229 testPacket("Incomplete IP header (3 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:3],
2232 self.RESULT_NOMATCH,
2233 )
2234 testPacket("Incomplete IP header (12 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:12],
2237 self.RESULT_NOMATCH,
2238 )
2239 testPacket("Incomplete IP header (16 bytes)",
2240 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2241 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:16],
2242 self.RESULT_NOMATCH,
2243 )
2244 testPacket("Incomplete IP header (19 bytes)",
2245 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2246 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto))[0:19],
2247 self.RESULT_NOMATCH,
2248 )
2249
2250 # Try variations where the TCP header is missing or incomplete. As we
2251 # saw bugs before where buffers were reused and lengths weren't honored,
2252 # we initiatlize once with a non-matching full packet and once with a
2253 # matching full packet.
2254 testPacket("Non-Matching TCP packet, warming buffer",
2255 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2256 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2257 tp(sport=tcp_sport, dport=tcp_dport + 1),
2258 self.RESULT_NOMATCH,
2259 )
2260 testPacket("Missing TCP header, buffer warmed with non-match",
2261 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2262 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2263 self.RESULT_NOMATCH,
2264 )
2265 testPacket("Matching TCP packet, warming buffer",
2266 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2267 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2268 tp(sport=tcp_sport, dport=tcp_dport),
2269 self.RESULT_MATCH,
2270 )
2271 testPacket("Missing TCP header, buffer warmed with match",
2272 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2273 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto),
2274 self.RESULT_NOMATCH,
2275 )
2276 testPacket("Truncated TCP header: 2 bytes",
2277 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2278 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2279 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:2]),
2280 self.RESULT_NOMATCH,
2281 )
2282
2283 # Play with IP header length values that put the start of TCP either
2284 # inside the generated TCP header or beyond. In some cases it may even
2285 # be beyond the packet boundary. Also play with IP options and more
2286 # importantly IP total length corruptions.
2287 testPacket("TCP packet, corrupt ihl (0x6)",
2288 simple_tcp_packet(ip_ihl=6),
2289 self.RESULT_NOMATCH,
2290 )
2291 testPacket("TCP packet, corrupt ihl (0xf)",
2292 simple_tcp_packet(ip_ihl=0xf), # ihl = 15 * 4 = 60
2293 self.RESULT_NOMATCH,
2294 )
2295 testPacket("TCP packet, corrupt ihl and total length",
2296 simple_tcp_packet(ip_ihl=0xf, pktlen=56), # ihl = 15 * 4 = 60,
2297 self.RESULT_NOMATCH,
2298 )
2299 testPacket("Corrupt IPoption: First 4 bytes of matching TCP header",
2300 simple_tcp_packet(
2301 ip_options=scapy.IPOption('\x04\xd2\x00\x50'),
2302 tcp_dport=2, tcp_sport=2
2303 ),
2304 self.RESULT_NOMATCH,
2305 )
2306 testPacket("Missing TCP header, corrupt ihl",
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),
2309 self.RESULT_NOMATCH,
2310 )
2311 testPacket("Missing TCP header, corrupt total length",
2312 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2313 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, len= 100),
2314 self.RESULT_NOMATCH,
2315 )
2316 testPacket("Missing TCP header, corrupt ihl and total length",
2317 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2318 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=0xf, proto=proto, len=43),
2319 self.RESULT_NOMATCH,
2320 )
2321 testPacket("Incomplete IP header (12 bytes), corrupt ihl and total length",
2322 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2323 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:12],
2324 self.RESULT_NOMATCH,
2325 )
2326 testPacket("Incomplete IP header (16 bytes), corrupt ihl and total length",
2327 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2328 str(scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto, ihl=10, len=43))[0:16],
2329 self.RESULT_NOMATCH,
2330 )
2331
2332 # Try an incomplete TCP header that has enough bytes to carry source and
2333 # destination ports. As that is all we care about during matching, some
2334 # implementations may match and some may drop the packet
2335 testPacket("Incomplete TCP header: src/dst port present",
2336 scapy.Ether(dst=dl_dst, src=dl_src)/ \
2337 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=proto)/ \
2338 (str(tp(sport=tcp_sport, dport=tcp_dport))[0:4]),
2339 self.RESULT_ANY,
2340 )
2341
2342 for i in range(1):
2343 for length in range(40 / 4): # IPv4 options are a maximum of 40 in length
2344 bytes = "".join([("%c" % random.randint(0, 255)) for x in range(length * 4)])
2345 eth = scapy.Ether(dst=dl_dst, src=dl_src)
2346 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2347 tcp = tp(sport=tcp_sport, dport=tcp_dport+1)
2348 pkt = eth / ip
2349 pkt = pkt / bytes
2350 pkt = pkt / str(tcp)
2351 testPacket("Random IP options len = %d - TP match must fail" % length * 4,
2352 pkt,
2353 self.RESULT_NOMATCH
2354 )
2355
2356 eth = scapy.Ether(dst=dl_dst, src=dl_src)
2357 ip = scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, ihl=5 + length, proto=proto)
2358 tcp = tp(sport=tcp_sport, dport=tcp_dport)
2359 pkt = eth / ip
2360 pkt = pkt / bytes
2361 pkt = pkt / str(tcp)
2362
2363 testPacket("Random IP options len = %d - May match",
2364 pkt,
2365 self.RESULT_ANY
2366 )
2367
2368
2369class DirectBadIpTcpPackets(DirectBadIpTcpPacketsBase):
2370 """
2371 Verify IP/TCP parsing and matching. Focus on packet corruptions
2372 """
2373 def runTest(self):
2374 self.runTestWithProto(protoName = 'TCP')
2375
2376class DirectBadIpUdpPackets(DirectBadIpTcpPacketsBase):
2377 """
2378 Verify IP/UDP parsing and matching. Focus on packet corruptions
2379 """
2380 def runTest(self):
2381 self.runTestWithProto(protoName = 'UDP')
2382
2383class DirectBadLlcPackets(DirectBadPacketBase):
2384 """
2385 Verify LLC/SNAP parsing and matching. Focus on packet corruptions
2386 """
2387 def runTest(self):
2388 dl_dst='00:01:02:03:04:05'
2389 dl_src='00:06:07:08:09:0a'
2390 ip_src='192.168.0.1'
2391 ip_dst='192.168.0.2'
2392 ip_tos=0
2393 tcp_sport=1234
2394 tcp_dport=80
2395
2396 IS_SNAP_IP = 1
2397 IS_SNAP_IP_CORRUPT = 2
2398 IS_NOT_SNAP_IP = 3
2399
2400 def testPacketTcpMatch(title, llc):
2401 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)/ \
2402 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos)/ \
2403 scapy.TCP(sport=tcp_sport, dport=tcp_dport)
2404 match = packet_to_flow_match(self, match_pkt)
2405 self.assertTrue(match is not None,
2406 "Could not generate flow match from pkt")
2407 match.wildcards &= ~ofp.OFPFW_IN_PORT
2408 act = action.action_output()
2409
2410 self.testPktsAgainstFlow(
2411 [[
2412 "TCP match - LLC frame correct length - %s" % title,
2413 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2414 self.RESULT_ANY,
2415 ]],
2416 act, match
2417 )
2418
2419 # Corrupt length field
2420 ethLen = random.randint(0, 1535)
2421 self.testPktsAgainstFlow(
2422 [[
2423 "TCP match - LLC frame corrupted length - %s" % title,
2424 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
2425 self.RESULT_ANY,
2426 ]],
2427 act, match
2428 )
2429
2430 def testPacketEthSrcDstMatch(title, llc):
2431 # Matching based on Ethernet source and destination
2432 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src)
2433 match = packet_to_flow_match(self, match_pkt)
2434 self.assertTrue(match is not None,
2435 "Could not generate flow match from pkt")
2436 match.wildcards &= ~ofp.OFPFW_IN_PORT
2437 match.wildcards |= ofp.OFPFW_DL_TYPE
2438 self.testPktsAgainstFlow(
2439 [[
2440 "Eth addr match - LLC frame correct length- %s" % title,
2441 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2442 self.RESULT_MATCH,
2443 ]],
2444 action.action_output(), match
2445 )
2446
2447 # Corrupt length field
2448 ethLen = random.randint(0, 1535)
2449 self.testPktsAgainstFlow(
2450 [[
2451 "Eth addr match - LLC frame corrupted length- %s" % title,
2452 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
2453 self.RESULT_ANY,
2454 ]],
2455 action.action_output(), match
2456 )
2457
2458 def testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip):
2459 # Matching based on Ethernet source, destination and type
2460 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src, type=0x800)
2461 match = packet_to_flow_match(self, match_pkt)
2462 self.assertTrue(match is not None,
2463 "Could not generate flow match from pkt")
2464 match.wildcards &= ~ofp.OFPFW_IN_PORT
2465 if is_snap_ip == IS_SNAP_IP:
2466 is_match = self.RESULT_MATCH
2467 elif is_snap_ip == IS_SNAP_IP_CORRUPT:
2468 is_match = self.RESULT_ANY
2469 else:
2470 is_match = self.RESULT_NOMATCH
2471 self.testPktsAgainstFlow(
2472 [[
2473 "Eth addr+type match - LLC frame correct length - %s" % title,
2474 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2475 is_match,
2476 ]],
2477 action.action_output(), match
2478 )
2479
2480 # Corrupt length field
2481 ethLen = random.randint(0, 1535)
2482 self.testPktsAgainstFlow(
2483 [[
2484 "Eth addr+type match - LLC frame corrupted length - %s" % title,
2485 scapy.Ether(dst=dl_dst, src=dl_src, type=ethLen) / llc,
Christian Dickmanne9b6d252012-10-08 22:56:50 -07002486 self.RESULT_ANY,
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002487 ]],
2488 action.action_output(), match
2489 )
2490
2491 def testPacket(title, llc, is_snap_ip):
2492 testPacketTcpMatch(title, llc)
2493 testPacketEthSrcDstMatch(title, llc)
2494 testPacketEthSrcDstTypeMatch(title, llc, is_snap_ip)
2495
2496 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002497 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002498 IS_NOT_SNAP_IP,
2499 )
2500 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002501 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002502 IS_NOT_SNAP_IP,
2503 )
2504 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002505 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002506 IS_NOT_SNAP_IP,
2507 )
2508 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002509 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002510 IS_NOT_SNAP_IP,
2511 )
2512 testPacket("LLC - SNAP - Small bogus payload",
2513 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2514 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2515 IS_SNAP_IP_CORRUPT,
2516 )
2517 testPacket("LLC - SNAP - Max -1 bogus payload",
2518 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2519 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2520 IS_NOT_SNAP_IP,
2521 )
2522 testPacket("LLC - SNAP - Max bogus payload",
2523 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2524 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2525 IS_NOT_SNAP_IP,
2526 )
2527 testPacket("LLC - SNAP - IP - TCP",
2528 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2529 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2530 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2531 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2532 IS_SNAP_IP,
2533 )
2534
2535
2536class DirectLlcPackets(DirectBadPacketBase):
2537 """
2538 Verify LLC/SNAP parsing (valid and corrupted packets) and matching
2539 """
2540 def runTest(self):
2541 dl_dst='00:01:02:03:04:05'
2542 dl_src='00:06:07:08:09:0a'
2543 ip_src='192.168.0.1'
2544 ip_dst='192.168.0.2'
2545 ip_tos=0
2546 tcp_sport=1234
2547 tcp_dport=80
2548
2549 # Test ethertype in face of LLC/SNAP and OFP_DL_TYPE_NOT_ETH_TYPE
2550 IS_SNAP_NOT_IP = 1
2551 IS_SNAP_AND_IP = 2
2552 IS_NOT_SNAP = 3
2553
2554 def testPacketEthTypeIP(title, llc, is_snap):
2555 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src, type=0x800)
2556 match = packet_to_flow_match(self, match_pkt)
2557 self.assertTrue(match is not None,
2558 "Could not generate flow match from pkt")
2559 match.wildcards &= ~ofp.OFPFW_IN_PORT
2560 pkts = []
2561 if is_snap == IS_NOT_SNAP or is_snap == IS_SNAP_NOT_IP:
2562 result = self.RESULT_NOMATCH
2563 else:
2564 result = self.RESULT_MATCH
2565 pkts.append([
2566 "Ether type 0x800 match - %s" % title,
2567 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2568 result,
2569 ])
2570 act = action.action_output()
2571 self.testPktsAgainstFlow(pkts, act, match)
2572
2573 def testPacketEthTypeNotEth(title, llc, is_snap):
2574 match_pkt = scapy.Ether(dst = dl_dst, src = dl_src,
2575 type = ofp.OFP_DL_TYPE_NOT_ETH_TYPE)
2576 match = packet_to_flow_match(self, match_pkt)
2577 self.assertTrue(match is not None,
2578 "Could not generate flow match from pkt")
2579 match.wildcards &= ~ofp.OFPFW_IN_PORT
2580 pkts = []
2581 if is_snap == IS_NOT_SNAP:
2582 result = self.RESULT_MATCH
2583 else:
2584 result = self.RESULT_NOMATCH
2585 pkts.append([
2586 "Ether type OFP_DL_TYPE_NOT_ETH_TYPE match - %s" % title,
2587 scapy.Ether(dst=dl_dst, src=dl_src, type=len(llc)) / llc,
2588 result,
2589 ])
2590 act = action.action_output()
2591 self.testPktsAgainstFlow(pkts, act, match)
2592
2593 def testPacket(title, llc, is_snap):
2594 testPacketEthTypeIP(title, llc, is_snap)
2595 testPacketEthTypeNotEth(title, llc, is_snap)
2596
2597 testPacket("LLC - No SNAP - No Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002598 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03),
2599 IS_NOT_SNAP,
2600 )
2601 testPacket("LLC (with information field) - No SNAP - No Payload",
2602 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x12) / "S",
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002603 IS_NOT_SNAP,
2604 )
2605 testPacket("LLC - No SNAP - Small Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002606 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * 10),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002607 IS_NOT_SNAP,
2608 )
2609 testPacket("LLC - No SNAP - Max -1 Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002610 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3 - 1)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002611 IS_NOT_SNAP,
2612 )
2613 testPacket("LLC - No SNAP - Max Payload",
Rich Lane6508ea02012-10-12 15:27:11 -07002614 scapy.LLC(dsap=0x33, ssap=0x44, ctrl=0x03) / ("S" * (1500 - 3)),
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002615 IS_NOT_SNAP,
2616 )
2617 testPacket("LLC - SNAP - Non-default OUI",
2618 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2619 scapy.SNAP(OUI=0x000001, code=0x800) / ("S" * 10),
2620 IS_NOT_SNAP,
2621 )
2622 testPacket("LLC - SNAP - Default OUI",
2623 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2624 scapy.SNAP(OUI=0x000000, code=0x800) / ("S" * 10),
2625 IS_SNAP_AND_IP,
2626 )
2627 testPacket("LLC - SNAP - Max -1 bogus payload",
2628 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2629 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5 - 1)),
2630 IS_SNAP_NOT_IP,
2631 )
2632 testPacket("LLC - SNAP - Max bogus payload",
2633 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2634 scapy.SNAP(OUI=0x000000, code=0x3) / ("S" * (1500 - 3 - 5)),
2635 IS_SNAP_NOT_IP,
2636 )
2637 testPacket("LLC - SNAP - IP - TCP",
2638 scapy.LLC(dsap=0xaa, ssap=0xaa, ctrl=0x03)/ \
2639 scapy.SNAP(OUI=0x000000, code=0x800)/ \
2640 scapy.IP(src=ip_src, dst=ip_dst, tos=ip_tos, proto=6)/ \
2641 scapy.TCP(sport=tcp_sport, dport=tcp_dport),
2642 IS_SNAP_AND_IP,
2643 )
2644
2645
2646class DirectArpPackets(DirectBadPacketBase):
2647 """
2648 Verify ARP parsing (valid and corrupted packets) and ARP matching
2649 """
2650 def runTest(self):
2651 self.testArpHandling()
2652
2653 def testArpHandling(self):
2654 dl_dst='00:01:02:03:04:05'
2655 dl_src='00:06:07:08:09:0a'
2656 ip_src='192.168.0.1'
2657 ip_dst='192.168.0.2'
2658 ip_src2='192.168.1.1'
2659 ip_dst2='192.168.1.2'
2660 ip_tos=0
2661 tcp_sport=1234
2662 tcp_dport=80
2663
2664 def testPacket(title, arp_match, arp_pkt, result):
2665 pkts = []
2666
2667 match_pkt = scapy.Ether(dst=dl_dst, src=dl_src) / arp_match
2668 match = packet_to_flow_match(self, match_pkt)
2669 self.assertTrue(match is not None,
2670 "Could not generate flow match from pkt")
2671 match.wildcards &= ~ofp.OFPFW_IN_PORT
2672
2673 pkts.append([
2674 title,
2675 scapy.Ether(dst=dl_dst, src=dl_src) / arp_pkt,
2676 result,
2677 ])
2678
2679 act = action.action_output()
2680 self.testPktsAgainstFlow(pkts, act, match)
2681
2682 testPacket("Basic ARP",
2683 scapy.ARP(psrc=ip_src, pdst=ip_dst, op = 1),
2684 scapy.ARP(hwdst = '00:00:00:00:00:00', hwsrc = dl_src,
2685 psrc = ip_src, pdst = ip_dst, hwlen = 6, plen = 4,
2686 ptype = 0x800, hwtype = 1, op = 1),
2687 self.RESULT_MATCH
2688 )
2689 # More stuff:
2690 # - Non matches on any property
2691 # - Corrupted hwlen and plen
2692 # - Other hwtype, ptype
2693 # - Truncated ARP pkt
2694
2695
2696class DirectVlanPackets(DirectBadPacketBase):
2697 """
2698 Verify VLAN parsing (valid and corrupted packets) and ARP matching
2699 """
2700 def runTest(self):
2701 dl_dst='00:01:02:03:04:05'
2702 dl_src='00:06:07:08:09:0a'
2703 ip_src='192.168.0.1'
2704 ip_dst='192.168.0.2'
2705 ip_src2='192.168.1.1'
2706 ip_dst2='192.168.1.2'
2707 ip_tos=0
2708 tcp_sport=1234
2709 tcp_dport=80
2710
2711 def testPacket(title, match, pkt, result):
2712 pkts = []
2713
2714 self.assertTrue(match is not None,
2715 "Could not generate flow match from pkt")
2716 match.wildcards &= ~ofp.OFPFW_IN_PORT
2717
2718 pkts.append([
2719 "%s" % title,
2720 pkt,
2721 result,
2722 ])
2723
2724 act = action.action_output()
2725 self.testPktsAgainstFlow(pkts, act, match)
2726
2727 testPacket("Basic MAC matching - IPv4 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=0x800) / scapy.IP(),
2730 self.RESULT_MATCH
2731 )
2732 testPacket("Basic MAC matching - VMware beacon - no 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, type=0x8922),
2735 self.RESULT_MATCH
2736 )
2737 testPacket("Basic MAC matching - VMware beacon - with payload",
2738 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2739 scapy.Ether(dst=dl_dst, src=dl_src, type=0x8922)/ ("X" * 1),
2740 self.RESULT_MATCH
2741 )
2742 testPacket("Basic MAC matching - IPv6 payload",
2743 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2744 scapy.Ether(dst=dl_dst, src=dl_src) / scapy.IPv6(),
2745 self.RESULT_MATCH
2746 )
2747 testPacket("Basic MAC matching with VLAN tag present",
2748 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src)),
2749 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002750 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002751 scapy.IP(),
2752 self.RESULT_MATCH
2753 )
2754 testPacket("Basic MAC matching with VLAN tag present",
2755 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2756 dl_type=0x800),
2757 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002758 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002759 scapy.IP(),
2760 self.RESULT_MATCH
2761 )
2762 testPacket("Ether matching with VLAN tag present - No type match",
2763 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2764 dl_type=0x801),
2765 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002766 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002767 scapy.IP(),
2768 self.RESULT_NOMATCH
2769 )
2770 testPacket("Ether matching with VLAN tag present - No type match 0x8100",
2771 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2772 dl_type=0x8100),
2773 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002774 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002775 scapy.IP(),
2776 self.RESULT_NOMATCH
2777 )
2778 testPacket("Ether matching with double VLAN tag - Wrong type match",
2779 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2780 dl_type=0x800),
2781 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002782 scapy.Dot1Q(prio=5, vlan=1000)/ \
2783 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002784 scapy.IP(),
2785 self.RESULT_NOMATCH
2786 )
2787 testPacket("Ether matching with double VLAN tag - Type match",
2788 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2789 dl_type=0x8100),
2790 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002791 scapy.Dot1Q(prio=5, vlan=1000)/ \
2792 scapy.Dot1Q(prio=3, vlan=1005)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002793 scapy.IP(),
2794 self.RESULT_MATCH
2795 )
2796 testPacket("IP matching - VLAN tag",
2797 self.createMatch(dl_dst=parse_mac(dl_dst), dl_src=parse_mac(dl_src),
2798 dl_type=0x0800,
2799 nw_src=parse_ip(ip_src), nw_dst=parse_ip(ip_dst)),
2800 scapy.Ether(dst=dl_dst, src=dl_src)/ \
Christian Dickmann8ac55252012-10-08 22:53:49 -07002801 scapy.Dot1Q(prio=5, vlan=1000)/ \
Christian Dickmann8b59b4b2012-09-23 16:48:30 -07002802 scapy.IP(src=ip_src, dst=ip_dst),
2803 self.RESULT_MATCH
2804 )
2805 # XXX:
2806 # - Matching on VLAN ID and Prio
2807 # - Actions
2808
2809
2810
Dan Talayco9f47f4d2010-06-03 13:54:37 -07002811if __name__ == "__main__":
2812 print "Please run through oft script: ./oft --test_spec=basic"