blob: 0c31a07e606d6f6094aa8bb7144c649686f54656 [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
18import logging
19
20import unittest
21
22import 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
28import basic
29
30from testutils import *
31
32#@var port_map Local copy of the configuration map from OF port
33# numbers to OS interfaces
34pa_port_map = None
35#@var pa_logger Local logger object
36pa_logger = None
37#@var pa_config Local copy of global configuration data
38pa_config = None
39
40def test_set_init(config):
41 """
42 Set up function for packet action test classes
43
44 @param config The configuration dictionary; see oft
45 """
46
47 global pa_port_map
48 global pa_logger
49 global pa_config
50
51 pa_logger = logging.getLogger("pkt_act")
52 pa_logger.info("Initializing test set")
53 pa_port_map = config["port_map"]
54 pa_config = config
55
56class DirectPacket(basic.SimpleDataPlane):
57 """
Dan Talayco2d0d49a2010-05-11 15:29:08 -070058 Send packet to single egress port
Dan Talayco5eba8442010-03-10 13:58:43 -080059
60 Generate a packet
61 Generate and install a matching flow
62 Add action to direct the packet to an egress port
63 Send the packet to ingress dataplane port
64 Verify the packet is received at the egress port only
65 """
66 def runTest(self):
67 global pa_port_map
68 of_ports = pa_port_map.keys()
69 of_ports.sort()
70 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
71
72 rc = delete_all_flows(self.controller, pa_logger)
73 self.assertEqual(rc, 0, "Failed to delete all flows")
74
75 pkt = simple_tcp_packet()
76 match = parse.packet_to_flow_match(pkt)
Dan Talayco7dd6cd62010-03-16 15:02:35 -070077 match.wildcards &= ~ofp.OFPFW_IN_PORT
Dan Talayco5eba8442010-03-10 13:58:43 -080078 self.assertTrue(match is not None,
79 "Could not generate flow match from pkt")
80 act = action.action_output()
81
82 for idx in range(len(of_ports)):
83 ingress_port = of_ports[idx]
84 egress_port = of_ports[(idx + 1) % len(of_ports)]
85 pa_logger.info("Ingress " + str(ingress_port) +
86 " to egress " + str(egress_port))
87
88 match.in_port = ingress_port
89
90 request = message.flow_mod()
91 request.match = match
92 request.buffer_id = 0xffffffff
93 act.port = egress_port
94 self.assertTrue(request.actions.add(act), "Could not add action")
95
96 pa_logger.info("Inserting flow")
97 rv = self.controller.message_send(request)
98 self.assertTrue(rv != -1, "Error installing flow mod")
99 do_barrier(self.controller)
100
101 pa_logger.info("Sending packet to dp port " +
102 str(ingress_port))
103 self.dataplane.send(ingress_port, str(pkt))
104 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(timeout=1)
105 self.assertTrue(rcv_pkt is not None, "Did not receive packet")
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700106 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on " +
Dan Talayco5eba8442010-03-10 13:58:43 -0800107 str(rcv_port))
108 self.assertEqual(rcv_port, egress_port, "Unexpected receive port")
109 self.assertEqual(str(pkt), str(rcv_pkt),
110 'Response packet does not match send packet')
111
112
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700113
114class DirectTwoPorts(basic.SimpleDataPlane):
115 """
116 Send packet to two egress ports
117
118 Generate a packet
119 Generate and install a matching flow
120 Add action to direct the packet to two egress ports
121 Send the packet to ingress dataplane port
122 Verify the packet is received at the two egress ports
123 """
124 def runTest(self):
125 global pa_port_map
126 of_ports = pa_port_map.keys()
127 of_ports.sort()
128 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
129
130 rc = delete_all_flows(self.controller, pa_logger)
131 self.assertEqual(rc, 0, "Failed to delete all flows")
132
133 pkt = simple_tcp_packet()
134 match = parse.packet_to_flow_match(pkt)
135 match.wildcards &= ~ofp.OFPFW_IN_PORT
136 self.assertTrue(match is not None,
137 "Could not generate flow match from pkt")
138 act = action.action_output()
139
140 for idx in range(len(of_ports)):
141 ingress_port = of_ports[idx]
142 egress_port1 = of_ports[(idx + 1) % len(of_ports)]
143 egress_port2 = of_ports[(idx + 2) % len(of_ports)]
144 pa_logger.info("Ingress " + str(ingress_port) +
145 " to egress " + str(egress_port1) + " and " +
146 str(egress_port2))
147
148 match.in_port = ingress_port
149
150 request = message.flow_mod()
151 request.match = match
152 request.buffer_id = 0xffffffff
153 act.port = egress_port1
154 self.assertTrue(request.actions.add(act), "Could not add action1")
155 act.port = egress_port2
156 self.assertTrue(request.actions.add(act), "Could not add action2")
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700157 # pa_logger.info(request.show())
Dan Talayco2d0d49a2010-05-11 15:29:08 -0700158
159 pa_logger.info("Inserting flow")
160 rv = self.controller.message_send(request)
161 self.assertTrue(rv != -1, "Error installing flow mod")
162 do_barrier(self.controller)
163
164 pa_logger.info("Sending packet to dp port " +
165 str(ingress_port))
166 self.dataplane.send(ingress_port, str(pkt))
167 (rcv_port1, rcv_pkt1, pkt_time1) = self.dataplane.poll(timeout=1)
168 (rcv_port2, rcv_pkt2, pkt_time2) = self.dataplane.poll(timeout=1)
169 self.assertTrue(rcv_pkt1 is not None, "Did not receive packet 1")
170 self.assertTrue(rcv_pkt2 is not None, "Did not receive packet 2")
171 pa_logger.debug("Packet len " + str(len(rcv_pkt1)) + " in on " +
172 str(rcv_port1))
173 pa_logger.debug("Packet len " + str(len(rcv_pkt2)) + " in on " +
174 str(rcv_port2))
175
176 # Check if ports swapped
177 if (rcv_port1 == egress_port2 and rcv_port2 == egress_port1):
178 (rcv_port2, rcv_port1) = (rcv_port1, rcv_port2)
179 (rcv_pkt2, rcv_pkt1) = (rcv_pkt1, rcv_pkt2)
180 self.assertEqual(rcv_port1, egress_port1,
181 "Unexpected receive port 1")
182 self.assertEqual(rcv_port2, egress_port2,
183 "Unexpected receive port 2")
184 self.assertEqual(str(pkt), str(rcv_pkt1),
185 'Response packet does not match send packet 1')
186 self.assertEqual(str(pkt), str(rcv_pkt2),
187 'Response packet does not match send packet 2')
188
189
Dan Talaycob0b0fdb2010-05-11 15:44:56 -0700190
191class DirectMCNonIngress(basic.SimpleDataPlane):
192 """
193 Multicast to all non-ingress ports
194
195 Generate a packet
196 Generate and install a matching flow
197 Add action to direct the packet to all non-ingress ports
198 Send the packet to ingress dataplane port
199 Verify the packet is received at all non-ingress ports
200
201 Does not use the flood action
202 """
203 def runTest(self):
204 global pa_port_map
205 of_ports = pa_port_map.keys()
206 of_ports.sort()
207 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
208
209 rc = delete_all_flows(self.controller, pa_logger)
210 self.assertEqual(rc, 0, "Failed to delete all flows")
211
212 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
219 for idx in range(len(of_ports)):
220 ingress_port = of_ports[idx]
221 pa_logger.info("Ingress " + str(ingress_port) +
222 " all non-ingress ports")
223
224 match.in_port = ingress_port
225
226 request = message.flow_mod()
227 request.match = match
228 request.buffer_id = 0xffffffff
229 for egr_idx in range(len(of_ports)):
230 if egr_idx == idx:
231 continue
232 egress_port = of_ports[egr_idx]
233 act.port = egress_port
234 self.assertTrue(request.actions.add(act),
235 "Could not add output to " + str(egress_port))
236 pa_logger.info(request.show())
237
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
243 pa_logger.info("Sending packet to dp port " +
244 str(ingress_port))
245 self.dataplane.send(ingress_port, str(pkt))
246 for egr_idx in range(len(of_ports)):
247 if egr_idx == idx:
248 continue
249 ofport = of_ports[egr_idx]
250 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(
251 port_number=ofport, timeout=1)
252 self.assertTrue(rcv_pkt is not None,
253 "Did not receive packet port " + str(ofport))
254 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on "
255 + str(rcv_port))
256
257 self.assertEqual(str(pkt), str(rcv_pkt),
258 'Response packet does not match send packet ' +
259 "on port " + str(ofport))
260
261
Dan Talayco32fa6542010-05-11 15:54:08 -0700262
263class DirectMC(basic.SimpleDataPlane):
264 """
265 Multicast to all ports including ingress
266
267 Generate a packet
268 Generate and install a matching flow
269 Add action to direct the packet to all non-ingress ports
270 Send the packet to ingress dataplane port
271 Verify the packet is received at all ports
272
273 Does not use the flood action
274 """
275 def runTest(self):
276 global pa_port_map
277 of_ports = pa_port_map.keys()
278 of_ports.sort()
279 self.assertTrue(len(of_ports) > 2, "Not enough ports for test")
280
281 rc = delete_all_flows(self.controller, pa_logger)
282 self.assertEqual(rc, 0, "Failed to delete all flows")
283
284 pkt = simple_tcp_packet()
285 match = parse.packet_to_flow_match(pkt)
286 match.wildcards &= ~ofp.OFPFW_IN_PORT
287 self.assertTrue(match is not None,
288 "Could not generate flow match from pkt")
289 act = action.action_output()
290
291 for idx in range(len(of_ports)):
292 ingress_port = of_ports[idx]
293 pa_logger.info("Ingress " + str(ingress_port) + " to all ports")
294
295 match.in_port = ingress_port
296
297 request = message.flow_mod()
298 request.match = match
299 request.buffer_id = 0xffffffff
300 for egr_idx in range(len(of_ports)):
301 egress_port = of_ports[egr_idx]
302 if egr_idx == idx:
303 act.port = ofp.OFPP_IN_PORT
304 else:
305 act.port = egress_port
306 self.assertTrue(request.actions.add(act),
307 "Could not add output to " + str(egress_port))
308 pa_logger.info(request.show())
309
310 pa_logger.info("Inserting flow")
311 rv = self.controller.message_send(request)
312 self.assertTrue(rv != -1, "Error installing flow mod")
313 do_barrier(self.controller)
314
315 pa_logger.info("Sending packet to dp port " + str(ingress_port))
316 self.dataplane.send(ingress_port, str(pkt))
317 for egr_idx in range(len(of_ports)):
318 ofport = of_ports[egr_idx]
319 (rcv_port, rcv_pkt, pkt_time) = self.dataplane.poll(
320 port_number=ofport, timeout=1)
321 self.assertTrue(rcv_pkt is not None,
322 "Did not receive packet port " + str(ofport))
323 pa_logger.debug("Packet len " + str(len(rcv_pkt)) + " in on "
324 + str(rcv_port))
325
326 self.assertEqual(str(pkt), str(rcv_pkt),
327 'Response packet does not match send packet ' +
328 "on port " + str(ofport))
329
330