blob: c9690309fa585d3e9b57a9ca429ff0afe3e62734 [file] [log] [blame]
ShreyaPandita9306c772012-09-28 12:21:40 -04001"""These tests fall under Conformance Test-Suite (OF-SWITCH-1.0.0 TestCases).
2 Refer Documentation -- Detailed testing methodology
3 <Some of test-cases are directly taken from oftest> """
4
5"Test Suite 3 --> Detailed Controller to switch messages"
6
7import logging
8
9import unittest
10import random
11
Rich Lane477f4812012-10-04 22:49:00 -070012from oftest import config
ShreyaPandita9306c772012-09-28 12:21:40 -040013import oftest.controller as controller
14import oftest.cstruct as ofp
15import oftest.message as message
16import oftest.dataplane as dataplane
17import oftest.action as action
18import oftest.parse as parse
Rich Laneb90a1c42012-10-05 09:16:05 -070019import oftest.base_tests as base_tests
ShreyaPandita9306c772012-09-28 12:21:40 -040020
Rich Laneda3b5ad2012-10-03 09:05:32 -070021from oftest.testutils import *
ShreyaPandita9306c772012-09-28 12:21:40 -040022from time import sleep
23from FuncUtils import *
24
Rich Laneb90a1c42012-10-05 09:16:05 -070025class OverlapChecking(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -040026
27 """Verify that if overlap check flag is set in the flow entry and an overlapping flow is inserted then an error
28 is generated and switch refuses flow entry"""
29
30 def runTest(self):
31
Rich Lane9a003812012-10-04 17:17:59 -070032 logging.info("Running Overlap_Checking test")
ShreyaPandita9306c772012-09-28 12:21:40 -040033
Rich Lane477f4812012-10-04 22:49:00 -070034 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -040035 of_ports.sort()
36 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
37
38 #Clear Switch State
Rich Lane9a003812012-10-04 17:17:59 -070039 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -040040 self.assertEqual(rc, 0, "Failed to delete all flows")
41
Rich Lane9a003812012-10-04 17:17:59 -070042 logging.info("Inserting two overlapping flows")
43 logging.info("Expecting switch to return an error")
ShreyaPandita9306c772012-09-28 12:21:40 -040044
45 #Insert a flow F with wildcarded all fields
46 (pkt,match) = Wildcard_All(self,of_ports)
47
48 #Verify flow is active
49 Verify_TableStats(self,active_entries=1)
50
51 # Build a overlapping flow F'-- Wildcard All except ingress with check overlap bit set
52 Pkt_MatchIngress = simple_tcp_packet()
53 match3 = parse.packet_to_flow_match(Pkt_MatchIngress)
54 self.assertTrue(match3 is not None, "Could not generate flow match from pkt")
55 match3.wildcards = ofp.OFPFW_ALL-ofp.OFPFW_IN_PORT
56 match3.in_port = of_ports[0]
57
58 msg3 = message.flow_mod()
59 msg3.command = ofp.OFPFC_ADD
60 msg3.match = match3
61 msg3.flags |= ofp.OFPFF_CHECK_OVERLAP
62 msg3.cookie = random.randint(0,9007199254740992)
63 msg3.buffer_id = 0xffffffff
64
65 act3 = action.action_output()
66 act3.port = of_ports[1]
67 self.assertTrue(msg3.actions.add(act3), "could not add action")
68 rv = self.controller.message_send(msg3)
69 self.assertTrue(rv != -1, "Error installing flow mod")
70 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
71
72 # Verify Flow does not get inserted
73 Verify_TableStats(self,active_entries=1)
74
75 #Verify OFPET_FLOW_MOD_FAILED/OFPFMFC_OVERLAP error is recieved on the control plane
76 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_ERROR,
77 timeout=5)
78 self.assertTrue(response is not None,
79 'Switch did not reply with error message')
80 self.assertTrue(response.type==ofp.OFPET_FLOW_MOD_FAILED,
81 'Error message type is not flow mod failed ')
82 self.assertTrue(response.code==ofp.OFPFMFC_OVERLAP,
83 'Error Message code is not overlap')
84
85
Rich Laneb90a1c42012-10-05 09:16:05 -070086class NoOverlapChecking(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -040087
88 """Verify that without overlap check flag set, overlapping flows can be created."""
89
90 def runTest(self):
91
Rich Lane9a003812012-10-04 17:17:59 -070092 logging.info("Running No_Overlap_Checking test")
ShreyaPandita9306c772012-09-28 12:21:40 -040093
Rich Lane477f4812012-10-04 22:49:00 -070094 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -040095 of_ports.sort()
96 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
97
98 #Clear Switch State
Rich Lane9a003812012-10-04 17:17:59 -070099 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400100 self.assertEqual(rc, 0, "Failed to delete all flows")
101
Rich Lane9a003812012-10-04 17:17:59 -0700102 logging.info("Inserting two overlapping flows")
103 logging.info("Expecting switch to insert the flows without generating errors")
ShreyaPandita9306c772012-09-28 12:21:40 -0400104
105 #Build a flow F with wildcarded all fields.
106 (pkt,match) = Wildcard_All(self,of_ports)
107
108 #Verify flow is active
109 Verify_TableStats(self,active_entries=1)
110
111 # Build a overlapping flow F' without check overlap bit set.
112 Wildcard_All_Except_Ingress(self,of_ports)
113
114 # Verify Flow gets inserted
115 Verify_TableStats(self,active_entries=2)
116
117
Rich Laneb90a1c42012-10-05 09:16:05 -0700118class IdenticalFlows(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400119
120 """Verify that adding two identical flows overwrites the existing one and clears counters"""
121
122 def runTest(self):
123
Rich Lane9a003812012-10-04 17:17:59 -0700124 logging.info("Running Identical_Flows test ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400125
Rich Lane477f4812012-10-04 22:49:00 -0700126 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400127 of_ports.sort()
128 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
129
130 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700131 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400132 self.assertEqual(rc, 0, "Failed to delete all flows")
133
Rich Lane9a003812012-10-04 17:17:59 -0700134 logging.info("Inserting two identical flows one by one")
135 logging.info("Expecting switch to overwrite the first flow and clear the counters associated with it ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400136
137 # Create and add flow-1, check on dataplane it is active.
138 (pkt,match) = Wildcard_All(self,of_ports)
139
140 # Verify active_entries in table_stats_request =1
141 Verify_TableStats(self,active_entries=1)
142
143 # Send Packet (to increment counters like byte_count and packet_count)
144 SendPacket(self,pkt,of_ports[0],of_ports[1])
145
146 # Verify Flow counters have incremented
147 Verify_FlowStats(self,match,byte_count=len(str(pkt)),packet_count=1)
148
149 #Send Identical flow
150 (pkt1,match1) = Wildcard_All(self,of_ports)
151
152 # Verify active_entries in table_stats_request =1
153 Verify_TableStats(self,active_entries=1)
154
155 # Verify Flow counters reset
156 Verify_FlowStats(self,match,byte_count=0,packet_count=0)
157
158
Rich Laneb90a1c42012-10-05 09:16:05 -0700159class EmerFlowTimeout(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400160
161 """Timeout values are not allowed for emergency flows"""
162
163 def runTest(self):
164
Rich Lane9a003812012-10-04 17:17:59 -0700165 logging.info("Running Emergency_Flow_Timeout test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400166
Rich Lane477f4812012-10-04 22:49:00 -0700167 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400168 of_ports.sort()
169 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
170
171 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700172 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400173 self.assertEqual(rc, 0, "Failed to delete all flows")
174
Rich Lane9a003812012-10-04 17:17:59 -0700175 logging.info("Inserting an emergency flow with timeout values")
176 logging.info("Expecting switch to generate error ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400177
178 #Insert an emergency flow
179 pkt = simple_tcp_packet()
180 match = parse.packet_to_flow_match(pkt)
181 match.in_port = of_ports[0]
182
183 request = message.flow_mod()
184 request.match = match
185 request.command = ofp.OFPFC_ADD
186 request.flags = request.flags|ofp.OFPFF_EMERG
187 request.hard_timeout =9
188 request.idle_timeout =9
189
190 act = action.action_output()
191 act.port = of_ports[1]
192
193 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700194 logging.info("Inserting flow")
ShreyaPandita9306c772012-09-28 12:21:40 -0400195 rv = self.controller.message_send(request)
196 self.assertTrue(rv != -1, "Flow addition did not fail.")
197
198 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
199
200 #Verify OFPET_FLOW_MOD_FAILED/OFPFMFC_OVERLAP error is recieved on the control plane
201 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_ERROR,
202 timeout=5)
203 self.assertTrue(response is not None,
204 'Switch did not reply with error message')
205 self.assertTrue(response.type==ofp.OFPET_FLOW_MOD_FAILED,
206 'Error message type is not flow mod failed ')
207 self.assertTrue(response.code==ofp.OFPFMFC_BAD_EMERG_TIMEOUT,
208 'Error Message code is not bad emergency timeout')
209
210
Rich Laneb90a1c42012-10-05 09:16:05 -0700211class MissingModifyAdd(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400212
213 """If a modify does not match an existing flow, the flow gets added """
214
215 def runTest(self):
216
Rich Lane9a003812012-10-04 17:17:59 -0700217 logging.info("Running Missing_Modify_Add test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400218
Rich Lane477f4812012-10-04 22:49:00 -0700219 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400220 of_ports.sort()
221 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
222
Rich Lane9a003812012-10-04 17:17:59 -0700223 logging.info("Inserting a flow-modify that does not match an existing flow")
224 logging.info("Expecting flow to get added i.e OFPFC_MODIFY command should be taken as OFPFC_ADD ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400225
226 #Clear Switch State
Rich Lane9a003812012-10-04 17:17:59 -0700227 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400228 self.assertEqual(rc, 0, "Failed to delete all flows")
229
230 #Generate a flow-mod,command OFPC_MODIFY
231
232 request = message.flow_mod()
233 request.command = ofp.OFPFC_MODIFY
234 request.match.wildcards = ofp.OFPFW_ALL-ofp.OFPFW_IN_PORT
235 request.match.in_port = of_ports[0]
236 request.cookie = random.randint(0,9007199254740992)
237 request.buffer_id = 0xffffffff
238 act3 = action.action_output()
239 act3.port = of_ports[1]
240 self.assertTrue(request.actions.add(act3), "could not add action")
241
Rich Lane9a003812012-10-04 17:17:59 -0700242 logging.info("Inserting flow")
ShreyaPandita9306c772012-09-28 12:21:40 -0400243 rv = self.controller.message_send(request)
244 self.assertTrue(rv != -1, "Error installing flow mod")
245 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
246
247 #Verify the flow gets added i.e. active_count= 1
248 Verify_TableStats(self,active_entries=1)
249
250
Rich Laneb90a1c42012-10-05 09:16:05 -0700251class ModifyAction(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400252
253 """A modified flow preserves counters"""
254
255 def runTest(self):
256
Rich Lane9a003812012-10-04 17:17:59 -0700257 logging.info("Running Modify_Action test ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400258
Rich Lane477f4812012-10-04 22:49:00 -0700259 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400260 of_ports.sort()
261 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
262
263 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700264 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400265 self.assertEqual(rc, 0, "Failed to delete all flows")
266
Rich Lane9a003812012-10-04 17:17:59 -0700267 logging.info("Inserting a Flow and incrementing flow counters. Modifying the flow action")
268 logging.info("Expecting the flow action to be modified , but the flow-counters should be preserved")
ShreyaPandita9306c772012-09-28 12:21:40 -0400269
270 #Create and add flow-1 Match on all, except one wildcarded (src adddress).Action A , output to of_port[1]
271 (pkt,match) = Match_All_Except_Source_Address(self,of_ports)
272
273 #Send Packet matching the flow thus incrementing counters like packet_count,byte_count
274 SendPacket(self,pkt,of_ports[0],of_ports[1])
275
276 #Verify flow counters
277 Verify_FlowStats(self,match,byte_count=len(str(pkt)),packet_count=1)
278
279 #Modify flow- 1
280 Modify_Flow_Action(self,of_ports,match)
281
282 # Send Packet matching the flow-1 i.e ingress_port=port[0] and verify it is recieved on corret dataplane port i.e port[2]
283 SendPacket(self,pkt,of_ports[0],of_ports[2])
284
285 #Verify flow counters are preserved
286 Verify_FlowStats(self,match,byte_count=(2*len(str(pkt))),packet_count=2)
287
288
Rich Laneb90a1c42012-10-05 09:16:05 -0700289class StrictModifyAction(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400290
291 """Strict Modify Flow also changes action preserves counters"""
292
293 def runTest(self):
294
Rich Lane9a003812012-10-04 17:17:59 -0700295 logging.info("Running Strict_Modify_Action test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400296
Rich Lane477f4812012-10-04 22:49:00 -0700297 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400298 of_ports.sort()
299 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
300
301 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700302 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400303 self.assertEqual(rc, 0, "Failed to delete all flows")
304
Rich Lane9a003812012-10-04 17:17:59 -0700305 logging.info("Inserting Flows and incrementing flow counters. Strict Modify the flow action ")
306 logging.info("Expecting the flow action to be modified , but the flow-counters should be preserved")
ShreyaPandita9306c772012-09-28 12:21:40 -0400307
308 #Create and add flow-1 Match on all, except one wildcarded (src adddress).Action A
309 (pkt,match) = Match_All_Except_Source_Address(self,of_ports,priority=100)
310
311 #Create and add flow-2 , Match on ingress_port only, Action A
312 (pkt1,match1) = Wildcard_All_Except_Ingress(self,of_ports,priority=10)
313
314 # Verify both the flows are active
315 Verify_TableStats(self,active_entries=2)
316
317 #Send a packet matching the flows, thus incrementing flow-counters (packet matches the flow F-1 with higher priority)
318 SendPacket(self,pkt,of_ports[0],of_ports[1])
319
320 # Verify flow counters of the flow-1
321 Verify_FlowStats(self,match,byte_count=len(str(pkt)),packet_count=1)
322
323 # Strict-Modify flow- 1
324 Strict_Modify_Flow_Action(self,of_ports[2],match,priority=100)
325
326 # Send Packet matching the flow-1 i.e ingress_port=port[0] and verify it is recieved on corret dataplane port i.e port[2]
327 SendPacket(self,pkt,of_ports[0],of_ports[2])
328
329 # Verify flow counters are preserved
330 Verify_FlowStats(self,match,byte_count=(2*len(str(pkt))),packet_count=2)
331
332
Rich Laneb90a1c42012-10-05 09:16:05 -0700333class DeleteNonexistingFlow(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400334
335 """Request deletion of non-existing flow"""
336
337 def runTest(self):
338
Rich Lane9a003812012-10-04 17:17:59 -0700339 logging.info("Delete_NonExisting_Flow test begins")
ShreyaPandita9306c772012-09-28 12:21:40 -0400340
Rich Lane477f4812012-10-04 22:49:00 -0700341 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400342 of_ports.sort()
343 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
344
345 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700346 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400347 self.assertEqual(rc, 0, "Failed to delete all flows")
348
Rich Lane9a003812012-10-04 17:17:59 -0700349 logging.info("Deleting a non-existing flow")
350 logging.info("Expecting switch to ignore the command , without generating errors")
ShreyaPandita9306c772012-09-28 12:21:40 -0400351
352 # Issue a delete command
353 msg = message.flow_mod()
354 msg.match.wildcards = ofp.OFPFW_ALL
355 msg.out_port = ofp.OFPP_NONE
356 msg.command = ofp.OFPFC_DELETE
357 msg.buffer_id = 0xffffffff
358
359 # Verify no message or error is generated by polling the the control plane
360 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_ERROR,
361 timeout=2)
362 self.assertTrue(response is None,
363 'Recieved Error for deleting non-exiting flow ')
364
365
366
Rich Laneb90a1c42012-10-05 09:16:05 -0700367class SendFlowRem(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400368
369 """Check deletion of flows happens and generates messages as configured.
370 If Send Flow removed message Flag is set in the flow entry, the flow deletion of that respective flow should generate the flow removed message,
371 vice versa also exists """
372
373 def runTest(self):
374
Rich Lane9a003812012-10-04 17:17:59 -0700375 logging.info("Running Send_Flow_Rem test ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400376
Rich Lane477f4812012-10-04 22:49:00 -0700377 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400378 of_ports.sort()
379 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
380
381 #Clear swicth state
Rich Lane9a003812012-10-04 17:17:59 -0700382 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400383 self.assertEqual(rc, 0, "Failed to delete all flows")
384
Rich Lane9a003812012-10-04 17:17:59 -0700385 logging.info("Inserting flows F1 and F2 without and with send_flow_removed_message flag set ")
386 logging.info("Deleting the flows")
387 logging.info("Expecting flow removed message only for F2")
ShreyaPandita9306c772012-09-28 12:21:40 -0400388
389 # Insert flow-1 with F without OFPFF_SEND_FLOW_REM flag set.
390 (pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
391
392 # Verify flow is inserted
393 Verify_TableStats(self,active_entries=1)
394
395 #Delete the flow-1
396 NonStrict_Delete(self,match,priority=0)
397
398 # Verify no flow removed message is generated for the FLOW-1
399
400 (response1, pkt1) = self.controller.poll(exp_msg=ofp.OFPT_FLOW_REMOVED,
401 timeout=2)
402 self.assertTrue(response1 is None,
403 'Received flow removed message for the flow with flow_rem flag not set')
404
405 # Insert another flow F' with OFPFF_SEND_FLOW_REM flag set.
406 msg9 = message.flow_mod()
407 msg9.match.wildcards = ofp.OFPFW_ALL
408 msg9.cookie = random.randint(0,9007199254740992)
409 msg9.buffer_id = 0xffffffff
410 msg9.idle_timeout = 1
411 msg9.flags |= ofp.OFPFF_SEND_FLOW_REM
412 rv1 = self.controller.message_send(msg9)
413 self.assertTrue(rv1 != -1, "Error installing flow mod")
414 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
415
416 # Delete the flow-2
Rich Lane9a003812012-10-04 17:17:59 -0700417 rc2 = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400418 self.assertEqual(rc2, 0, "Failed to delete all flows")
419
420 # Verify flow removed message is generated for the FLOW-2
421
422 (response2, pkt2) = self.controller.poll(exp_msg=ofp.OFPT_FLOW_REMOVED,
423 timeout=2)
424 self.assertTrue(response2 is not None,
425 'Did not receive flow removed message for this flow')
426
427
Rich Laneb90a1c42012-10-05 09:16:05 -0700428class DeleteEmerFlow(base_tests.SimpleProtocol):
ShreyaPandita9306c772012-09-28 12:21:40 -0400429
430 """Delete emergency flow and verify no message is generated.An emergency flow deletion will not generate flow-removed messages even if
431 Send Flow removed message flag was set during the emergency flow entry"""
432
433 def runTest(self):
434
Rich Lane9a003812012-10-04 17:17:59 -0700435 logging.info("Running Delete_Emer_Flow")
ShreyaPandita9306c772012-09-28 12:21:40 -0400436
Rich Lane477f4812012-10-04 22:49:00 -0700437 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400438 of_ports.sort()
439
440 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700441 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400442 self.assertEqual(rc, 0, "Failed to delete all flows")
443
Rich Lane9a003812012-10-04 17:17:59 -0700444 logging.info("Inserting a emergency flow with send_flow_removed flag set")
445 logging.info("Expecting no flow_removed_message on the deletion of the emergency flow")
ShreyaPandita9306c772012-09-28 12:21:40 -0400446
447 # Insert a flow with emergency bit set.
448 pkt = simple_tcp_packet()
449 match = parse.packet_to_flow_match(pkt)
450 match.in_port = of_ports[0]
451 request = message.flow_mod()
452 request.match = match
453 request.command = ofp.OFPFC_ADD
454 request.flags = request.flags|ofp.OFPFF_EMERG|ofp.OFPFF_SEND_FLOW_REM
455 act = action.action_output()
456 act.port = of_ports[1]
457 request.actions.add(act)
458
459 rv = self.controller.message_send(request)
460 self.assertTrue(rv != -1, "Flow addition failed.")
461
462 # Delete the emergency flow
463
464 NonStrict_Delete(self,match)
465 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPFF_SEND_FLOW_REM ,
466 timeout=2)
467 self.assertTrue(response is None,
468 'Test Failed ')
469
470
Rich Laneb90a1c42012-10-05 09:16:05 -0700471class StrictVsNonstrict(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400472
473 """Delete and verify strict and non-strict behaviors
474 This test compares the behavior of delete strict and non-strict"""
475
476 def runTest(self):
477
Rich Lane9a003812012-10-04 17:17:59 -0700478 logging.info("Strict_Vs_Nonstrict test begins")
ShreyaPandita9306c772012-09-28 12:21:40 -0400479
Rich Lane477f4812012-10-04 22:49:00 -0700480 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400481 of_ports.sort()
482 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
483
484 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700485 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400486 self.assertEqual(rc, 0, "Failed to delete all flows")
487
Rich Lane9a003812012-10-04 17:17:59 -0700488 logging.info("Inserting a flow with exact match")
489 logging.info("Issue Strict Delete command , verify it gets deleted")
ShreyaPandita9306c772012-09-28 12:21:40 -0400490
491 #Insert F with an exact Match
492 (pkt,match) = Exact_Match(self,of_ports)
493 Verify_TableStats(self,active_entries=1)
494
495 #Issue Strict Delete Command , verify F gets deleted.
496 Strict_Delete(self,match)
497 Verify_TableStats(self,active_entries=0)
498
Rich Lane9a003812012-10-04 17:17:59 -0700499 logging.info("Inserting two overlapping flows")
500 logging.info("Issue Strict Delete command ")
501 logging.info("Expecting only one flow gets deleted , because Strict Delete matches on wildcards as well")
ShreyaPandita9306c772012-09-28 12:21:40 -0400502
503 #Insert Flow T with match on all , except one wildcarded ( say src adddress ).
504 (pkt,match) = Match_All_Except_Source_Address(self,of_ports)
505
506 #Insert another flow T' with match on ingress_port , wildcarded rest.
507 (pkt1,match1) = Wildcard_All_Except_Ingress(self,of_ports)
508 Verify_TableStats(self,active_entries=2)
509
510 #Issue Strict Delete matching on ingress_port. Verify only T' gets deleted
511 Strict_Delete(self,match1)
512 Verify_TableStats(self,active_entries=1)
513
Rich Lane9a003812012-10-04 17:17:59 -0700514 logging.info("Inserting two overlapping flows")
515 logging.info("Issue Non-Strict Delete command ")
516 logging.info("Expecting both the flow gets deleted , because wildcards are active")
ShreyaPandita9306c772012-09-28 12:21:40 -0400517
518 #Insert T and T' again .
519 (pkt,match) = Match_All_Except_Source_Address(self,of_ports)
520 (pkt1,match1) = Wildcard_All_Except_Ingress(self,of_ports)
521 Verify_TableStats(self,active_entries=2)
522
523 #Issue Non-strict Delete with match on ingress_port.Verify T+T' gets deleted .
524 NonStrict_Delete(self,match1)
525 Verify_TableStats(self,active_entries=0)
526
Rich Lane9a003812012-10-04 17:17:59 -0700527 logging.info("Inserting three overlapping flows with different priorities")
528 logging.info("Issue Non-Strict Delete command ")
529 logging.info("Expecting all the flows to get deleted")
ShreyaPandita9306c772012-09-28 12:21:40 -0400530
531 #Insert T , add Priority P (say 100 )
532 (pkt,match) = Match_All_Except_Source_Address(self,of_ports,priority=100)
533
534 #Insert T' add priority (200).
535 (pkt1,match1) = Wildcard_All_Except_Ingress(self,of_ports,priority=200)
536
537 #Insert T' again add priority 300 --> T" .
538 (pkt2,match2) = Wildcard_All_Except_Ingress(self,of_ports,priority=300)
539 Verify_TableStats(self,active_entries=3)
540
541 #Issue Non-Strict Delete and verify all getting deleted
542 NonStrict_Delete(self,match1,priority=200)
543 Verify_TableStats(self,active_entries=0)
544
Rich Lane9a003812012-10-04 17:17:59 -0700545 logging.info("Inserting three overlapping flows with different priorities")
546 logging.info("Issue Strict Delete command ")
547 logging.info("Expecting only one to get deleted because here priorities & wildcards are being matched")
ShreyaPandita9306c772012-09-28 12:21:40 -0400548
549 #Issue Strict-Delete and verify only T'' gets deleted.
550 (pkt,match) = Match_All_Except_Source_Address(self,of_ports,priority=100)
551 (pkt1,match1) = Wildcard_All_Except_Ingress(self,of_ports,priority=200)
552 (pkt2,match2) = Wildcard_All_Except_Ingress(self,of_ports,priority=300)
553 Strict_Delete(self,match1,priority=200)
554 Verify_TableStats(self,active_entries=2)
555
556
557
Rich Laneb90a1c42012-10-05 09:16:05 -0700558class Outport1(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400559
560 """Delete flows filtered by action outport.If the out_port field in the delete command contains a value other than OFPP_NONE,
561 it introduces a constraint when matching. This constraint is that the rule must contain an output action directed at that port."""
562
563 def runTest(self):
564
Rich Lane9a003812012-10-04 17:17:59 -0700565 logging.info("Outport1 test begins")
ShreyaPandita9306c772012-09-28 12:21:40 -0400566
Rich Lane477f4812012-10-04 22:49:00 -0700567 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400568 of_ports.sort()
569 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
570
571 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700572 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400573 self.assertEqual(rc, 0, "Failed to delete all flows")
574
Rich Lane9a003812012-10-04 17:17:59 -0700575 logging.info("Inserting a flow with output action --> of_port[1]")
576 logging.info("Deleting the flow but with out_port set to of_port[2]")
577 logging.info("Expecting switch to filter the delete command")
ShreyaPandita9306c772012-09-28 12:21:40 -0400578
579 #Build and send Flow-1 with action output to of_port[1]
580 (pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
581
582 # Verify active_entries in table_stats_request = 1
583 Verify_TableStats(self,active_entries=1)
584
585 #Send delete command matching the flow-1 but with contraint out_port = of_port[2]
586 msg7 = message.flow_mod()
587 msg7.out_port = of_ports[2]
588 msg7.command = ofp.OFPFC_DELETE
589 msg7.buffer_id = 0xffffffff
590 msg7.match = match
591
592 rv = self.controller.message_send(msg7)
593 self.assertTrue(rv != -1, "Error installing flow mod")
594 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
595
596 # Verify flow will not get deleted, active_entries in table_stats_request = 1
597 Verify_TableStats(self,active_entries=1)
598
Rich Lane9a003812012-10-04 17:17:59 -0700599 logging.info("Deleting the flow with out_port set to of_port[1]")
600 logging.info("Expecting switch to delete the flow")
ShreyaPandita9306c772012-09-28 12:21:40 -0400601
602 #Send Delete command with contraint out_port = of_ports[1]
603 msg7 = message.flow_mod()
604 msg7.out_port = of_ports[1]
605 msg7.command = ofp.OFPFC_DELETE
606 msg7.buffer_id = 0xffffffff
607 msg7.match = match
608
609 rv = self.controller.message_send(msg7)
610 self.assertTrue(rv != -1, "Error installing flow mod")
611 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
612
613 #Verify flow gets deleted.
614 Verify_TableStats(self,active_entries=0)
615
616
Rich Laneb90a1c42012-10-05 09:16:05 -0700617class IdleTimeout(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400618
619 """ Verify that idle timeout is implemented"""
620
621 def runTest(self):
622
Rich Lane9a003812012-10-04 17:17:59 -0700623 logging.info("Running Idle_Timeout test ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400624
Rich Lane477f4812012-10-04 22:49:00 -0700625 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400626 of_ports.sort()
627 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
628
629 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700630 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400631 self.assertEqual(rc, 0, "Failed to delete all flows")
632
Rich Lane9a003812012-10-04 17:17:59 -0700633 logging.info("Inserting flow entry with idle_timeout set. Also send_flow_removed_message flag set")
634 logging.info("Expecting the flow entry to delete with given idle_timeout")
ShreyaPandita9306c772012-09-28 12:21:40 -0400635
636 #Insert a flow entry with idle_timeout=1.Send_Flow_Rem flag set
637 msg9 = message.flow_mod()
638 msg9.match.wildcards = ofp.OFPFW_ALL
639 msg9.cookie = random.randint(0,9007199254740992)
640 msg9.buffer_id = 0xffffffff
641 msg9.idle_timeout = 1
642 msg9.flags |= ofp.OFPFF_SEND_FLOW_REM
643 rv1 = self.controller.message_send(msg9)
644 self.assertTrue(rv1 != -1, "Error installing flow mod")
645 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
646
647 #Verify flow gets inserted
648 Verify_TableStats(self,active_entries=1)
649
650 # Verify flow removed message is recieved.
651 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_FLOW_REMOVED,
652 timeout=5)
653 self.assertTrue(response is not None,
654 'Did not receive flow removed message ')
655 self.assertEqual(ofp.OFPRR_IDLE_TIMEOUT, response.reason,
656 'Flow table entry removal reason is not idle_timeout')
657 self.assertEqual(1, response.duration_sec,
658 'Flow was not alive for 1 sec')
659
660
Rich Laneb90a1c42012-10-05 09:16:05 -0700661class Outport2(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400662
663 """Add, modify flows with outport set. This field is ignored by ADD, MODIFY, and MODIFY STRICT messages."""
664
665 def runTest(self):
666
Rich Lane9a003812012-10-04 17:17:59 -0700667 logging.info("Running Outport2 test ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400668
Rich Lane477f4812012-10-04 22:49:00 -0700669 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400670 of_ports.sort()
671 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
672
673 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700674 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400675 self.assertEqual(rc, 0, "Failed to delete all flows")
676
Rich Lane9a003812012-10-04 17:17:59 -0700677 logging.info("Adding and modifying flow with out_port fields set")
678 logging.info("Expecting switch to ignore out_port")
ShreyaPandita9306c772012-09-28 12:21:40 -0400679
680 # Create and add flow-1,Action A ,output to port of_port[1], out_port set to of_ports[2]
681 (pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
682
683 # Verify flow is active
684 Verify_TableStats(self,active_entries=1)
685
686 # Send Packet matching the flow
687 SendPacket(self,pkt,of_ports[0],of_ports[1])
688
689 # Insert Flow-Modify matching flow F-1 ,action A', output to port[2], out_port set to port[3]
690 Modify_Flow_Action(self,of_ports,match)
691
692 # Again verify active_entries in table_stats_request =1
693 Verify_TableStats(self,active_entries=1)
694
695 #Verify action is modified
696 SendPacket(self,pkt,of_ports[0],of_ports[2])
697
698
699
700
Rich Laneb90a1c42012-10-05 09:16:05 -0700701class HardTimeout(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400702
703 """ Verify that hard timeout is implemented """
704
705 def runTest(self):
706
Rich Lane9a003812012-10-04 17:17:59 -0700707 logging.info("Running Hard_Timeout test ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400708
Rich Lane477f4812012-10-04 22:49:00 -0700709 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400710 of_ports.sort()
711 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
712
713 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700714 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400715 self.assertEqual(rc, 0, "Failed to delete all flows")
716
Rich Lane9a003812012-10-04 17:17:59 -0700717 logging.info("Inserting flow entry with hard_timeout set. Also send_flow_removed_message flag set")
718 logging.info("Expecting the flow entry to delete with given hard_timeout")
ShreyaPandita9306c772012-09-28 12:21:40 -0400719
720 # Insert a flow entry with hardtimeout=1 and send_flow_removed flag set
721 msg9 = message.flow_mod()
722 msg9.match.wildcards = ofp.OFPFW_ALL
723 msg9.cookie = random.randint(0,9007199254740992)
724 msg9.buffer_id = 0xffffffff
725 msg9.hard_timeout = 1
726 msg9.flags |= ofp.OFPFF_SEND_FLOW_REM
727 rv1 = self.controller.message_send(msg9)
728 self.assertTrue(rv1 != -1, "Error installing flow mod")
729 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
730
731 #Verify flow gets inserted
732 Verify_TableStats(self,active_entries=1)
733
734 # Verify flow removed message is recieved.
735 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_FLOW_REMOVED,
736 timeout=5)
737 self.assertTrue(response is not None,
738 'Did not receive flow removed message ')
739 self.assertEqual(ofp.OFPRR_HARD_TIMEOUT, response.reason,
740 'Flow table entry removal reason is not hard_timeout')
741 self.assertEqual(1, response.duration_sec,
742 'Flow was not alive for 1 sec')
743
744
Rich Laneb90a1c42012-10-05 09:16:05 -0700745class FlowTimeout(base_tests.SimpleDataPlane):
ShreyaPandita9306c772012-09-28 12:21:40 -0400746
747 """Verify that Flow removed messages are generated as expected
748 Flow removed messages being generated when flag is set, is already tested in the above tests
749 So here, we test the vice-versa condition"""
750
751
752 def runTest(self):
753
Rich Lane9a003812012-10-04 17:17:59 -0700754 logging.info("Running Flow_Timeout test ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400755
Rich Lane477f4812012-10-04 22:49:00 -0700756 of_ports = config["port_map"].keys()
ShreyaPandita9306c772012-09-28 12:21:40 -0400757 of_ports.sort()
758 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
759
760 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700761 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400762 self.assertEqual(rc, 0, "Failed to delete all flows")
763
Rich Lane9a003812012-10-04 17:17:59 -0700764 logging.info("Inserting flow entry with hard_timeout set and send_flow_removed_message flag not set")
765 logging.info("Expecting the flow entry to delete, but no flow removed message")
ShreyaPandita9306c772012-09-28 12:21:40 -0400766
767 # Insert a flow with hard_timeout = 1 but no Send_Flow_Rem flag set
768 pkt = simple_tcp_packet()
769 match3 = parse.packet_to_flow_match(pkt)
770 self.assertTrue(match3 is not None, "Could not generate flow match from pkt")
771 match3.wildcards = ofp.OFPFW_ALL-ofp.OFPFW_IN_PORT
772 match3.in_port = of_ports[0]
773 msg3 = message.flow_mod()
774 msg3.out_port = of_ports[2] # ignored by flow add,flow modify
775 msg3.command = ofp.OFPFC_ADD
776 msg3.cookie = random.randint(0,9007199254740992)
777 msg3.buffer_id = 0xffffffff
778 msg3.hard_timeout = 1
779 msg3.buffer_id = 0xffffffff
780 msg3.match = match3
781 act3 = action.action_output()
782 act3.port = of_ports[1]
783 self.assertTrue(msg3.actions.add(act3), "could not add action")
784
785 rv = self.controller.message_send(msg3)
786 self.assertTrue(rv != -1, "Error installing flow mod")
787 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
788
789 #Verify no flow removed message is generated
790 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_FLOW_REMOVED,
791 timeout=3)
792 self.assertTrue(response is None,
793 'Recieved flow removed message ')
794
795 # Verify no entries in the table
796 Verify_TableStats(self,active_entries=0)
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819