blob: 70883501226c43fce3c5956963aa254218c1407c [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
42def test_set_init(config):
43 """
44 Set up function for packet action test classes
45
46 @param config The configuration dictionary; see oft
47 """
48
49 global pa_port_map
50 global pa_logger
51 global pa_config
52
53 pa_logger = logging.getLogger("pkt_act")
54 pa_logger.info("Initializing test set")
55 pa_port_map = config["port_map"]
56 pa_config = config
57
58class DirectPacket(basic.SimpleDataPlane):
59 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -070060 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -080061
62 Generate a packet
63 Generate and install a matching flow
64 Add action to direct the packet to an egress port
65 Send the packet to ingress dataplane port
66 Verify the packet is received at the egress port only
67 """
68 def runTest(self):
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -070069 self.handleFlow()
70
71 def handleFlow(self, pkttype='TCP'):
72
Dan Talayco5eba8442010-03-10 13:58:43 -080073 global pa_port_map
74 of_ports = pa_port_map.keys()
75 of_ports.sort()
76 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
77
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -070078 if (pkttype == 'ICMP'):
79 pkt = simple_icmp_packet()
80 else:
81 pkt = simple_tcp_packet()
Dan Talayco5eba8442010-03-10 13:58:43 -080082 match = parse.packet_to_flow_match(pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -070083 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -080084 self.assertTrue(match is not None,
85 "Could not generate flow match from pkt")
86 act = action.action_output()
87
88 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -070089 rv = delete_all_flows(self.controller, pa_logger)
90 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -070091
Dan Talayco5eba8442010-03-10 13:58:43 -080092 ingress_port = of_ports[idx]
93 egress_port = of_ports[(idx + 1) % len(of_ports)]
94 pa_logger.info("Ingress " + str(ingress_port) +
95 " to egress " + str(egress_port))
96
97 match.in_port = ingress_port
98
99 request = message.flow_mod()
100 request.match = match
101 request.buffer_id = 0xffffffff
102 act.port = egress_port
103 self.assertTrue(request.actions.add(act), "Could not add action")
104
105 pa_logger.info("Inserting flow")
106 rv = self.controller.message_send(request)
107 self.assertTrue(rv != -1, "Error installing flow mod")
108 do_barrier(self.controller)
109
110 pa_logger.info("Sending packet to dp port " +
111 str(ingress_port))
112 self.dataplane.send(ingress_port, str(pkt))
113 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(timeout=1)
114 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700115 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800116 str(rcv_port))
117 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
118 self.assertEqual(str(pkt), str(rcv_pkt),
119 'Response packet does not match send packet')
Tatsuya Yabeb8fb3c32010-06-14 15:48:36 -0700120
121class DirectPacketICMP(DirectPacket):
122 """
123 Send ICMP packet to single egress port
124
125 Generate a ICMP packet
126 Generate and install a matching flow
127 Add action to direct the packet to an egress port
128 Send the packet to ingress dataplane port
129 Verify the packet is received at the egress port only
130 Difference from DirectPacket test is that sent packet is ICMP
131 """
132 def runTest(self):
133 self.handleFlow(pkttype='ICMP')
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700134
135class DirectTwoPorts(basic.SimpleDataPlane):
136 """
137 Send packet to two egress ports
138
139 Generate a packet
140 Generate and install a matching flow
141 Add action to direct the packet to two egress ports
142 Send the packet to ingress dataplane port
143 Verify the packet is received at the two egress ports
144 """
145 def runTest(self):
146 global pa_port_map
147 of_ports = pa_port_map.keys()
148 of_ports.sort()
149 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
150
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700151 pkt = simple_tcp_packet()
152 match = parse.packet_to_flow_match(pkt)
153 match.wildcards &= ~ofp.OFPFW_IN_PORT
154 self.assertTrue(match is not None,
155 "Could not generate flow match from pkt")
156 act = action.action_output()
157
158 for idx in range(len(of_ports)):
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700159 rv = delete_all_flows(self.controller, pa_logger)
160 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700161
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700162 ingress_port = of_ports[idx]
163 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
164 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
165 pa_logger.info("Ingress " + str(ingress_port) +
166 " to egress " + str(egress_port1) + " and " +
167 str(egress_port2))
168
169 match.in_port = ingress_port
170
171 request = message.flow_mod()
172 request.match = match
173 request.buffer_id = 0xffffffff
174 act.port = egress_port1
175 self.assertTrue(request.actions.add(act), "Could not add action1")
176 act.port = egress_port2
177 self.assertTrue(request.actions.add(act), "Could not add action2")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700178 # pa_logger.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700179
180 pa_logger.info("Inserting flow")
181 rv = self.controller.message_send(request)
182 self.assertTrue(rv != -1, "Error installing flow mod")
183 do_barrier(self.controller)
184
185 pa_logger.info("Sending packet to dp port " +
186 str(ingress_port))
187 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700188 yes_ports = set([egress_port1, egress_port2])
189 no_ports = set(of_ports).difference(yes_ports)
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700190
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700191 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports,
192 self, pa_logger)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700193
194class DirectMCNonIngress(basic.SimpleDataPlane):
195 """
196 Multicast to all non-ingress ports
197
198 Generate a packet
199 Generate and install a matching flow
200 Add action to direct the packet to all non-ingress ports
201 Send the packet to ingress dataplane port
202 Verify the packet is received at all non-ingress ports
203
204 Does not use the flood action
205 """
206 def runTest(self):
207 global pa_port_map
208 of_ports = pa_port_map.keys()
209 of_ports.sort()
210 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
211
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700212 pkt = simple_tcp_packet()
213 match = parse.packet_to_flow_match(pkt)
214 match.wildcards &= ~ofp.OFPFW_IN_PORT
215 self.assertTrue(match is not None,
216 "Could not generate flow match from pkt")
217 act = action.action_output()
218
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700219 for ingress_port in of_ports:
220 rv = delete_all_flows(self.controller, pa_logger)
221 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700222
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700223 pa_logger.info("Ingress " + str(ingress_port) +
224 " all non-ingress ports")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700225 match.in_port = ingress_port
226
227 request = message.flow_mod()
228 request.match = match
229 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700230 for egress_port in of_ports:
231 if egress_port == ingress_port:
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700232 continue
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700233 act.port = egress_port
234 self.assertTrue(request.actions.add(act),
235 "Could not add output to " + str(egress_port))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700236 pa_logger.debug(request.show())
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700237
238 pa_logger.info("Inserting flow")
239 rv = self.controller.message_send(request)
240 self.assertTrue(rv != -1, "Error installing flow mod")
241 do_barrier(self.controller)
242
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700243 pa_logger.info("Sending packet to dp port " + str(ingress_port))
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700244 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700245 yes_ports = set(of_ports).difference([ingress_port])
246 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
247 self, pa_logger)
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700248
Dan Talayco32fa6542010-05-11 15:54:08 -0700249
250class DirectMC(basic.SimpleDataPlane):
251 """
252 Multicast to all ports including ingress
253
254 Generate a packet
255 Generate and install a matching flow
256 Add action to direct the packet to all non-ingress ports
257 Send the packet to ingress dataplane port
258 Verify the packet is received at all ports
259
260 Does not use the flood action
261 """
262 def runTest(self):
263 global pa_port_map
264 of_ports = pa_port_map.keys()
265 of_ports.sort()
266 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
267
Dan Talayco32fa6542010-05-11 15:54:08 -0700268 pkt = simple_tcp_packet()
269 match = parse.packet_to_flow_match(pkt)
270 match.wildcards &= ~ofp.OFPFW_IN_PORT
271 self.assertTrue(match is not None,
272 "Could not generate flow match from pkt")
273 act = action.action_output()
274
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700275 for ingress_port in of_ports:
276 rv = delete_all_flows(self.controller, pa_logger)
277 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700278
Dan Talayco32fa6542010-05-11 15:54:08 -0700279 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco32fa6542010-05-11 15:54:08 -0700280 match.in_port = ingress_port
281
282 request = message.flow_mod()
283 request.match = match
284 request.buffer_id = 0xffffffff
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700285 for egress_port in of_ports:
286 if egress_port == ingress_port:
Dan Talayco32fa6542010-05-11 15:54:08 -0700287 act.port = ofp.OFPP_IN_PORT
288 else:
289 act.port = egress_port
290 self.assertTrue(request.actions.add(act),
291 "Could not add output to " + str(egress_port))
Dan Talayco2e77a842010-05-12 15:39:46 -0700292 # pa_logger.info(request.show())
293
294 pa_logger.info("Inserting flow")
295 rv = self.controller.message_send(request)
296 self.assertTrue(rv != -1, "Error installing flow mod")
297 do_barrier(self.controller)
298
299 pa_logger.info("Sending packet to dp port " + str(ingress_port))
300 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700301 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
302 pa_logger)
Dan Talayco2e77a842010-05-12 15:39:46 -0700303
304class Flood(basic.SimpleDataPlane):
305 """
306 Flood to all ports except ingress
307
308 Generate a packet
309 Generate and install a matching flow
310 Add action to flood the packet
311 Send the packet to ingress dataplane port
312 Verify the packet is received at all other ports
313 """
314 def runTest(self):
315 global pa_port_map
316 of_ports = pa_port_map.keys()
317 of_ports.sort()
318 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
319
320 pkt = simple_tcp_packet()
321 match = parse.packet_to_flow_match(pkt)
322 match.wildcards &= ~ofp.OFPFW_IN_PORT
323 self.assertTrue(match is not None,
324 "Could not generate flow match from pkt")
325 act = action.action_output()
326
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700327 for ingress_port in of_ports:
328 rv = delete_all_flows(self.controller, pa_logger)
329 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco2e77a842010-05-12 15:39:46 -0700330
Dan Talayco2e77a842010-05-12 15:39:46 -0700331 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco2e77a842010-05-12 15:39:46 -0700332 match.in_port = ingress_port
333
334 request = message.flow_mod()
335 request.match = match
336 request.buffer_id = 0xffffffff
337 act.port = ofp.OFPP_FLOOD
338 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700339 "Could not add flood port action")
Dan Talayco32fa6542010-05-11 15:54:08 -0700340 pa_logger.info(request.show())
341
342 pa_logger.info("Inserting flow")
343 rv = self.controller.message_send(request)
344 self.assertTrue(rv != -1, "Error installing flow mod")
345 do_barrier(self.controller)
346
347 pa_logger.info("Sending packet to dp port " + str(ingress_port))
348 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700349 yes_ports = set(of_ports).difference([ingress_port])
350 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
351 self, pa_logger)
Dan Talayco3be5b062010-05-12 15:46:21 -0700352
Dan Talayco3be5b062010-05-12 15:46:21 -0700353class FloodPlusIngress(basic.SimpleDataPlane):
354 """
355 Flood to all ports plus send to ingress port
356
357 Generate a packet
358 Generate and install a matching flow
359 Add action to flood the packet
360 Add action to send to ingress port
361 Send the packet to ingress dataplane port
362 Verify the packet is received at all other ports
363 """
364 def runTest(self):
365 global pa_port_map
366 of_ports = pa_port_map.keys()
367 of_ports.sort()
368 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
369
370 pkt = simple_tcp_packet()
371 match = parse.packet_to_flow_match(pkt)
372 match.wildcards &= ~ofp.OFPFW_IN_PORT
373 self.assertTrue(match is not None,
374 "Could not generate flow match from pkt")
375 act = action.action_output()
376
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700377 for ingress_port in of_ports:
378 rv = delete_all_flows(self.controller, pa_logger)
379 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco3be5b062010-05-12 15:46:21 -0700380
Dan Talayco3be5b062010-05-12 15:46:21 -0700381 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco3be5b062010-05-12 15:46:21 -0700382 match.in_port = ingress_port
383
384 request = message.flow_mod()
385 request.match = match
386 request.buffer_id = 0xffffffff
387 act.port = ofp.OFPP_FLOOD
388 self.assertTrue(request.actions.add(act),
Dan Talayco4aa13122010-05-12 15:54:44 -0700389 "Could not add flood port action")
390 act.port = ofp.OFPP_IN_PORT
391 self.assertTrue(request.actions.add(act),
392 "Could not add ingress port for output")
393 pa_logger.info(request.show())
394
395 pa_logger.info("Inserting flow")
396 rv = self.controller.message_send(request)
397 self.assertTrue(rv != -1, "Error installing flow mod")
398 do_barrier(self.controller)
399
400 pa_logger.info("Sending packet to dp port " + str(ingress_port))
401 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700402 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
403 pa_logger)
Dan Talayco4aa13122010-05-12 15:54:44 -0700404
405class All(basic.SimpleDataPlane):
406 """
407 Send to OFPP_ALL port
408
409 Generate a packet
410 Generate and install a matching flow
411 Add action to forward to OFPP_ALL
412 Send the packet to ingress dataplane port
413 Verify the packet is received at all other ports
414 """
415 def runTest(self):
416 global pa_port_map
417 of_ports = pa_port_map.keys()
418 of_ports.sort()
419 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
420
421 pkt = simple_tcp_packet()
422 match = parse.packet_to_flow_match(pkt)
423 match.wildcards &= ~ofp.OFPFW_IN_PORT
424 self.assertTrue(match is not None,
425 "Could not generate flow match from pkt")
426 act = action.action_output()
427
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700428 for ingress_port in of_ports:
429 rv = delete_all_flows(self.controller, pa_logger)
430 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700431
Dan Talayco4aa13122010-05-12 15:54:44 -0700432 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700433 match.in_port = ingress_port
434
435 request = message.flow_mod()
436 request.match = match
437 request.buffer_id = 0xffffffff
438 act.port = ofp.OFPP_ALL
439 self.assertTrue(request.actions.add(act),
440 "Could not add ALL port action")
441 pa_logger.info(request.show())
442
443 pa_logger.info("Inserting flow")
444 rv = self.controller.message_send(request)
445 self.assertTrue(rv != -1, "Error installing flow mod")
446 do_barrier(self.controller)
447
448 pa_logger.info("Sending packet to dp port " + str(ingress_port))
449 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700450 yes_ports = set(of_ports).difference([ingress_port])
451 receive_pkt_check(self.dataplane, pkt, yes_ports, [ingress_port],
452 self, pa_logger)
Dan Talayco4aa13122010-05-12 15:54:44 -0700453
454class AllPlusIngress(basic.SimpleDataPlane):
455 """
456 Send to OFPP_ALL port and ingress port
457
458 Generate a packet
459 Generate and install a matching flow
460 Add action to forward to OFPP_ALL
461 Add action to forward to ingress port
462 Send the packet to ingress dataplane port
463 Verify the packet is received at all other ports
464 """
465 def runTest(self):
466 global pa_port_map
467 of_ports = pa_port_map.keys()
468 of_ports.sort()
469 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
470
471 pkt = simple_tcp_packet()
472 match = parse.packet_to_flow_match(pkt)
473 match.wildcards &= ~ofp.OFPFW_IN_PORT
474 self.assertTrue(match is not None,
475 "Could not generate flow match from pkt")
476 act = action.action_output()
477
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700478 for ingress_port in of_ports:
479 rv = delete_all_flows(self.controller, pa_logger)
480 self.assertEqual(rv, 0, "Failed to delete all flows")
Dan Talayco4aa13122010-05-12 15:54:44 -0700481
Dan Talayco4aa13122010-05-12 15:54:44 -0700482 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
Dan Talayco4aa13122010-05-12 15:54:44 -0700483 match.in_port = ingress_port
484
485 request = message.flow_mod()
486 request.match = match
487 request.buffer_id = 0xffffffff
488 act.port = ofp.OFPP_ALL
489 self.assertTrue(request.actions.add(act),
490 "Could not add ALL port action")
Dan Talayco3be5b062010-05-12 15:46:21 -0700491 act.port = ofp.OFPP_IN_PORT
492 self.assertTrue(request.actions.add(act),
493 "Could not add ingress port for output")
494 pa_logger.info(request.show())
495
496 pa_logger.info("Inserting flow")
497 rv = self.controller.message_send(request)
498 self.assertTrue(rv != -1, "Error installing flow mod")
499 do_barrier(self.controller)
500
501 pa_logger.info("Sending packet to dp port " + str(ingress_port))
502 self.dataplane.send(ingress_port, str(pkt))
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700503 receive_pkt_check(self.dataplane, pkt, of_ports, [], self,
504 pa_logger)
505
Dan Talayco9f47f4d2010-06-03 13:54:37 -0700506class FloodMinusPort(basic.SimpleDataPlane):
507 """
508 Config port with No_Flood and test Flood action
509
510 Generate a packet
511 Generate a matching flow
512 Add action to forward to OFPP_ALL
513 Set port to no-flood
514 Send the packet to ingress dataplane port
515 Verify the packet is received at all other ports except
516 the ingress port and the no_flood port
517 """
518 def runTest(self):
519 global pa_port_map
520 of_ports = pa_port_map.keys()
521 of_ports.sort()
522 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
523
524 pkt = simple_tcp_packet()
525 match = parse.packet_to_flow_match(pkt)
526 match.wildcards &= ~ofp.OFPFW_IN_PORT
527 self.assertTrue(match is not None,
528 "Could not generate flow match from pkt")
529 act = action.action_output()
530
531 for idx in range(len(of_ports)):
532 rv = delete_all_flows(self.controller, pa_logger)
533 self.assertEqual(rv, 0, "Failed to delete all flows")
534
535 ingress_port = of_ports[idx]
536 no_flood_idx = (idx + 1) % len(of_ports)
537 no_flood_port = of_ports[no_flood_idx]
538 rv = port_config_set(self.controller, no_flood_port,
539 ofp.OFPPC_NO_FLOOD, ofp.OFPPC_NO_FLOOD,
540 pa_logger)
541 self.assertEqual(rv, 0, "Failed to set port config")
542
543 match.in_port = ingress_port
544
545 request = message.flow_mod()
546 request.match = match
547 request.buffer_id = 0xffffffff
548 act.port = ofp.OFPP_FLOOD
549 self.assertTrue(request.actions.add(act),
550 "Could not add flood port action")
551 pa_logger.info(request.show())
552
553 pa_logger.info("Inserting flow")
554 rv = self.controller.message_send(request)
555 self.assertTrue(rv != -1, "Error installing flow mod")
556 do_barrier(self.controller)
557
558 pa_logger.info("Sending packet to dp port " + str(ingress_port))
559 pa_logger.info("No flood port is " + str(no_flood_port))
560 self.dataplane.send(ingress_port, str(pkt))
561 no_ports = set([ingress_port, no_flood_port])
562 yes_ports = set(of_ports).difference(no_ports)
563 receive_pkt_check(self.dataplane, pkt, yes_ports, no_ports, self,
564 pa_logger)
565
566 # Turn no flood off again
567 rv = port_config_set(self.controller, no_flood_port,
568 0, ofp.OFPPC_NO_FLOOD, pa_logger)
569 self.assertEqual(rv, 0, "Failed to reset port config")
570
571 #@todo Should check no other packets received
572
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700573class SimpleExactMatch(basic.SimpleDataPlane):
574 """
575 Exercise exact matching for all ports
576
577 Generate a packet
578 Generate and install a matching flow without wildcard mask
579 Add action to forward to a port
580 Send the packet to the port
581 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700582 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700583 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700584 IP_ETHTYPE = 0x800
585 TCP_PROTOCOL = 0x6
586 UDP_PROTOCOL = 0x11
587
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700588 def runTest(self):
589 self.flowMatchTest()
590
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700591 def flowMatchTest(self, wildcards=0, check_expire=False):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700592 global pa_port_map
593 of_ports = pa_port_map.keys()
594 of_ports.sort()
595 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
596
597 pkt = simple_tcp_packet()
598 match = parse.packet_to_flow_match(pkt)
599 self.assertTrue(match is not None,
600 "Could not generate flow match from pkt")
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700601 match.dl_vlan = ofp.OFP_VLAN_NONE
602 match.nw_proto = self.TCP_PROTOCOL
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700603 match.wildcards = wildcards
604
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700605 for idx in range(len(of_ports)):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700606 ingress_port = of_ports[idx]
607 pa_logger.info("Ingress " + str(ingress_port) + " to all the other ports")
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700608 match.in_port = ingress_port
609
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700610 for egr_idx in range(len(of_ports)):
611 if egr_idx == idx:
612 continue
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700613
614 rc = delete_all_flows(self.controller, pa_logger)
615 self.assertEqual(rc, 0, "Failed to delete all flows")
616 do_barrier(self.controller)
617
618 request = message.flow_mod()
619 request.match = match
620 request.buffer_id = 0xffffffff
621 #@todo Need UI to setup FLAGS parameter for flow_mod
622 if(check_expire):
623 request.flags |= ofp.OFPFF_SEND_FLOW_REM
624 request.hard_timeout = 1
625
626 act = action.action_output()
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700627 act.port = of_ports[egr_idx]
628 self.assertTrue(request.actions.add(act),
629 "Could not add output action")
630 pa_logger.info(request.show())
631
632 pa_logger.info("Inserting flow")
633 rv = self.controller.message_send(request)
634 self.assertTrue(rv != -1, "Error installing flow mod")
635 do_barrier(self.controller)
636
637 pa_logger.info("Sending packet to dp port " +str(ingress_port))
638 self.dataplane.send(ingress_port, str(pkt))
639
640 ofport = of_ports[egr_idx]
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700641 self.verifPkt(ofport, pkt)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700642
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700643 #@todo Need UI for enabling response-verification
644 if(check_expire):
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700645 self.verifFlowRemoved(request)
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700646
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700647 def verifPkt(self, ofport, exp_pkt):
648 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(
649 port_number=ofport, timeout=1)
650 self.assertTrue(rcv_pkt is not None,
651 "Did not receive packet port " + str(ofport))
652 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on "
653 + str(rcv_port))
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700654
Tatsuya Yabecdf575e2010-05-25 16:56:38 -0700655 self.assertEqual(str(exp_pkt), str(rcv_pkt),
656 'Response packet does not match send packet ' +
657 "on port " + str(ofport))
658
659 def verifFlowRemoved(self, request):
660 (response, raw) = self.controller.poll(ofp.OFPT_FLOW_REMOVED, 2)
661 self.assertTrue(response is not None,
662 'Flow removed message not received')
663
664 req_match = request.match
665 res_match = response.match
666 if(req_match != res_match):
667 self.verifMatchField(req_match, res_match)
668
669 self.assertEqual(request.cookie, response.cookie,
670 self.matchErrStr('cookie'))
671 if (req_match.wildcards != 0):
672 self.assertEqual(request.priority, response.priority,
673 self.matchErrStr('priority'))
674 self.assertEqual(response.reason, ofp.OFPRR_HARD_TIMEOUT,
675 'Reason is not HARD TIMEOUT')
676 self.assertEqual(response.packet_count, 1,
677 'Packet count is not correct')
678 self.assertEqual(response.byte_count, len(pkt),
679 'Packet length is not correct')
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700680
681 def verifMatchField(self, req_match, res_match):
682 self.assertEqual(str(req_match.wildcards), str(res_match.wildcards),
683 self.matchErrStr('wildcards'))
684 self.assertEqual(str(req_match.in_port), str(res_match.in_port),
685 self.matchErrStr('in_port'))
686 self.assertEqual(str(req_match.dl_src), str(res_match.dl_src),
687 self.matchErrStr('dl_src'))
688 self.assertEqual(str(req_match.dl_dst), str(res_match.dl_dst),
689 self.matchErrStr('dl_dst'))
690 self.assertEqual(str(req_match.dl_vlan), str(res_match.dl_vlan),
691 self.matchErrStr('dl_vlan'))
692 self.assertEqual(str(req_match.dl_vlan_pcp), str(res_match.dl_vlan_pcp),
693 self.matchErrStr('dl_vlan_pcp'))
694 self.assertEqual(str(req_match.dl_type), str(res_match.dl_type),
695 self.matchErrStr('dl_type'))
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700696 if(not(req_match.wildcards & ofp.OFPFW_DL_TYPE)
697 and (req_match.dl_type == self.IP_ETHERTYPE)):
698 self.assertEqual(str(req_match.nw_tos), str(res_match.nw_tos),
699 self.matchErrStr('nw_tos'))
700 self.assertEqual(str(req_match.nw_proto), str(res_match.nw_proto),
701 self.matchErrStr('nw_proto'))
702 self.assertEqual(str(req_match.nw_src), str(res_match.nw_src),
703 self.matchErrStr('nw_src'))
704 self.assertEqual(str(req_match.nw_dst), str(res_match.nw_dst),
705 self.matchErrStr('nw_dst'))
706 if(not(req_match.wildcards & ofp.OFPFW_NW_PROTO)
707 and ((req_match.nw_proto == self.TCP_PROTOCOL)
708 or (req_match.nw_proto == self.UDP_PROTOCOL))):
709 self.assertEqual(str(req_match.tp_src), str(res_match.tp_src),
710 self.matchErrStr('tp_src'))
711 self.assertEqual(str(req_match.tp_dst), str(res_match.tp_dst),
712 self.matchErrStr('tp_dst'))
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700713
714 def matchErrStr(self, field):
715 return ('Response Match_' + field + ' does not match send message')
716
717class SingleWildcardMatch(SimpleExactMatch):
718 """
719 Exercise wildcard matching for all ports
720
721 Generate a packet
722 Generate and install a matching flow with wildcard mask
723 Add action to forward to a port
724 Send the packet to the port
725 Verify the packet is received at all other ports (one port at a time)
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700726 Verify flow_expiration message is correct when command option is set
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700727 """
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700728 def __init__(self):
729 SimpleExactMatch.__init__(self)
730 self.wildcards = [ofp.OFPFW_IN_PORT,
731 ofp.OFPFW_DL_VLAN,
732 ofp.OFPFW_DL_SRC,
733 ofp.OFPFW_DL_DST,
734 ofp.OFPFW_DL_TYPE,
735 ofp.OFPFW_NW_PROTO,
736 ofp.OFPFW_TP_SRC,
737 ofp.OFPFW_TP_DST,
738 0x3F << ofp.OFPFW_NW_SRC_SHIFT,
739 0x3F << ofp.OFPFW_NW_DST_SHIFT,
740 ofp.OFPFW_DL_VLAN_PCP,
741 ofp.OFPFW_NW_TOS]
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700742
Tatsuya Yabe0718ad32010-05-24 15:22:10 -0700743 def runTest(self):
744 for exec_wildcard in range(len(self.wildcards)):
Tatsuya Yabe6a6f38a2010-05-22 23:48:04 -0700745 self.flowMatchTest(exec_wildcard)
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700746
747class AllExceptOneWildcardMatch(SingleWildcardMatch):
748 """
Dan Talayco80b54ed2010-07-13 09:48:35 -0700749 Match exactly one field
Tatsuya Yabe4fad7e32010-05-24 15:24:50 -0700750
751 Generate a packet
752 Generate and install a matching flow with wildcard all except one filed
753 Add action to forward to a port
754 Send the packet to the port
755 Verify the packet is received at all other ports (one port at a time)
756 Verify flow_expiration message is correct when command option is set
757 """
758 def runTest(self):
759 for exec_wildcard in range(len(self.wildcards)):
760 all_exp_one_wildcard = ofp.OFPFW_ALL ^ self.wildcards[exec_wildcard]
761 self.flowMatchTest(all_exp_one_wildcard)
Tatsuya Yabee30ebe22010-05-25 09:30:49 -0700762
763class AllWildcardMatch(SingleWildcardMatch):
764 """
765 Create Wildcard-all flow and exercise for all ports
766
767 Generate a packet
768 Generate and install a matching flow with wildcard-all
769 Add action to forward to a port
770 Send the packet to the port
771 Verify the packet is received at all other ports (one port at a time)
772 Verify flow_expiration message is correct when command option is set
773 """
774 def runTest(self):
775 self.flowMatchTest(ofp.OFPFW_ALL)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700776
777class ExactModifyAction(SimpleExactMatch):
778 """
779 Perform Modify action with exact matching for all ports
780
781 Generate a packet for transmit
782 Generate the expected packet
783 Generate and install a matching flow with a modify action and
784 an output action without wildcard mask
785 Send the packet to the port
786 Verify the expected packet is received at all other ports
787 (one port at a time)
788 Verify flow_expiration message is correct when command option is set
789 """
790 def __init__(self):
791 SimpleExactMatch.__init__(self)
792 self.modify_act = [ofp.OFPAT_SET_VLAN_VID,
793 ofp.OFPAT_SET_VLAN_PCP,
794 ofp.OFPAT_STRIP_VLAN,
795 ofp.OFPAT_SET_DL_SRC,
796 ofp.OFPAT_SET_DL_DST,
797 ofp.OFPAT_SET_NW_SRC,
798 ofp.OFPAT_SET_NW_DST,
799 ofp.OFPAT_SET_NW_TOS,
800 ofp.OFPAT_SET_TP_SRC,
801 ofp.OFPAT_SET_TP_DST]
Dan Talaycof36f1082010-07-13 13:57:17 -0700802 self.act_bitmap = 0
803 for val in self.modify_act:
804 self.act_bitmap = self.act_bitmap | (1 << val)
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700805
806 def runTest(self):
807 self.flowMatchModTest()
808
809 def flowMatchModTest(self, wildcards=0, check_expire=False):
Dan Talaycof36f1082010-07-13 13:57:17 -0700810 #@todo Refactor this routine to be separate functions for each action
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700811 global pa_port_map
812 of_ports = pa_port_map.keys()
813 of_ports.sort()
814 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
815
816 mod_dl_dst = '43:21:0F:ED:CB:A9'
817 mod_dl_src = '7F:ED:CB:A9:87:65'
818 mod_dl_vlan = 4094
819 mod_dl_vlan_pcp = 7
820 mod_ip_src = '10.20.30.40'
821 mod_ip_dst = '50.60.70.80'
822 mod_ip_tos = 0xf0
823 mod_tcp_sport = 4321
824 mod_tcp_dport = 8765
825
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700826 request = message.features_request()
827 (reply, pkt) = self.controller.transact(request, timeout=2)
828 self.assertTrue(reply is not None, "Did not get response to ftr req")
829 supported_act = reply.actions
Dan Talaycof36f1082010-07-13 13:57:17 -0700830 pa_logger.info("Supported actions: " + hex(supported_act))
831 if (supported_act & self.act_bitmap) == 0:
832 pa_logger.info("No modification actions supported");
833 return
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700834
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700835 for idx in range(len(of_ports)):
836 ingress_port = of_ports[idx]
Dan Talaycof36f1082010-07-13 13:57:17 -0700837 pa_logger.info("Ingress " + str(ingress_port) +
838 " to all the other ports")
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700839
840 for egr_idx in range(len(of_ports)):
841 if egr_idx == idx:
842 continue
843
844 for exec_mod in range(len(self.modify_act)):
845 pkt_len = 100
846 dl_dst = '0C:DE:F0:12:34:56'
847 dl_src = '01:23:45:67:89:AB'
848 dl_vlan_enable = False
849 dl_vlan = 0
850 dl_vlan_pcp = 0
851 ip_src = '192.168.0.1'
852 ip_dst = '192.168.0.2'
853 ip_tos = 0
854 tcp_sport = 1234
855 tcp_dport = 80
856
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700857 pkt = simple_tcp_packet(pktlen=pkt_len,
858 dl_dst=dl_dst,
859 dl_src=dl_src,
860 dl_vlan_enable=dl_vlan_enable,
861 dl_vlan=dl_vlan,
862 dl_vlan_pcp=dl_vlan_pcp,
863 ip_src=ip_src,
864 ip_dst=ip_dst,
865 ip_tos=ip_tos,
866 tcp_sport=tcp_sport,
867 tcp_dport=tcp_dport)
868
869 match = parse.packet_to_flow_match(pkt)
870 self.assertTrue(match is not None,
871 "Could not generate flow match from pkt")
872 match.in_port = ingress_port
873 match.dl_vlan = ofp.OFP_VLAN_NONE
874 match.nw_proto = self.TCP_PROTOCOL
875 match.wildcards = wildcards
876
877 request = message.flow_mod()
878 request.match = match
879 request.buffer_id = 0xffffffff
880 #@todo Need UI to setup FLAGS parameter for flow_mod
Dan Talaycof36f1082010-07-13 13:57:17 -0700881 if (check_expire):
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700882 request.flags |= ofp.OFPFF_SEND_FLOW_REM
883 request.hard_timeout = 1
884
885 exec_act = self.modify_act[exec_mod]
886 if exec_act == ofp.OFPAT_SET_VLAN_VID:
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700887 if not(supported_act & 1<<ofp.OFPAT_SET_VLAN_VID):
Dan Talaycof36f1082010-07-13 13:57:17 -0700888 pa_logger.debug("Skipping action " +
889 ofp.ofp_action_type_map[exec_act])
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700890 continue
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700891 pkt_len = pkt_len + 4
892 dl_vlan_enable = True
893 dl_vlan = mod_dl_vlan
894 mod_act = action.action_set_vlan_vid()
895 mod_act.vlan_vid = mod_dl_vlan
Tatsuya Yabe17195a02010-05-26 15:29:55 -0700896 elif exec_act == ofp.OFPAT_SET_VLAN_PCP:
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700897 if not(supported_act & 1<<ofp.OFPAT_SET_VLAN_PCP):
Dan Talaycof36f1082010-07-13 13:57:17 -0700898 pa_logger.debug("Skipping action " +
899 ofp.ofp_action_type_map[exec_act])
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700900 continue
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700901 pkt_len = pkt_len + 4
902 dl_vlan_enable = True
903 dl_vlan_pcp = mod_dl_vlan_pcp
904 mod_act = action.action_set_vlan_pcp()
905 mod_act.vlan_pcp = mod_dl_vlan_pcp
Tatsuya Yabe17195a02010-05-26 15:29:55 -0700906 elif exec_act == ofp.OFPAT_STRIP_VLAN:
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700907 if not(supported_act & 1<<ofp.OFPAT_STRIP_VLAN):
Dan Talaycof36f1082010-07-13 13:57:17 -0700908 pa_logger.debug("Skipping action " +
909 ofp.ofp_action_type_map[exec_act])
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700910 continue
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700911 dl_vlan_enable = False
912 mod_act = action.action_strip_vlan()
Tatsuya Yabe17195a02010-05-26 15:29:55 -0700913 elif exec_act == ofp.OFPAT_SET_DL_SRC:
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700914 if not(supported_act & 1<<ofp.OFPAT_SET_DL_SRC):
Dan Talaycof36f1082010-07-13 13:57:17 -0700915 pa_logger.debug("Skipping action " +
916 ofp.ofp_action_type_map[exec_act])
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700917 continue
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700918 dl_src = mod_dl_src
919 mod_act = action.action_set_dl_src()
920 mod_act.dl_addr = parse.parse_mac(mod_dl_src)
Tatsuya Yabe17195a02010-05-26 15:29:55 -0700921 elif exec_act == ofp.OFPAT_SET_DL_DST:
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700922 if not(supported_act & 1<<ofp.OFPAT_SET_DL_DST):
Dan Talaycof36f1082010-07-13 13:57:17 -0700923 pa_logger.debug("Skipping action " +
924 ofp.ofp_action_type_map[exec_act])
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700925 continue
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700926 dl_dst = mod_dl_dst
927 mod_act = action.action_set_dl_dst()
928 mod_act.dl_addr = parse.parse_mac(mod_dl_dst)
Tatsuya Yabe17195a02010-05-26 15:29:55 -0700929 elif exec_act == ofp.OFPAT_SET_NW_SRC:
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700930 if not(supported_act & 1<<ofp.OFPAT_SET_NW_SRC):
Dan Talaycof36f1082010-07-13 13:57:17 -0700931 pa_logger.debug("Skipping action " +
932 ofp.ofp_action_type_map[exec_act])
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700933 continue
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700934 ip_src = mod_ip_src
935 mod_act = action.action_set_nw_src()
936 mod_act.nw_addr = parse.parse_ip(mod_ip_src)
Tatsuya Yabe17195a02010-05-26 15:29:55 -0700937 elif exec_act == ofp.OFPAT_SET_NW_DST:
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700938 if not(supported_act & 1<<ofp.OFPAT_SET_NW_DST):
Dan Talaycof36f1082010-07-13 13:57:17 -0700939 pa_logger.debug("Skipping action " +
940 ofp.ofp_action_type_map[exec_act])
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700941 continue
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700942 ip_dst = mod_ip_dst
943 mod_act = action.action_set_nw_dst()
944 mod_act.nw_addr = parse.parse_ip(mod_ip_dst)
Tatsuya Yabe17195a02010-05-26 15:29:55 -0700945 elif exec_act == ofp.OFPAT_SET_NW_TOS:
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700946 if not(supported_act & 1<<ofp.OFPAT_SET_NW_TOS):
Dan Talaycof36f1082010-07-13 13:57:17 -0700947 pa_logger.debug("Skipping action " +
948 ofp.ofp_action_type_map[exec_act])
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700949 continue
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700950 ip_tos = mod_ip_tos
951 mod_act = action.action_set_nw_tos()
952 mod_act.nw_tos = mod_ip_tos
Tatsuya Yabe17195a02010-05-26 15:29:55 -0700953 elif exec_act == ofp.OFPAT_SET_TP_SRC:
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700954 if not(supported_act & 1<<ofp.OFPAT_SET_TP_SRC):
Dan Talaycof36f1082010-07-13 13:57:17 -0700955 pa_logger.debug("Skipping action " +
956 ofp.ofp_action_type_map[exec_act])
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700957 continue
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700958 tcp_sport = mod_tcp_sport
959 mod_act = action.action_set_tp_src()
960 mod_act.tp_port = mod_tcp_sport
Tatsuya Yabe17195a02010-05-26 15:29:55 -0700961 elif exec_act == ofp.OFPAT_SET_TP_DST:
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700962 if not(supported_act & 1<<ofp.OFPAT_SET_TP_DST):
Dan Talaycof36f1082010-07-13 13:57:17 -0700963 pa_logger.debug("Skipping action " +
964 ofp.ofp_action_type_map[exec_act])
Tatsuya Yabef5ffb972010-05-26 15:36:33 -0700965 continue
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700966 tcp_dport = mod_tcp_dport
967 mod_act = action.action_set_tp_dst()
968 mod_act.tp_port = mod_tcp_dport
Tatsuya Yabe17195a02010-05-26 15:29:55 -0700969 else:
Dan Talaycof36f1082010-07-13 13:57:17 -0700970 pa_logger.debug("Unknown action " + str(exec_act))
Tatsuya Yabe17195a02010-05-26 15:29:55 -0700971 continue
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700972
973 self.assertTrue(request.actions.add(mod_act),
Dan Talaycof36f1082010-07-13 13:57:17 -0700974 "Could not add output action: " +
975 ofp.ofp_action_type_map[exec_act])
976 pa_logger.info("Testing action " +
977 ofp.ofp_action_type_map[exec_act])
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700978 pa_logger.info(request.show())
979
Dan Talaycof36f1082010-07-13 13:57:17 -0700980 rc = delete_all_flows(self.controller, pa_logger)
981 self.assertEqual(rc, 0, "Failed to delete all flows")
982 do_barrier(self.controller)
983
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -0700984 exp_pkt = simple_tcp_packet(pktlen=pkt_len,
985 dl_dst=dl_dst,
986 dl_src=dl_src,
987 dl_vlan_enable=dl_vlan_enable,
988 dl_vlan=dl_vlan,
989 dl_vlan_pcp=dl_vlan_pcp,
990 ip_src=ip_src,
991 ip_dst=ip_dst,
992 ip_tos=ip_tos,
993 tcp_sport=tcp_sport,
994 tcp_dport=tcp_dport)
995
996 act = action.action_output()
997 act.port = of_ports[egr_idx]
998 self.assertTrue(request.actions.add(act),
Dan Talaycof36f1082010-07-13 13:57:17 -0700999 "Could not add output action for port "
1000 + str(act.port))
Tatsuya Yabee6cae8b2010-05-25 18:20:04 -07001001 pa_logger.info(request.show())
1002
1003 pa_logger.info("Inserting flow")
1004 rv = self.controller.message_send(request)
1005 self.assertTrue(rv != -1, "Error installing flow mod")
1006 do_barrier(self.controller)
1007
1008 pa_logger.info("Sending packet to dp port " +str(ingress_port))
1009 self.dataplane.send(ingress_port, str(pkt))
1010
1011 ofport = of_ports[egr_idx]
1012 self.verifPkt(ofport, exp_pkt)
1013
1014 #@todo Need UI for enabling response-verification
1015 if(check_expire):
1016 self.verifFlowRemoved(request)
Tatsuya Yabe9c31e222010-06-16 13:48:02 -07001017
Dan Talayco9f47f4d2010-06-03 13:54:37 -07001018if __name__ == "__main__":
1019 print "Please run through oft script: ./oft --test_spec=basic"