blob: c2d4a683ccba46f75c3565902a133bfcc64be1bb [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
10 The function test_set_init is called with a complete configuration
11dictionary prior to the invocation of any tests from this file.
12
13 The switch is actively attempting to contact the controller at the address
14indicated oin oft_config
15
16"""
17
Dan Talayco9f47f4d2010-06-03 13:54:37 -070018import copy
19
Dan Talayco5eba8442010-03-10 13:58:43 -080020import logging
21
22import unittest
23
24import oftest.controller as controller
25import oftest.cstruct as ofp
26import oftest.message as message
27import oftest.dataplane as dataplane
28import oftest.action as action
29import oftest.parse as parse
30import basic
31
32from testutils import *
33
34#@var port_map Local copy of the configuration map from OF port
35# numbers to OS interfaces
36pa_port_map = None
37#@var pa_logger Local logger object
38pa_logger = None
39#@var pa_config Local copy of global configuration data
40pa_config = None
41
Dan Talayco551befa2010-07-15 17:05:32 -070042# For test priority
43#@var test_prio Set test priority for local tests
44test_prio = {}
45
46WILDCARD_VALUES = [ofp.OFPFW_IN_PORT,
47 ofp.OFPFW_DL_VLAN,
48 ofp.OFPFW_DL_SRC,
49 ofp.OFPFW_DL_DST,
50 ofp.OFPFW_DL_TYPE,
51 ofp.OFPFW_NW_PROTO,
52 ofp.OFPFW_TP_SRC,
53 ofp.OFPFW_TP_DST,
54 0x3F << ofp.OFPFW_NW_SRC_SHIFT,
55 0x3F << ofp.OFPFW_NW_DST_SHIFT,
56 ofp.OFPFW_DL_VLAN_PCP,
57 ofp.OFPFW_NW_TOS]
58
59MODIFY_ACTION_VALUES = [ofp.OFPAT_SET_VLAN_VID,
60 ofp.OFPAT_SET_VLAN_PCP,
61 ofp.OFPAT_STRIP_VLAN,
62 ofp.OFPAT_SET_DL_SRC,
63 ofp.OFPAT_SET_DL_DST,
64 ofp.OFPAT_SET_NW_SRC,
65 ofp.OFPAT_SET_NW_DST,
66 ofp.OFPAT_SET_NW_TOS,
67 ofp.OFPAT_SET_TP_SRC,
68 ofp.OFPAT_SET_TP_DST]
69
70# Cache supported features to avoid transaction overhead
71cached_supported_actions = None
72
Dan Talayco21381562010-07-17 00:34:47 -070073TEST_VID_DEFAULT = 2
74
Dan Talayco5eba8442010-03-10 13:58:43 -080075def test_set_init(config):
76 """
77 Set up function for packet action test classes
78
79 @param config The configuration dictionary; see oft
80 """
81
82 global pa_port_map
83 global pa_logger
84 global pa_config
85
86 pa_logger = logging.getLogger("pkt_act")
87 pa_logger.info("Initializing test set")
88 pa_port_map = config["port_map"]
89 pa_config = config
90
91class DirectPacket(basic.SimpleDataPlane):
92 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -070093 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -080094
95 Generate a packet
96 Generate and install a matching flow
97 Add action to direct the packet to an egress port
98 Send the packet to ingress dataplane port
99 Verify the packet is received at the egress port only
100 """
101 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700102 self.handleFlow()
103
104 def handleFlow(self, pkttype='TCP'):
Dan Talayco5eba8442010-03-10 13:58:43 -0800105 of_ports = pa_port_map.keys()
106 of_ports.sort()
107 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
108
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700109 if (pkttype == 'ICMP'):
110 pkt = simple_icmp_packet()
111 else:
112 pkt = simple_tcp_packet()
Dan Talayco5eba8442010-03-10 13:58:43 -0800113 match = parse.packet_to_flow_match(pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -0700114 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -0800115 self.assertTrue(match is not None,
116 "Could not generate flow match from pkt")
117 act = action.action_output()
118
119 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700120 rv = delete_all_flows(self.controller, pa_logger)
121 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700122
Dan Talayco5eba8442010-03-10 13:58:43 -0800123 ingress_port = of_ports[idx]
124 egress_port = of_ports[(idx + 1) % len(of_ports)]
125 pa_logger.info("Ingress " + str(ingress_port) +
Dan Talayco551befa2010-07-15 17:05:32 -0700126 " to egress " + str(egress_port))
Dan Talayco5eba8442010-03-10 13:58:43 -0800127
128 match.in_port = ingress_port
129
130 request = message.flow_mod()
131 request.match = match
132 request.buffer_id = 0xffffffff
133 act.port = egress_port
134 self.assertTrue(request.actions.add(act), "Could not add action")
135
136 pa_logger.info("Inserting flow")
137 rv = self.controller.message_send(request)
138 self.assertTrue(rv != -1, "Error installing flow mod")
139 do_barrier(self.controller)
140
141 pa_logger.info("Sending packet to dp port " +
142 str(ingress_port))
143 self.dataplane.send(ingress_port, str(pkt))
144 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(timeout=1)
145 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700146 pa_logger.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
152class DirectPacketICMP(DirectPacket):
153 """
154 Send ICMP packet to single egress port
155
156 Generate a ICMP packet
157 Generate and install a matching flow
158 Add action to direct the packet to an egress port
159 Send the packet to ingress dataplane port
160 Verify the packet is received at the egress port only
161 Difference from DirectPacket test is that sent packet is ICMP
162 """
163 def runTest(self):
164 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700165
166class DirectTwoPorts(basic.SimpleDataPlane):
167 """
168 Send packet to two egress ports
169
170 Generate a packet
171 Generate and install a matching flow
172 Add action to direct the packet to two egress ports
173 Send the packet to ingress dataplane port
174 Verify the packet is received at the two egress ports
175 """
176 def runTest(self):
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700177 of_ports = pa_port_map.keys()
178 of_ports.sort()
179 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
180
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700181 pkt = simple_tcp_packet()
182 match = parse.packet_to_flow_match(pkt)
183 match.wildcards &= ~ofp.OFPFW_IN_PORT
184 self.assertTrue(match is not None,
185 "Could not generate flow match from pkt")
186 act = action.action_output()
187
188 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700189 rv = delete_all_flows(self.controller, pa_logger)
190 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700191
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700192 ingress_port = of_ports[idx]
193 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
194 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
195 pa_logger.info("Ingress " + str(ingress_port) +
196 " to egress " + str(egress_port1) + " and " +
197 str(egress_port2))
198
199 match.in_port = ingress_port
200
201 request = message.flow_mod()
202 request.match = match
203 request.buffer_id = 0xffffffff
204 act.port = egress_port1
205 self.assertTrue(request.actions.add(act), "Could not add action1")
206 act.port = egress_port2
207 self.assertTrue(request.actions.add(act), "Could not add action2")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700208 # pa_logger.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700209
210 pa_logger.info("Inserting flow")
211 rv = self.controller.message_send(request)
212 self.assertTrue(rv != -1, "Error installing flow mod")
213 do_barrier(self.controller)
214
215 pa_logger.info("Sending packet to dp port " +
216 str(ingress_port))
217 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700218 yes_ports = set([egress_port1, egress_port2])
219 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700220
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700221 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
222 self, pa_logger)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700223
224class DirectMCNonIngress(basic.SimpleDataPlane):
225 """
226 Multicast to all non-ingress ports
227
228 Generate a packet
229 Generate and install a matching flow
230 Add action to direct the packet to all non-ingress ports
231 Send the packet to ingress dataplane port
232 Verify the packet is received at all non-ingress ports
233
234 Does not use the flood action
235 """
236 def runTest(self):
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700237 of_ports = pa_port_map.keys()
238 of_ports.sort()
239 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
240
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700241 pkt = simple_tcp_packet()
242 match = parse.packet_to_flow_match(pkt)
243 match.wildcards &= ~ofp.OFPFW_IN_PORT
244 self.assertTrue(match is not None,
245 "Could not generate flow match from pkt")
246 act = action.action_output()
247
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700248 for ingress_port in of_ports:
249 rv = delete_all_flows(self.controller, pa_logger)
250 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700251
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700252 pa_logger.info("Ingress " + str(ingress_port) +
253 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700254 match.in_port = ingress_port
255
256 request = message.flow_mod()
257 request.match = match
258 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700259 for egress_port in of_ports:
260 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700261 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700262 act.port = egress_port
263 self.assertTrue(request.actions.add(act),
264 "Could not add output to " + str(egress_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700265 pa_logger.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700266
267 pa_logger.info("Inserting flow")
268 rv = self.controller.message_send(request)
269 self.assertTrue(rv != -1, "Error installing flow mod")
270 do_barrier(self.controller)
271
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700272 pa_logger.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700273 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700274 yes_ports = set(of_ports).difference([ingress_port])
275 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
276 self, pa_logger)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700277
Dan Talayco32fa6542010-05-11 15:54:08 -0700278
279class DirectMC(basic.SimpleDataPlane):
280 """
281 Multicast to all ports including ingress
282
283 Generate a packet
284 Generate and install a matching flow
285 Add action to direct the packet to all non-ingress ports
286 Send the packet to ingress dataplane port
287 Verify the packet is received at all ports
288
289 Does not use the flood action
290 """
291 def runTest(self):
Dan Talayco32fa6542010-05-11 15:54:08 -0700292 of_ports = pa_port_map.keys()
293 of_ports.sort()
294 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
295
Dan Talayco32fa6542010-05-11 15:54:08 -0700296 pkt = simple_tcp_packet()
297 match = parse.packet_to_flow_match(pkt)
298 match.wildcards &= ~ofp.OFPFW_IN_PORT
299 self.assertTrue(match is not None,
300 "Could not generate flow match from pkt")
301 act = action.action_output()
302
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700303 for ingress_port in of_ports:
304 rv = delete_all_flows(self.controller, pa_logger)
305 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700306
Dan Talayco32fa6542010-05-11 15:54:08 -0700307 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700308 match.in_port = ingress_port
309
310 request = message.flow_mod()
311 request.match = match
312 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700313 for egress_port in of_ports:
314 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700315 act.port = ofp.OFPP_IN_PORT
316 else:
317 act.port = egress_port
318 self.assertTrue(request.actions.add(act),
319 "Could not add output to " + str(egress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700320 # pa_logger.info(request.show())
321
322 pa_logger.info("Inserting flow")
323 rv = self.controller.message_send(request)
324 self.assertTrue(rv != -1, "Error installing flow mod")
325 do_barrier(self.controller)
326
327 pa_logger.info("Sending packet to dp port " + str(ingress_port))
328 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700329 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
330 pa_logger)
Dan Talayco2e77a842010-05-12 15:39:46 -0700331
332class Flood(basic.SimpleDataPlane):
333 """
334 Flood to all ports except ingress
335
336 Generate a packet
337 Generate and install a matching flow
338 Add action to flood the packet
339 Send the packet to ingress dataplane port
340 Verify the packet is received at all other ports
341 """
342 def runTest(self):
Dan Talayco2e77a842010-05-12 15:39:46 -0700343 of_ports = pa_port_map.keys()
344 of_ports.sort()
345 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
346
347 pkt = simple_tcp_packet()
348 match = parse.packet_to_flow_match(pkt)
349 match.wildcards &= ~ofp.OFPFW_IN_PORT
350 self.assertTrue(match is not None,
351 "Could not generate flow match from pkt")
352 act = action.action_output()
353
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700354 for ingress_port in of_ports:
355 rv = delete_all_flows(self.controller, pa_logger)
356 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700357
Dan Talayco2e77a842010-05-12 15:39:46 -0700358 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700359 match.in_port = ingress_port
360
361 request = message.flow_mod()
362 request.match = match
363 request.buffer_id = 0xffffffff
364 act.port = ofp.OFPP_FLOOD
365 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700366 "Could not add flood port action")
Dan Talayco32fa6542010-05-11 15:54:08 -0700367 pa_logger.info(request.show())
368
369 pa_logger.info("Inserting flow")
370 rv = self.controller.message_send(request)
371 self.assertTrue(rv != -1, "Error installing flow mod")
372 do_barrier(self.controller)
373
374 pa_logger.info("Sending packet to dp port " + str(ingress_port))
375 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700376 yes_ports = set(of_ports).difference([ingress_port])
377 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
378 self, pa_logger)
Dan Talayco3be5b062010-05-12 15:46:21 -0700379
Dan Talayco3be5b062010-05-12 15:46:21 -0700380class FloodPlusIngress(basic.SimpleDataPlane):
381 """
382 Flood to all ports plus send to ingress port
383
384 Generate a packet
385 Generate and install a matching flow
386 Add action to flood the packet
387 Add action to send to ingress port
388 Send the packet to ingress dataplane port
389 Verify the packet is received at all other ports
390 """
391 def runTest(self):
Dan Talayco3be5b062010-05-12 15:46:21 -0700392 of_ports = pa_port_map.keys()
393 of_ports.sort()
394 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
395
396 pkt = simple_tcp_packet()
397 match = parse.packet_to_flow_match(pkt)
398 match.wildcards &= ~ofp.OFPFW_IN_PORT
399 self.assertTrue(match is not None,
400 "Could not generate flow match from pkt")
401 act = action.action_output()
402
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700403 for ingress_port in of_ports:
404 rv = delete_all_flows(self.controller, pa_logger)
405 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700406
Dan Talayco3be5b062010-05-12 15:46:21 -0700407 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700408 match.in_port = ingress_port
409
410 request = message.flow_mod()
411 request.match = match
412 request.buffer_id = 0xffffffff
413 act.port = ofp.OFPP_FLOOD
414 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700415 "Could not add flood port action")
416 act.port = ofp.OFPP_IN_PORT
417 self.assertTrue(request.actions.add(act),
418 "Could not add ingress port for output")
419 pa_logger.info(request.show())
420
421 pa_logger.info("Inserting flow")
422 rv = self.controller.message_send(request)
423 self.assertTrue(rv != -1, "Error installing flow mod")
424 do_barrier(self.controller)
425
426 pa_logger.info("Sending packet to dp port " + str(ingress_port))
427 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700428 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
429 pa_logger)
Dan Talayco4aa13122010-05-12 15:54:44 -0700430
431class All(basic.SimpleDataPlane):
432 """
433 Send to OFPP_ALL port
434
435 Generate a packet
436 Generate and install a matching flow
437 Add action to forward to OFPP_ALL
438 Send the packet to ingress dataplane port
439 Verify the packet is received at all other ports
440 """
441 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700442 of_ports = pa_port_map.keys()
443 of_ports.sort()
444 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
445
446 pkt = simple_tcp_packet()
447 match = parse.packet_to_flow_match(pkt)
448 match.wildcards &= ~ofp.OFPFW_IN_PORT
449 self.assertTrue(match is not None,
450 "Could not generate flow match from pkt")
451 act = action.action_output()
452
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700453 for ingress_port in of_ports:
454 rv = delete_all_flows(self.controller, pa_logger)
455 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700456
Dan Talayco4aa13122010-05-12 15:54:44 -0700457 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700458 match.in_port = ingress_port
459
460 request = message.flow_mod()
461 request.match = match
462 request.buffer_id = 0xffffffff
463 act.port = ofp.OFPP_ALL
464 self.assertTrue(request.actions.add(act),
465 "Could not add ALL port action")
466 pa_logger.info(request.show())
467
468 pa_logger.info("Inserting flow")
469 rv = self.controller.message_send(request)
470 self.assertTrue(rv != -1, "Error installing flow mod")
471 do_barrier(self.controller)
472
473 pa_logger.info("Sending packet to dp port " + str(ingress_port))
474 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700475 yes_ports = set(of_ports).difference([ingress_port])
476 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
477 self, pa_logger)
Dan Talayco4aa13122010-05-12 15:54:44 -0700478
479class AllPlusIngress(basic.SimpleDataPlane):
480 """
481 Send to OFPP_ALL port and ingress port
482
483 Generate a packet
484 Generate and install a matching flow
485 Add action to forward to OFPP_ALL
486 Add action to forward to ingress port
487 Send the packet to ingress dataplane port
488 Verify the packet is received at all other ports
489 """
490 def runTest(self):
Dan Talayco4aa13122010-05-12 15:54:44 -0700491 of_ports = pa_port_map.keys()
492 of_ports.sort()
493 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
494
495 pkt = simple_tcp_packet()
496 match = parse.packet_to_flow_match(pkt)
497 match.wildcards &= ~ofp.OFPFW_IN_PORT
498 self.assertTrue(match is not None,
499 "Could not generate flow match from pkt")
500 act = action.action_output()
501
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700502 for ingress_port in of_ports:
503 rv = delete_all_flows(self.controller, pa_logger)
504 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700505
Dan Talayco4aa13122010-05-12 15:54:44 -0700506 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700507 match.in_port = ingress_port
508
509 request = message.flow_mod()
510 request.match = match
511 request.buffer_id = 0xffffffff
512 act.port = ofp.OFPP_ALL
513 self.assertTrue(request.actions.add(act),
514 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700515 act.port = ofp.OFPP_IN_PORT
516 self.assertTrue(request.actions.add(act),
517 "Could not add ingress port for output")
518 pa_logger.info(request.show())
519
520 pa_logger.info("Inserting flow")
521 rv = self.controller.message_send(request)
522 self.assertTrue(rv != -1, "Error installing flow mod")
523 do_barrier(self.controller)
524
525 pa_logger.info("Sending packet to dp port " + str(ingress_port))
526 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700527 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
528 pa_logger)
529
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700530class FloodMinusPort(basic.SimpleDataPlane):
531 """
532 Config port with No_Flood and test Flood action
533
534 Generate a packet
535 Generate a matching flow
536 Add action to forward to OFPP_ALL
537 Set port to no-flood
538 Send the packet to ingress dataplane port
539 Verify the packet is received at all other ports except
540 the ingress port and the no_flood port
541 """
542 def runTest(self):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700543 of_ports = pa_port_map.keys()
544 of_ports.sort()
545 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
546
547 pkt = simple_tcp_packet()
548 match = parse.packet_to_flow_match(pkt)
549 match.wildcards &= ~ofp.OFPFW_IN_PORT
550 self.assertTrue(match is not None,
551 "Could not generate flow match from pkt")
552 act = action.action_output()
553
554 for idx in range(len(of_ports)):
555 rv = delete_all_flows(self.controller, pa_logger)
556 self.assertEqual(rv, 0, "Failed to delete all flows")
557
558 ingress_port = of_ports[idx]
559 no_flood_idx = (idx + 1) % len(of_ports)
560 no_flood_port = of_ports[no_flood_idx]
561 rv = port_config_set(self.controller, no_flood_port,
562 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
563 pa_logger)
564 self.assertEqual(rv, 0, "Failed to set port config")
565
566 match.in_port = ingress_port
567
568 request = message.flow_mod()
569 request.match = match
570 request.buffer_id = 0xffffffff
571 act.port = ofp.OFPP_FLOOD
572 self.assertTrue(request.actions.add(act),
573 "Could not add flood port action")
574 pa_logger.info(request.show())
575
576 pa_logger.info("Inserting flow")
577 rv = self.controller.message_send(request)
578 self.assertTrue(rv != -1, "Error installing flow mod")
579 do_barrier(self.controller)
580
581 pa_logger.info("Sending packet to dp port " + str(ingress_port))
582 pa_logger.info("No flood port is " + str(no_flood_port))
583 self.dataplane.send(ingress_port, str(pkt))
584 no_ports = set([ingress_port, no_flood_port])
585 yes_ports = set(of_ports).difference(no_ports)
586 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self,
587 pa_logger)
588
589 # Turn no flood off again
590 rv = port_config_set(self.controller, no_flood_port,
591 0, ofp.OFPPC_NO_FLOOD, pa_logger)
592 self.assertEqual(rv, 0, "Failed to reset port config")
593
594 #@todo Should check no other packets received
595
Dan Talayco21381562010-07-17 00:34:47 -0700596
597
Dan Talayco551befa2010-07-15 17:05:32 -0700598################################################################
599
600class BaseMatchCase(basic.SimpleDataPlane):
601 def setUp(self):
602 basic.SimpleDataPlane.setUp(self)
603 self.logger = pa_logger
604 def runTest(self):
605 self.logger.info("BaseMatchCase")
606
607class ExactMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700608 """
Dan Talayco551befa2010-07-15 17:05:32 -0700609 Exercise exact matching for all port pairs
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700610
611 Generate a packet
612 Generate and install a matching flow without wildcard mask
613 Add action to forward to a port
614 Send the packet to the port
615 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700616 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700617
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700618 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700619 flow_match_test(self, pa_port_map)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700620
Dan Talayco551befa2010-07-15 17:05:32 -0700621class ExactMatchTagged(BaseMatchCase):
622 """
623 Exact match for all port pairs with tagged pkts
624 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700625
Dan Talayco551befa2010-07-15 17:05:32 -0700626 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700627 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700628 flow_match_test(self, pa_port_map, dl_vlan=vid)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700629
Dan Talayco551befa2010-07-15 17:05:32 -0700630class ExactMatchTaggedMany(BaseMatchCase):
631 """
632 ExactMatchTagged with many VLANS
633 """
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700634
Dan Talayco551befa2010-07-15 17:05:32 -0700635 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700636 for vid in range(2,100,10):
Dan Talayco551befa2010-07-15 17:05:32 -0700637 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
638 for vid in range(100,4000,389):
639 flow_match_test(self, pa_port_map, dl_vlan=vid, max_test=5)
640 flow_match_test(self, pa_port_map, dl_vlan=4094, max_test=5)
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700641
Dan Talayco551befa2010-07-15 17:05:32 -0700642# Don't run by default
643test_prio["ExactMatchTaggedMany"] = -1
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700644
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700645
Dan Talayco551befa2010-07-15 17:05:32 -0700646class SingleWildcardMatch(BaseMatchCase):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700647 """
648 Exercise wildcard matching for all ports
649
650 Generate a packet
651 Generate and install a matching flow with wildcard mask
652 Add action to forward to a port
653 Send the packet to the port
654 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700655 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700656 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700657 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700658 for wc in WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700659 flow_match_test(self, pa_port_map, wildcards=wc, max_test=10)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700660
Dan Talayco551befa2010-07-15 17:05:32 -0700661class SingleWildcardMatchTagged(BaseMatchCase):
662 """
663 SingleWildcardMatch with tagged packets
664 """
665 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700666 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700667 for wc in WILDCARD_VALUES:
Dan Talayco21381562010-07-17 00:34:47 -0700668 flow_match_test(self, pa_port_map, wildcards=wc, dl_vlan=vid,
Dan Talayco551befa2010-07-15 17:05:32 -0700669 max_test=10)
670
671class AllExceptOneWildcardMatch(BaseMatchCase):
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700672 """
Dan Talayco80b54ed2010-07-13 09:48:35 -0700673 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700674
675 Generate a packet
676 Generate and install a matching flow with wildcard all except one filed
677 Add action to forward to a port
678 Send the packet to the port
679 Verify the packet is received at all other ports (one port at a time)
680 Verify flow_expiration message is correct when command option is set
681 """
682 def runTest(self):
Dan Talayco551befa2010-07-15 17:05:32 -0700683 for wc in WILDCARD_VALUES:
684 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco21381562010-07-17 00:34:47 -0700685 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700686
Dan Talayco551befa2010-07-15 17:05:32 -0700687class AllExceptOneWildcardMatchTagged(BaseMatchCase):
688 """
689 Match one field with tagged packets
690 """
691 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700692 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700693 for wc in WILDCARD_VALUES:
694 all_exp_one_wildcard = ofp.OFPFW_ALL ^ wc
Dan Talayco21381562010-07-17 00:34:47 -0700695 flow_match_test(self, pa_port_map, wildcards=all_exp_one_wildcard,
696 dl_vlan=vid)
Dan Talayco551befa2010-07-15 17:05:32 -0700697
698class AllWildcardMatch(BaseMatchCase):
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700699 """
700 Create Wildcard-all flow and exercise for all ports
701
702 Generate a packet
703 Generate and install a matching flow with wildcard-all
704 Add action to forward to a port
705 Send the packet to the port
706 Verify the packet is received at all other ports (one port at a time)
707 Verify flow_expiration message is correct when command option is set
708 """
709 def runTest(self):
Dan Talayco21381562010-07-17 00:34:47 -0700710 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700711
Dan Talayco551befa2010-07-15 17:05:32 -0700712class AllWildcardMatchTagged(BaseMatchCase):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700713 """
Dan Talayco551befa2010-07-15 17:05:32 -0700714 AllWildcardMatch with tagged packets
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700715 """
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700716 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700717 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco21381562010-07-17 00:34:47 -0700718 flow_match_test(self, pa_port_map, wildcards=ofp.OFPFW_ALL,
719 dl_vlan=vid)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700720
Dan Talaycoba3745c2010-07-21 21:51:08 -0700721
Dan Talayco551befa2010-07-15 17:05:32 -0700722class AddVLANTag(BaseMatchCase):
723 """
724 Add a VLAN tag to an untagged packet
725 """
726 def runTest(self):
727 new_vid = 2
728 sup_acts = supported_actions_get(self)
729 if not(sup_acts & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700730 skip_message_emit(self, "Add VLAN tag test")
Dan Talaycof36f1082010-07-13 13:57:17 -0700731 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700732
Dan Talayco551befa2010-07-15 17:05:32 -0700733 len = 100
734 len_w_vid = 104
735 pkt = simple_tcp_packet(pktlen=len)
736 exp_pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
737 dl_vlan=new_vid)
738 vid_act = action.action_set_vlan_vid()
739 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700740
Dan Talayco551befa2010-07-15 17:05:32 -0700741 flow_match_test(self, pa_port_map, pkt=pkt,
742 exp_pkt=exp_pkt, action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700743
Dan Talayco551befa2010-07-15 17:05:32 -0700744class PacketOnly(basic.DataPlaneOnly):
745 """
746 Just send a packet thru the switch
747 """
748 def runTest(self):
749 pkt = simple_tcp_packet()
750 of_ports = pa_port_map.keys()
751 of_ports.sort()
752 ing_port = of_ports[0]
753 pa_logger.info("Sending packet to " + str(ing_port))
754 pa_logger.debug("Data: " + str(pkt).encode('hex'))
755 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700756
Dan Talayco551befa2010-07-15 17:05:32 -0700757class PacketOnlyTagged(basic.DataPlaneOnly):
758 """
759 Just send a packet thru the switch
760 """
761 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700762 vid = test_param_get(self.config, 'vid', default=TEST_VID_DEFAULT)
Dan Talayco551befa2010-07-15 17:05:32 -0700763 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=vid)
764 of_ports = pa_port_map.keys()
765 of_ports.sort()
766 ing_port = of_ports[0]
767 pa_logger.info("Sending packet to " + str(ing_port))
768 pa_logger.debug("Data: " + str(pkt).encode('hex'))
769 self.dataplane.send(ing_port, str(pkt))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700770
Dan Talayco551befa2010-07-15 17:05:32 -0700771test_prio["PacketOnly"] = -1
772test_prio["PacketOnlyTagged"] = -1
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700773
Dan Talayco551befa2010-07-15 17:05:32 -0700774class ModifyVID(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700775 """
776 Modify the VLAN ID in the VLAN tag of a tagged packet
777 """
Dan Talayco551befa2010-07-15 17:05:32 -0700778 def runTest(self):
779 old_vid = 2
780 new_vid = 3
781 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700782 if not (sup_acts & 1 << ofp.OFPAT_SET_VLAN_VID):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700783 skip_message_emit(self, "Modify VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700784 return
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700785
Dan Talayco551befa2010-07-15 17:05:32 -0700786 pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=old_vid)
787 exp_pkt = simple_tcp_packet(dl_vlan_enable=True, dl_vlan=new_vid)
788 vid_act = action.action_set_vlan_vid()
789 vid_act.vlan_vid = new_vid
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700790
Dan Talayco551befa2010-07-15 17:05:32 -0700791 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
792 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700793
Dan Talayco551befa2010-07-15 17:05:32 -0700794class StripVLANTag(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700795 """
796 Strip the VLAN tag from a tagged packet
797 """
Dan Talayco551befa2010-07-15 17:05:32 -0700798 def runTest(self):
799 old_vid = 2
800 sup_acts = supported_actions_get(self)
Dan Talayco4b2bee62010-07-20 14:10:05 -0700801 if not (sup_acts & 1 << ofp.OFPAT_STRIP_VLAN):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700802 skip_message_emit(self, "Strip VLAN tag test")
Dan Talayco551befa2010-07-15 17:05:32 -0700803 return
Dan Talaycof36f1082010-07-13 13:57:17 -0700804
Dan Talayco551befa2010-07-15 17:05:32 -0700805 len_w_vid = 104
806 len = 100
807 pkt = simple_tcp_packet(pktlen=len_w_vid, dl_vlan_enable=True,
808 dl_vlan=old_vid)
809 exp_pkt = simple_tcp_packet(pktlen=len)
810 vid_act = action.action_strip_vlan()
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700811
Dan Talayco551befa2010-07-15 17:05:32 -0700812 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
813 action_list=[vid_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700814
Dan Talayco4b2bee62010-07-20 14:10:05 -0700815def init_pkt_args():
816 """
817 Pass back a dictionary with default packet arguments
818 """
819 args = {}
820 args["dl_src"] = '00:23:45:67:89:AB'
821
822 dl_vlan_enable=False
823 dl_vlan=-1
824 if pa_config["test-params"]["vid"]:
825 dl_vlan_enable=True
826 dl_vlan = pa_config["test-params"]["vid"]
827
828# Unpack operator is ** on a dictionary
829
830 return args
831
Dan Talayco551befa2010-07-15 17:05:32 -0700832class ModifyL2Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700833 """
834 Modify the source MAC address (TP1)
835 """
Dan Talayco551befa2010-07-15 17:05:32 -0700836 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700837 sup_acts = supported_actions_get(self)
838 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700839 skip_message_emit(self, "ModifyL2Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700840 return
841
842 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_src'],
843 check_test_params=True)
844 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
845 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700846
Dan Talayco551befa2010-07-15 17:05:32 -0700847class ModifyL2Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700848 """
849 Modify the dest MAC address (TP1)
850 """
Dan Talayco551befa2010-07-15 17:05:32 -0700851 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700852 sup_acts = supported_actions_get(self)
853 if not (sup_acts & 1 << ofp.OFPAT_SET_DL_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700854 skip_message_emit(self, "ModifyL2dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700855 return
856
857 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['dl_dst'],
858 check_test_params=True)
859 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
860 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700861
Dan Talayco551befa2010-07-15 17:05:32 -0700862class ModifyL3Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700863 """
864 Modify the source IP address of an IP packet (TP1)
865 """
Dan Talayco551befa2010-07-15 17:05:32 -0700866 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700867 sup_acts = supported_actions_get(self)
868 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700869 skip_message_emit(self, "ModifyL3Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700870 return
871
872 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_src'],
873 check_test_params=True)
874 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
875 action_list=acts, max_test=2)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700876
Dan Talayco551befa2010-07-15 17:05:32 -0700877class ModifyL3Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700878 """
879 Modify the dest IP address of an IP packet (TP1)
880 """
Dan Talayco551befa2010-07-15 17:05:32 -0700881 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700882 sup_acts = supported_actions_get(self)
883 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700884 skip_message_emit(self, "ModifyL3Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700885 return
886
887 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_dst'],
888 check_test_params=True)
889 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
890 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -0700891
892class ModifyL4Src(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700893 """
894 Modify the source TCP port of a TCP packet (TP1)
895 """
Dan Talayco551befa2010-07-15 17:05:32 -0700896 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700897 sup_acts = supported_actions_get(self)
898 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_SRC):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700899 skip_message_emit(self, "ModifyL4Src test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700900 return
901
902 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_sport'],
903 check_test_params=True)
904 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
905 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -0700906
907class ModifyL4Dst(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700908 """
909 Modify the dest TCP port of a TCP packet (TP1)
910 """
Dan Talayco551befa2010-07-15 17:05:32 -0700911 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700912 sup_acts = supported_actions_get(self)
913 if not (sup_acts & 1 << ofp.OFPAT_SET_TP_DST):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700914 skip_message_emit(self, "ModifyL4Dst test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700915 return
916
917 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['tcp_dport'],
918 check_test_params=True)
919 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
920 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -0700921
922class ModifyTOS(BaseMatchCase):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700923 """
924 Modify the IP type of service of an IP packet (TP1)
925 """
Dan Talayco551befa2010-07-15 17:05:32 -0700926 def runTest(self):
Dan Talayco4b2bee62010-07-20 14:10:05 -0700927 sup_acts = supported_actions_get(self)
928 if not (sup_acts & 1 << ofp.OFPAT_SET_NW_TOS):
Dan Talaycoba3745c2010-07-21 21:51:08 -0700929 skip_message_emit(self, "ModifyTOS test")
Dan Talayco4b2bee62010-07-20 14:10:05 -0700930 return
Dan Talayco551befa2010-07-15 17:05:32 -0700931
Dan Talayco4b2bee62010-07-20 14:10:05 -0700932 (pkt, exp_pkt, acts) = pkt_action_setup(self, mod_fields=['ip_tos'],
933 check_test_params=True)
934 flow_match_test(self, pa_port_map, pkt=pkt, exp_pkt=exp_pkt,
935 action_list=acts, max_test=2)
Dan Talayco551befa2010-07-15 17:05:32 -0700936
Dan Talayco4b2bee62010-07-20 14:10:05 -0700937#@todo Need to implement tagged versions of the above tests
938#
939#@todo Implement a test case that strips tag 2, adds tag 3
940# and modifies tag 4 to tag 5. Then verify (in addition) that
941# tag 6 does not get modified.
942
943class MixedVLAN(BaseMatchCase):
944 """
945 Test mixture of VLAN tag actions
946
947 Strip tag 2 on port 1, send to port 2
948 Add tag 3 on port 1, send to port 2
949 Modify tag 4 to 5 on port 1, send to port 2
950 All other traffic from port 1, send to port 3
951 All traffic from port 2 sent to port 4
952 Use exact matches with different packets for all mods
953 Verify the following: (port, vid)
954 (port 1, vid 2) => VLAN tag stripped, out port 2
955 (port 1, no tag) => tagged packet w/ vid 2 out port 2
956 (port 1, vid 4) => tagged packet w/ vid 5 out port 2
957 (port 1, vid 5) => tagged packet w/ vid 5 out port 2
958 (port 1, vid 6) => tagged packet w/ vid 6 out port 2
959 (port 2, no tag) => untagged packet out port 4
960 (port 2, vid 2-6) => unmodified packet out port 4
961
962 Variation: Might try sending VID 5 to port 3 and check.
963 If only VID 5 distinguishes pkt, this will fail on some platforms
964 """
965
966test_prio["MixedVLAN"] = -1
967
Dan Talayco551befa2010-07-15 17:05:32 -0700968def supported_actions_get(parent, use_cache=True):
969 """
970 Get the bitmap of supported actions from the switch
971 If use_cache is false, the cached value will be updated
972 """
973 global cached_supported_actions
974 if cached_supported_actions is None or not use_cache:
975 request = message.features_request()
976 (reply, pkt) = parent.controller.transact(request, timeout=2)
977 parent.assertTrue(reply is not None, "Did not get response to ftr req")
978 cached_supported_actions = reply.actions
979 pa_logger.info("Supported actions: " + hex(cached_supported_actions))
980
981 return cached_supported_actions
Tatsuya Yabe9c31e222010-06-16 13:48:02 -0700982
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700983if __name__ == "__main__":
984 print "Please run through oft script: ./oft --test_spec=basic"