blob: b13659d399b58cda35121492d835cd75a26047c5 [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
12import oftest.controller as controller
13import oftest.cstruct as ofp
14import oftest.message as message
15import oftest.dataplane as dataplane
16import oftest.action as action
17import oftest.parse as parse
18import basic
19
Rich Laneda3b5ad2012-10-03 09:05:32 -070020from oftest.testutils import *
ShreyaPandita9306c772012-09-28 12:21:40 -040021from time import sleep
22from FuncUtils import *
23
24cs_port_map = None
ShreyaPandita9306c772012-09-28 12:21:40 -040025cs_config = None
26
27def test_set_init(config):
28
29
30 basic.test_set_init(config)
31
32 global cs_port_map
ShreyaPandita9306c772012-09-28 12:21:40 -040033 global cs_config
34
ShreyaPandita9306c772012-09-28 12:21:40 -040035 cs_port_map = config["port_map"]
36 cs_config = config
37
38
39class OverlapChecking(basic.SimpleDataPlane):
40
41 """Verify that if overlap check flag is set in the flow entry and an overlapping flow is inserted then an error
42 is generated and switch refuses flow entry"""
43
44 def runTest(self):
45
Rich Lane9a003812012-10-04 17:17:59 -070046 logging.info("Running Overlap_Checking test")
ShreyaPandita9306c772012-09-28 12:21:40 -040047
48 of_ports = cs_port_map.keys()
49 of_ports.sort()
50 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
51
52 #Clear Switch State
Rich Lane9a003812012-10-04 17:17:59 -070053 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -040054 self.assertEqual(rc, 0, "Failed to delete all flows")
55
Rich Lane9a003812012-10-04 17:17:59 -070056 logging.info("Inserting two overlapping flows")
57 logging.info("Expecting switch to return an error")
ShreyaPandita9306c772012-09-28 12:21:40 -040058
59 #Insert a flow F with wildcarded all fields
60 (pkt,match) = Wildcard_All(self,of_ports)
61
62 #Verify flow is active
63 Verify_TableStats(self,active_entries=1)
64
65 # Build a overlapping flow F'-- Wildcard All except ingress with check overlap bit set
66 Pkt_MatchIngress = simple_tcp_packet()
67 match3 = parse.packet_to_flow_match(Pkt_MatchIngress)
68 self.assertTrue(match3 is not None, "Could not generate flow match from pkt")
69 match3.wildcards = ofp.OFPFW_ALL-ofp.OFPFW_IN_PORT
70 match3.in_port = of_ports[0]
71
72 msg3 = message.flow_mod()
73 msg3.command = ofp.OFPFC_ADD
74 msg3.match = match3
75 msg3.flags |= ofp.OFPFF_CHECK_OVERLAP
76 msg3.cookie = random.randint(0,9007199254740992)
77 msg3.buffer_id = 0xffffffff
78
79 act3 = action.action_output()
80 act3.port = of_ports[1]
81 self.assertTrue(msg3.actions.add(act3), "could not add action")
82 rv = self.controller.message_send(msg3)
83 self.assertTrue(rv != -1, "Error installing flow mod")
84 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
85
86 # Verify Flow does not get inserted
87 Verify_TableStats(self,active_entries=1)
88
89 #Verify OFPET_FLOW_MOD_FAILED/OFPFMFC_OVERLAP error is recieved on the control plane
90 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_ERROR,
91 timeout=5)
92 self.assertTrue(response is not None,
93 'Switch did not reply with error message')
94 self.assertTrue(response.type==ofp.OFPET_FLOW_MOD_FAILED,
95 'Error message type is not flow mod failed ')
96 self.assertTrue(response.code==ofp.OFPFMFC_OVERLAP,
97 'Error Message code is not overlap')
98
99
100class NoOverlapChecking(basic.SimpleDataPlane):
101
102 """Verify that without overlap check flag set, overlapping flows can be created."""
103
104 def runTest(self):
105
Rich Lane9a003812012-10-04 17:17:59 -0700106 logging.info("Running No_Overlap_Checking test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400107
108 of_ports = cs_port_map.keys()
109 of_ports.sort()
110 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
111
112 #Clear Switch State
Rich Lane9a003812012-10-04 17:17:59 -0700113 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400114 self.assertEqual(rc, 0, "Failed to delete all flows")
115
Rich Lane9a003812012-10-04 17:17:59 -0700116 logging.info("Inserting two overlapping flows")
117 logging.info("Expecting switch to insert the flows without generating errors")
ShreyaPandita9306c772012-09-28 12:21:40 -0400118
119 #Build a flow F with wildcarded all fields.
120 (pkt,match) = Wildcard_All(self,of_ports)
121
122 #Verify flow is active
123 Verify_TableStats(self,active_entries=1)
124
125 # Build a overlapping flow F' without check overlap bit set.
126 Wildcard_All_Except_Ingress(self,of_ports)
127
128 # Verify Flow gets inserted
129 Verify_TableStats(self,active_entries=2)
130
131
132class IdenticalFlows(basic.SimpleDataPlane):
133
134 """Verify that adding two identical flows overwrites the existing one and clears counters"""
135
136 def runTest(self):
137
Rich Lane9a003812012-10-04 17:17:59 -0700138 logging.info("Running Identical_Flows test ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400139
140 of_ports = cs_port_map.keys()
141 of_ports.sort()
142 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
143
144 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700145 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400146 self.assertEqual(rc, 0, "Failed to delete all flows")
147
Rich Lane9a003812012-10-04 17:17:59 -0700148 logging.info("Inserting two identical flows one by one")
149 logging.info("Expecting switch to overwrite the first flow and clear the counters associated with it ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400150
151 # Create and add flow-1, check on dataplane it is active.
152 (pkt,match) = Wildcard_All(self,of_ports)
153
154 # Verify active_entries in table_stats_request =1
155 Verify_TableStats(self,active_entries=1)
156
157 # Send Packet (to increment counters like byte_count and packet_count)
158 SendPacket(self,pkt,of_ports[0],of_ports[1])
159
160 # Verify Flow counters have incremented
161 Verify_FlowStats(self,match,byte_count=len(str(pkt)),packet_count=1)
162
163 #Send Identical flow
164 (pkt1,match1) = Wildcard_All(self,of_ports)
165
166 # Verify active_entries in table_stats_request =1
167 Verify_TableStats(self,active_entries=1)
168
169 # Verify Flow counters reset
170 Verify_FlowStats(self,match,byte_count=0,packet_count=0)
171
172
173class EmerFlowTimeout(basic.SimpleProtocol):
174
175 """Timeout values are not allowed for emergency flows"""
176
177 def runTest(self):
178
Rich Lane9a003812012-10-04 17:17:59 -0700179 logging.info("Running Emergency_Flow_Timeout test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400180
181 of_ports = cs_port_map.keys()
182 of_ports.sort()
183 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
184
185 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700186 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400187 self.assertEqual(rc, 0, "Failed to delete all flows")
188
Rich Lane9a003812012-10-04 17:17:59 -0700189 logging.info("Inserting an emergency flow with timeout values")
190 logging.info("Expecting switch to generate error ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400191
192 #Insert an emergency flow
193 pkt = simple_tcp_packet()
194 match = parse.packet_to_flow_match(pkt)
195 match.in_port = of_ports[0]
196
197 request = message.flow_mod()
198 request.match = match
199 request.command = ofp.OFPFC_ADD
200 request.flags = request.flags|ofp.OFPFF_EMERG
201 request.hard_timeout =9
202 request.idle_timeout =9
203
204 act = action.action_output()
205 act.port = of_ports[1]
206
207 request.actions.add(act)
Rich Lane9a003812012-10-04 17:17:59 -0700208 logging.info("Inserting flow")
ShreyaPandita9306c772012-09-28 12:21:40 -0400209 rv = self.controller.message_send(request)
210 self.assertTrue(rv != -1, "Flow addition did not fail.")
211
212 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
213
214 #Verify OFPET_FLOW_MOD_FAILED/OFPFMFC_OVERLAP error is recieved on the control plane
215 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_ERROR,
216 timeout=5)
217 self.assertTrue(response is not None,
218 'Switch did not reply with error message')
219 self.assertTrue(response.type==ofp.OFPET_FLOW_MOD_FAILED,
220 'Error message type is not flow mod failed ')
221 self.assertTrue(response.code==ofp.OFPFMFC_BAD_EMERG_TIMEOUT,
222 'Error Message code is not bad emergency timeout')
223
224
225class MissingModifyAdd(basic.SimpleDataPlane):
226
227 """If a modify does not match an existing flow, the flow gets added """
228
229 def runTest(self):
230
Rich Lane9a003812012-10-04 17:17:59 -0700231 logging.info("Running Missing_Modify_Add test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400232
233 of_ports = cs_port_map.keys()
234 of_ports.sort()
235 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
236
Rich Lane9a003812012-10-04 17:17:59 -0700237 logging.info("Inserting a flow-modify that does not match an existing flow")
238 logging.info("Expecting flow to get added i.e OFPFC_MODIFY command should be taken as OFPFC_ADD ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400239
240 #Clear Switch State
Rich Lane9a003812012-10-04 17:17:59 -0700241 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400242 self.assertEqual(rc, 0, "Failed to delete all flows")
243
244 #Generate a flow-mod,command OFPC_MODIFY
245
246 request = message.flow_mod()
247 request.command = ofp.OFPFC_MODIFY
248 request.match.wildcards = ofp.OFPFW_ALL-ofp.OFPFW_IN_PORT
249 request.match.in_port = of_ports[0]
250 request.cookie = random.randint(0,9007199254740992)
251 request.buffer_id = 0xffffffff
252 act3 = action.action_output()
253 act3.port = of_ports[1]
254 self.assertTrue(request.actions.add(act3), "could not add action")
255
Rich Lane9a003812012-10-04 17:17:59 -0700256 logging.info("Inserting flow")
ShreyaPandita9306c772012-09-28 12:21:40 -0400257 rv = self.controller.message_send(request)
258 self.assertTrue(rv != -1, "Error installing flow mod")
259 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
260
261 #Verify the flow gets added i.e. active_count= 1
262 Verify_TableStats(self,active_entries=1)
263
264
265class ModifyAction(basic.SimpleDataPlane):
266
267 """A modified flow preserves counters"""
268
269 def runTest(self):
270
Rich Lane9a003812012-10-04 17:17:59 -0700271 logging.info("Running Modify_Action test ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400272
273 of_ports = cs_port_map.keys()
274 of_ports.sort()
275 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
276
277 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700278 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400279 self.assertEqual(rc, 0, "Failed to delete all flows")
280
Rich Lane9a003812012-10-04 17:17:59 -0700281 logging.info("Inserting a Flow and incrementing flow counters. Modifying the flow action")
282 logging.info("Expecting the flow action to be modified , but the flow-counters should be preserved")
ShreyaPandita9306c772012-09-28 12:21:40 -0400283
284 #Create and add flow-1 Match on all, except one wildcarded (src adddress).Action A , output to of_port[1]
285 (pkt,match) = Match_All_Except_Source_Address(self,of_ports)
286
287 #Send Packet matching the flow thus incrementing counters like packet_count,byte_count
288 SendPacket(self,pkt,of_ports[0],of_ports[1])
289
290 #Verify flow counters
291 Verify_FlowStats(self,match,byte_count=len(str(pkt)),packet_count=1)
292
293 #Modify flow- 1
294 Modify_Flow_Action(self,of_ports,match)
295
296 # 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]
297 SendPacket(self,pkt,of_ports[0],of_ports[2])
298
299 #Verify flow counters are preserved
300 Verify_FlowStats(self,match,byte_count=(2*len(str(pkt))),packet_count=2)
301
302
303class StrictModifyAction(basic.SimpleDataPlane):
304
305 """Strict Modify Flow also changes action preserves counters"""
306
307 def runTest(self):
308
Rich Lane9a003812012-10-04 17:17:59 -0700309 logging.info("Running Strict_Modify_Action test")
ShreyaPandita9306c772012-09-28 12:21:40 -0400310
311 of_ports = cs_port_map.keys()
312 of_ports.sort()
313 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
314
315 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700316 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400317 self.assertEqual(rc, 0, "Failed to delete all flows")
318
Rich Lane9a003812012-10-04 17:17:59 -0700319 logging.info("Inserting Flows and incrementing flow counters. Strict Modify the flow action ")
320 logging.info("Expecting the flow action to be modified , but the flow-counters should be preserved")
ShreyaPandita9306c772012-09-28 12:21:40 -0400321
322 #Create and add flow-1 Match on all, except one wildcarded (src adddress).Action A
323 (pkt,match) = Match_All_Except_Source_Address(self,of_ports,priority=100)
324
325 #Create and add flow-2 , Match on ingress_port only, Action A
326 (pkt1,match1) = Wildcard_All_Except_Ingress(self,of_ports,priority=10)
327
328 # Verify both the flows are active
329 Verify_TableStats(self,active_entries=2)
330
331 #Send a packet matching the flows, thus incrementing flow-counters (packet matches the flow F-1 with higher priority)
332 SendPacket(self,pkt,of_ports[0],of_ports[1])
333
334 # Verify flow counters of the flow-1
335 Verify_FlowStats(self,match,byte_count=len(str(pkt)),packet_count=1)
336
337 # Strict-Modify flow- 1
338 Strict_Modify_Flow_Action(self,of_ports[2],match,priority=100)
339
340 # 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]
341 SendPacket(self,pkt,of_ports[0],of_ports[2])
342
343 # Verify flow counters are preserved
344 Verify_FlowStats(self,match,byte_count=(2*len(str(pkt))),packet_count=2)
345
346
347class DeleteNonexistingFlow(basic.SimpleDataPlane):
348
349 """Request deletion of non-existing flow"""
350
351 def runTest(self):
352
Rich Lane9a003812012-10-04 17:17:59 -0700353 logging.info("Delete_NonExisting_Flow test begins")
ShreyaPandita9306c772012-09-28 12:21:40 -0400354
355 of_ports = cs_port_map.keys()
356 of_ports.sort()
357 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
358
359 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700360 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400361 self.assertEqual(rc, 0, "Failed to delete all flows")
362
Rich Lane9a003812012-10-04 17:17:59 -0700363 logging.info("Deleting a non-existing flow")
364 logging.info("Expecting switch to ignore the command , without generating errors")
ShreyaPandita9306c772012-09-28 12:21:40 -0400365
366 # Issue a delete command
367 msg = message.flow_mod()
368 msg.match.wildcards = ofp.OFPFW_ALL
369 msg.out_port = ofp.OFPP_NONE
370 msg.command = ofp.OFPFC_DELETE
371 msg.buffer_id = 0xffffffff
372
373 # Verify no message or error is generated by polling the the control plane
374 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_ERROR,
375 timeout=2)
376 self.assertTrue(response is None,
377 'Recieved Error for deleting non-exiting flow ')
378
379
380
381class SendFlowRem(basic.SimpleDataPlane):
382
383 """Check deletion of flows happens and generates messages as configured.
384 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,
385 vice versa also exists """
386
387 def runTest(self):
388
Rich Lane9a003812012-10-04 17:17:59 -0700389 logging.info("Running Send_Flow_Rem test ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400390
391 of_ports = cs_port_map.keys()
392 of_ports.sort()
393 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
394
395 #Clear swicth state
Rich Lane9a003812012-10-04 17:17:59 -0700396 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400397 self.assertEqual(rc, 0, "Failed to delete all flows")
398
Rich Lane9a003812012-10-04 17:17:59 -0700399 logging.info("Inserting flows F1 and F2 without and with send_flow_removed_message flag set ")
400 logging.info("Deleting the flows")
401 logging.info("Expecting flow removed message only for F2")
ShreyaPandita9306c772012-09-28 12:21:40 -0400402
403 # Insert flow-1 with F without OFPFF_SEND_FLOW_REM flag set.
404 (pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
405
406 # Verify flow is inserted
407 Verify_TableStats(self,active_entries=1)
408
409 #Delete the flow-1
410 NonStrict_Delete(self,match,priority=0)
411
412 # Verify no flow removed message is generated for the FLOW-1
413
414 (response1, pkt1) = self.controller.poll(exp_msg=ofp.OFPT_FLOW_REMOVED,
415 timeout=2)
416 self.assertTrue(response1 is None,
417 'Received flow removed message for the flow with flow_rem flag not set')
418
419 # Insert another flow F' with OFPFF_SEND_FLOW_REM flag set.
420 msg9 = message.flow_mod()
421 msg9.match.wildcards = ofp.OFPFW_ALL
422 msg9.cookie = random.randint(0,9007199254740992)
423 msg9.buffer_id = 0xffffffff
424 msg9.idle_timeout = 1
425 msg9.flags |= ofp.OFPFF_SEND_FLOW_REM
426 rv1 = self.controller.message_send(msg9)
427 self.assertTrue(rv1 != -1, "Error installing flow mod")
428 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
429
430 # Delete the flow-2
Rich Lane9a003812012-10-04 17:17:59 -0700431 rc2 = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400432 self.assertEqual(rc2, 0, "Failed to delete all flows")
433
434 # Verify flow removed message is generated for the FLOW-2
435
436 (response2, pkt2) = self.controller.poll(exp_msg=ofp.OFPT_FLOW_REMOVED,
437 timeout=2)
438 self.assertTrue(response2 is not None,
439 'Did not receive flow removed message for this flow')
440
441
442class DeleteEmerFlow(basic.SimpleProtocol):
443
444 """Delete emergency flow and verify no message is generated.An emergency flow deletion will not generate flow-removed messages even if
445 Send Flow removed message flag was set during the emergency flow entry"""
446
447 def runTest(self):
448
Rich Lane9a003812012-10-04 17:17:59 -0700449 logging.info("Running Delete_Emer_Flow")
ShreyaPandita9306c772012-09-28 12:21:40 -0400450
451 of_ports = cs_port_map.keys()
452 of_ports.sort()
453
454 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700455 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400456 self.assertEqual(rc, 0, "Failed to delete all flows")
457
Rich Lane9a003812012-10-04 17:17:59 -0700458 logging.info("Inserting a emergency flow with send_flow_removed flag set")
459 logging.info("Expecting no flow_removed_message on the deletion of the emergency flow")
ShreyaPandita9306c772012-09-28 12:21:40 -0400460
461 # Insert a flow with emergency bit set.
462 pkt = simple_tcp_packet()
463 match = parse.packet_to_flow_match(pkt)
464 match.in_port = of_ports[0]
465 request = message.flow_mod()
466 request.match = match
467 request.command = ofp.OFPFC_ADD
468 request.flags = request.flags|ofp.OFPFF_EMERG|ofp.OFPFF_SEND_FLOW_REM
469 act = action.action_output()
470 act.port = of_ports[1]
471 request.actions.add(act)
472
473 rv = self.controller.message_send(request)
474 self.assertTrue(rv != -1, "Flow addition failed.")
475
476 # Delete the emergency flow
477
478 NonStrict_Delete(self,match)
479 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPFF_SEND_FLOW_REM ,
480 timeout=2)
481 self.assertTrue(response is None,
482 'Test Failed ')
483
484
485class StrictVsNonstrict(basic.SimpleDataPlane):
486
487 """Delete and verify strict and non-strict behaviors
488 This test compares the behavior of delete strict and non-strict"""
489
490 def runTest(self):
491
Rich Lane9a003812012-10-04 17:17:59 -0700492 logging.info("Strict_Vs_Nonstrict test begins")
ShreyaPandita9306c772012-09-28 12:21:40 -0400493
494 of_ports = cs_port_map.keys()
495 of_ports.sort()
496 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
497
498 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700499 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400500 self.assertEqual(rc, 0, "Failed to delete all flows")
501
Rich Lane9a003812012-10-04 17:17:59 -0700502 logging.info("Inserting a flow with exact match")
503 logging.info("Issue Strict Delete command , verify it gets deleted")
ShreyaPandita9306c772012-09-28 12:21:40 -0400504
505 #Insert F with an exact Match
506 (pkt,match) = Exact_Match(self,of_ports)
507 Verify_TableStats(self,active_entries=1)
508
509 #Issue Strict Delete Command , verify F gets deleted.
510 Strict_Delete(self,match)
511 Verify_TableStats(self,active_entries=0)
512
Rich Lane9a003812012-10-04 17:17:59 -0700513 logging.info("Inserting two overlapping flows")
514 logging.info("Issue Strict Delete command ")
515 logging.info("Expecting only one flow gets deleted , because Strict Delete matches on wildcards as well")
ShreyaPandita9306c772012-09-28 12:21:40 -0400516
517 #Insert Flow T with match on all , except one wildcarded ( say src adddress ).
518 (pkt,match) = Match_All_Except_Source_Address(self,of_ports)
519
520 #Insert another flow T' with match on ingress_port , wildcarded rest.
521 (pkt1,match1) = Wildcard_All_Except_Ingress(self,of_ports)
522 Verify_TableStats(self,active_entries=2)
523
524 #Issue Strict Delete matching on ingress_port. Verify only T' gets deleted
525 Strict_Delete(self,match1)
526 Verify_TableStats(self,active_entries=1)
527
Rich Lane9a003812012-10-04 17:17:59 -0700528 logging.info("Inserting two overlapping flows")
529 logging.info("Issue Non-Strict Delete command ")
530 logging.info("Expecting both the flow gets deleted , because wildcards are active")
ShreyaPandita9306c772012-09-28 12:21:40 -0400531
532 #Insert T and T' again .
533 (pkt,match) = Match_All_Except_Source_Address(self,of_ports)
534 (pkt1,match1) = Wildcard_All_Except_Ingress(self,of_ports)
535 Verify_TableStats(self,active_entries=2)
536
537 #Issue Non-strict Delete with match on ingress_port.Verify T+T' gets deleted .
538 NonStrict_Delete(self,match1)
539 Verify_TableStats(self,active_entries=0)
540
Rich Lane9a003812012-10-04 17:17:59 -0700541 logging.info("Inserting three overlapping flows with different priorities")
542 logging.info("Issue Non-Strict Delete command ")
543 logging.info("Expecting all the flows to get deleted")
ShreyaPandita9306c772012-09-28 12:21:40 -0400544
545 #Insert T , add Priority P (say 100 )
546 (pkt,match) = Match_All_Except_Source_Address(self,of_ports,priority=100)
547
548 #Insert T' add priority (200).
549 (pkt1,match1) = Wildcard_All_Except_Ingress(self,of_ports,priority=200)
550
551 #Insert T' again add priority 300 --> T" .
552 (pkt2,match2) = Wildcard_All_Except_Ingress(self,of_ports,priority=300)
553 Verify_TableStats(self,active_entries=3)
554
555 #Issue Non-Strict Delete and verify all getting deleted
556 NonStrict_Delete(self,match1,priority=200)
557 Verify_TableStats(self,active_entries=0)
558
Rich Lane9a003812012-10-04 17:17:59 -0700559 logging.info("Inserting three overlapping flows with different priorities")
560 logging.info("Issue Strict Delete command ")
561 logging.info("Expecting only one to get deleted because here priorities & wildcards are being matched")
ShreyaPandita9306c772012-09-28 12:21:40 -0400562
563 #Issue Strict-Delete and verify only T'' gets deleted.
564 (pkt,match) = Match_All_Except_Source_Address(self,of_ports,priority=100)
565 (pkt1,match1) = Wildcard_All_Except_Ingress(self,of_ports,priority=200)
566 (pkt2,match2) = Wildcard_All_Except_Ingress(self,of_ports,priority=300)
567 Strict_Delete(self,match1,priority=200)
568 Verify_TableStats(self,active_entries=2)
569
570
571
572class Outport1(basic.SimpleDataPlane):
573
574 """Delete flows filtered by action outport.If the out_port field in the delete command contains a value other than OFPP_NONE,
575 it introduces a constraint when matching. This constraint is that the rule must contain an output action directed at that port."""
576
577 def runTest(self):
578
Rich Lane9a003812012-10-04 17:17:59 -0700579 logging.info("Outport1 test begins")
ShreyaPandita9306c772012-09-28 12:21:40 -0400580
581 of_ports = cs_port_map.keys()
582 of_ports.sort()
583 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
584
585 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700586 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400587 self.assertEqual(rc, 0, "Failed to delete all flows")
588
Rich Lane9a003812012-10-04 17:17:59 -0700589 logging.info("Inserting a flow with output action --> of_port[1]")
590 logging.info("Deleting the flow but with out_port set to of_port[2]")
591 logging.info("Expecting switch to filter the delete command")
ShreyaPandita9306c772012-09-28 12:21:40 -0400592
593 #Build and send Flow-1 with action output to of_port[1]
594 (pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
595
596 # Verify active_entries in table_stats_request = 1
597 Verify_TableStats(self,active_entries=1)
598
599 #Send delete command matching the flow-1 but with contraint out_port = of_port[2]
600 msg7 = message.flow_mod()
601 msg7.out_port = of_ports[2]
602 msg7.command = ofp.OFPFC_DELETE
603 msg7.buffer_id = 0xffffffff
604 msg7.match = match
605
606 rv = self.controller.message_send(msg7)
607 self.assertTrue(rv != -1, "Error installing flow mod")
608 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
609
610 # Verify flow will not get deleted, active_entries in table_stats_request = 1
611 Verify_TableStats(self,active_entries=1)
612
Rich Lane9a003812012-10-04 17:17:59 -0700613 logging.info("Deleting the flow with out_port set to of_port[1]")
614 logging.info("Expecting switch to delete the flow")
ShreyaPandita9306c772012-09-28 12:21:40 -0400615
616 #Send Delete command with contraint out_port = of_ports[1]
617 msg7 = message.flow_mod()
618 msg7.out_port = of_ports[1]
619 msg7.command = ofp.OFPFC_DELETE
620 msg7.buffer_id = 0xffffffff
621 msg7.match = match
622
623 rv = self.controller.message_send(msg7)
624 self.assertTrue(rv != -1, "Error installing flow mod")
625 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
626
627 #Verify flow gets deleted.
628 Verify_TableStats(self,active_entries=0)
629
630
631class IdleTimeout(basic.SimpleDataPlane):
632
633 """ Verify that idle timeout is implemented"""
634
635 def runTest(self):
636
Rich Lane9a003812012-10-04 17:17:59 -0700637 logging.info("Running Idle_Timeout test ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400638
639 of_ports = cs_port_map.keys()
640 of_ports.sort()
641 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
642
643 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700644 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400645 self.assertEqual(rc, 0, "Failed to delete all flows")
646
Rich Lane9a003812012-10-04 17:17:59 -0700647 logging.info("Inserting flow entry with idle_timeout set. Also send_flow_removed_message flag set")
648 logging.info("Expecting the flow entry to delete with given idle_timeout")
ShreyaPandita9306c772012-09-28 12:21:40 -0400649
650 #Insert a flow entry with idle_timeout=1.Send_Flow_Rem flag set
651 msg9 = message.flow_mod()
652 msg9.match.wildcards = ofp.OFPFW_ALL
653 msg9.cookie = random.randint(0,9007199254740992)
654 msg9.buffer_id = 0xffffffff
655 msg9.idle_timeout = 1
656 msg9.flags |= ofp.OFPFF_SEND_FLOW_REM
657 rv1 = self.controller.message_send(msg9)
658 self.assertTrue(rv1 != -1, "Error installing flow mod")
659 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
660
661 #Verify flow gets inserted
662 Verify_TableStats(self,active_entries=1)
663
664 # Verify flow removed message is recieved.
665 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_FLOW_REMOVED,
666 timeout=5)
667 self.assertTrue(response is not None,
668 'Did not receive flow removed message ')
669 self.assertEqual(ofp.OFPRR_IDLE_TIMEOUT, response.reason,
670 'Flow table entry removal reason is not idle_timeout')
671 self.assertEqual(1, response.duration_sec,
672 'Flow was not alive for 1 sec')
673
674
675class Outport2(basic.SimpleDataPlane):
676
677 """Add, modify flows with outport set. This field is ignored by ADD, MODIFY, and MODIFY STRICT messages."""
678
679 def runTest(self):
680
Rich Lane9a003812012-10-04 17:17:59 -0700681 logging.info("Running Outport2 test ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400682
683 of_ports = cs_port_map.keys()
684 of_ports.sort()
685 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
686
687 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700688 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400689 self.assertEqual(rc, 0, "Failed to delete all flows")
690
Rich Lane9a003812012-10-04 17:17:59 -0700691 logging.info("Adding and modifying flow with out_port fields set")
692 logging.info("Expecting switch to ignore out_port")
ShreyaPandita9306c772012-09-28 12:21:40 -0400693
694 # Create and add flow-1,Action A ,output to port of_port[1], out_port set to of_ports[2]
695 (pkt,match) = Wildcard_All_Except_Ingress(self,of_ports)
696
697 # Verify flow is active
698 Verify_TableStats(self,active_entries=1)
699
700 # Send Packet matching the flow
701 SendPacket(self,pkt,of_ports[0],of_ports[1])
702
703 # Insert Flow-Modify matching flow F-1 ,action A', output to port[2], out_port set to port[3]
704 Modify_Flow_Action(self,of_ports,match)
705
706 # Again verify active_entries in table_stats_request =1
707 Verify_TableStats(self,active_entries=1)
708
709 #Verify action is modified
710 SendPacket(self,pkt,of_ports[0],of_ports[2])
711
712
713
714
715class HardTimeout(basic.SimpleDataPlane):
716
717 """ Verify that hard timeout is implemented """
718
719 def runTest(self):
720
Rich Lane9a003812012-10-04 17:17:59 -0700721 logging.info("Running Hard_Timeout test ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400722
723 of_ports = cs_port_map.keys()
724 of_ports.sort()
725 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
726
727 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700728 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400729 self.assertEqual(rc, 0, "Failed to delete all flows")
730
Rich Lane9a003812012-10-04 17:17:59 -0700731 logging.info("Inserting flow entry with hard_timeout set. Also send_flow_removed_message flag set")
732 logging.info("Expecting the flow entry to delete with given hard_timeout")
ShreyaPandita9306c772012-09-28 12:21:40 -0400733
734 # Insert a flow entry with hardtimeout=1 and send_flow_removed flag set
735 msg9 = message.flow_mod()
736 msg9.match.wildcards = ofp.OFPFW_ALL
737 msg9.cookie = random.randint(0,9007199254740992)
738 msg9.buffer_id = 0xffffffff
739 msg9.hard_timeout = 1
740 msg9.flags |= ofp.OFPFF_SEND_FLOW_REM
741 rv1 = self.controller.message_send(msg9)
742 self.assertTrue(rv1 != -1, "Error installing flow mod")
743 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
744
745 #Verify flow gets inserted
746 Verify_TableStats(self,active_entries=1)
747
748 # Verify flow removed message is recieved.
749 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_FLOW_REMOVED,
750 timeout=5)
751 self.assertTrue(response is not None,
752 'Did not receive flow removed message ')
753 self.assertEqual(ofp.OFPRR_HARD_TIMEOUT, response.reason,
754 'Flow table entry removal reason is not hard_timeout')
755 self.assertEqual(1, response.duration_sec,
756 'Flow was not alive for 1 sec')
757
758
759class FlowTimeout(basic.SimpleDataPlane):
760
761 """Verify that Flow removed messages are generated as expected
762 Flow removed messages being generated when flag is set, is already tested in the above tests
763 So here, we test the vice-versa condition"""
764
765
766 def runTest(self):
767
Rich Lane9a003812012-10-04 17:17:59 -0700768 logging.info("Running Flow_Timeout test ")
ShreyaPandita9306c772012-09-28 12:21:40 -0400769
770 of_ports = cs_port_map.keys()
771 of_ports.sort()
772 self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
773
774 #Clear switch state
Rich Lane9a003812012-10-04 17:17:59 -0700775 rc = delete_all_flows(self.controller)
ShreyaPandita9306c772012-09-28 12:21:40 -0400776 self.assertEqual(rc, 0, "Failed to delete all flows")
777
Rich Lane9a003812012-10-04 17:17:59 -0700778 logging.info("Inserting flow entry with hard_timeout set and send_flow_removed_message flag not set")
779 logging.info("Expecting the flow entry to delete, but no flow removed message")
ShreyaPandita9306c772012-09-28 12:21:40 -0400780
781 # Insert a flow with hard_timeout = 1 but no Send_Flow_Rem flag set
782 pkt = simple_tcp_packet()
783 match3 = parse.packet_to_flow_match(pkt)
784 self.assertTrue(match3 is not None, "Could not generate flow match from pkt")
785 match3.wildcards = ofp.OFPFW_ALL-ofp.OFPFW_IN_PORT
786 match3.in_port = of_ports[0]
787 msg3 = message.flow_mod()
788 msg3.out_port = of_ports[2] # ignored by flow add,flow modify
789 msg3.command = ofp.OFPFC_ADD
790 msg3.cookie = random.randint(0,9007199254740992)
791 msg3.buffer_id = 0xffffffff
792 msg3.hard_timeout = 1
793 msg3.buffer_id = 0xffffffff
794 msg3.match = match3
795 act3 = action.action_output()
796 act3.port = of_ports[1]
797 self.assertTrue(msg3.actions.add(act3), "could not add action")
798
799 rv = self.controller.message_send(msg3)
800 self.assertTrue(rv != -1, "Error installing flow mod")
801 self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
802
803 #Verify no flow removed message is generated
804 (response, pkt) = self.controller.poll(exp_msg=ofp.OFPT_FLOW_REMOVED,
805 timeout=3)
806 self.assertTrue(response is None,
807 'Recieved flow removed message ')
808
809 # Verify no entries in the table
810 Verify_TableStats(self,active_entries=0)
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833