blob: 067ed3e3e31e4dbdcc6bac2588fb7949fb203d71 [file] [log] [blame]
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001"""
2 Wrapper functions for FuncIntent
3 This functions include Onosclidriver and Mininetclidriver driver functions
4 Author: kelvin@onlab.us
5"""
6import time
7import copy
8import json
9
10def __init__( self ):
11 self.default = ''
12
Jeremy Songster1f39bf02016-01-20 17:17:25 -080013def installHostIntent( main,
14 name,
15 host1,
16 host2,
17 onosNode=0,
18 ethType="",
19 bandwidth="",
20 lambdaAlloc=False,
21 ipProto="",
22 ipAddresses="",
23 tcp="",
24 sw1="",
25 sw2=""):
kelvin-onlabd48a68c2015-07-13 16:01:36 -070026 """
Jeremy Songster1f39bf02016-01-20 17:17:25 -080027 Installs a Host Intent
28
kelvin-onlab58dc39e2015-08-06 08:11:09 -070029 Description:
Jeremy Songster1f39bf02016-01-20 17:17:25 -080030 Install a host intent using
31 add-host-intent
32
kelvin-onlab58dc39e2015-08-06 08:11:09 -070033 Steps:
Jeremy Songster1f39bf02016-01-20 17:17:25 -080034 - Fetch host data if not given
35 - Add host intent
36 - Ingress device is the first sender host
37 - Egress devices are the recipient devices
38 - Ports if defined in senders or recipients
39 - MAC address ethSrc loaded from Ingress device
40 - Check intent state with retry
kelvin-onlab58dc39e2015-08-06 08:11:09 -070041 Required:
42 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
Jeremy Songster1f39bf02016-01-20 17:17:25 -080043 host1 - Dictionary for host1
44 { "name":"h8", "id":"of:0000000000000005/8" }
45 host2 - Dictionary for host2
46 { "name":"h16", "id":"of:0000000000000006/8" }
kelvin-onlab58dc39e2015-08-06 08:11:09 -070047 Optional:
48 onosNode - ONOS node to install the intents in main.CLIs[ ]
49 0 by default so that it will always use the first
50 ONOS node
kelvin-onlab58dc39e2015-08-06 08:11:09 -070051 ethType - Ethernet type eg. IPV4, IPV6
kelvin-onlab58dc39e2015-08-06 08:11:09 -070052 bandwidth - Bandwidth capacity
53 lambdaAlloc - Allocate lambda, defaults to False
54 ipProto - IP protocol
Jeremy Songster1f39bf02016-01-20 17:17:25 -080055 tcp - TCP ports in the same order as the hosts in hostNames
56 """
57
58 assert main, "There is no main variable"
59 assert host1, "You must specify host1"
60 assert host2, "You must specify host2"
61
62 global itemName # The name of this run. Used for logs.
63 itemName = name
64 onosNode = int( onosNode )
65
66 main.log.info( itemName + ": Adding single point to multi point intents" )
67
68 if not host1.get( "id" ):
69 main.log.warn( "ID not given for host1 {0}. Loading from main.hostData".format( host1.get( "name" ) ) )
70 main.log.debug( main.hostsData.get( host1.get( "name" ) ) )
71 host1[ "id" ] = main.hostsData.get( host1.get( "name" ) ).get( "id" )
72
73 if not host2.get( "id" ):
74 main.log.warn( "ID not given for host2 {0}. Loading from main.h ostData".format( host2.get( "name" ) ) )
75 host2[ "id" ] = main.hostsData.get( host2.get( "name" ) ).get( "id" )
76
77 # Adding point intent
78 intentId = main.CLIs[ onosNode ].addHostIntent( hostIdOne=host1.get( "id" ),
79 hostIdTwo=host2.get( "id" ) )
80
81 # Check intents state
82 if utilities.retry( f=checkIntentState, retValue=main.FALSE,
83 args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
84 return intentId
85 else:
86 main.log.error( "Single to Multi Intent did not install correctly" )
87 return main.FALSE
88
89def testHostIntent( main,
90 name,
91 intentId,
92 host1,
93 host2,
94 onosNode=0,
95 sw1="s5",
96 sw2="s2",
97 expectedLink=0):
98 """
99 Test a Host Intent
100
101 Description:
102 Test a host intent of given ID between given hosts
103
104 Steps:
105 - Fetch host data if not given
106 - Check Intent State
107 - Check Flow State
108 - Check Connectivity
109 - Check Lack of Connectivity Between Hosts not in the Intent
110 - Reroute
111 - Take Expected Link Down
112 - Check Intent State
113 - Check Flow State
114 - Check Topology
115 - Check Connectivity
116 - Bring Expected Link Up
117 - Check Intent State
118 - Check Flow State
119 - Check Topology
120 - Check Connectivity
121 - Remove Topology
122
123 Required:
124 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
125 intentId - intent ID to be tested ( and removed )
126 host1 - Dictionary for host1
127 { "name":"h8", "id":"of:0000000000000005/8" }
128 host2 - Dictionary for host2
129 { "name":"h16", "id":"of:0000000000000006/8" }
130 Optional:
131 onosNode - ONOS node to install the intents in main.CLIs[ ]
132 0 by default so that it will always use the first
133 ONOS node
134 sw1 - First switch to bring down & up for rerouting purpose
135 sw2 - Second switch to bring down & up for rerouting purpose
136 expectedLink - Expected link when the switches are down, it should
137 be two links lower than the links before the two
138 switches are down
139
140 """
141
142 # Parameter Validity Check
143 assert main, "There is no main variable"
144 assert host1, "You must specify host1"
145 assert host2, "You must specify host2"
146
147 global itemName
148 itemName = name
149 tempHostsData = {}
150 onosNode = int( onosNode )
151
152 main.log.info( itemName + ": Testing Single to Multi Point Intent" )
153
154 if not host1.get( "id" ):
155 main.log.warn( "Id not given for host1 {0}. Loading from main.hostData".format( host1.get( "name" ) ) )
156 host1[ "id" ] = main.hostsData.get( host1.get( "name" ) ).get( "location" )
157
158 if not host2.get( "id" ):
159 main.log.warn( "Id not given for host2 {0}. Loading from main.hostData".format( host2.get( "name" ) ) )
160 host2[ "id" ] = main.hostsData.get( host2.get( "name" ) ).get( "location" )
161
162 senderNames = [ host1.get( "name" ), host2.get( "name" ) ]
163 recipientNames = [ host1.get( "name" ), host2.get( "name" ) ]
164
165 testResult = main.TRUE
166 main.log.info( itemName + ": Adding single point to multi point intents" )
167
168 # Check intent state
169 if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
170 main.assertReturnString += 'Initial Intent State Passed\n'
171 else:
172 main.assertReturnString += 'Initial Intent State Failed\n'
173 testResult = main.FALSE
174
175 # Check flows count in each node
176 if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ] ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ] ):
177 main.assertReturnString += 'Initial Flow State Passed\n'
178 else:
179 main.assertReturnString += 'Intial Flow State Failed\n'
180 testResult = main.FALSE
181
182 # Check Connectivity
183 if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames ) ):
184 main.assertReturnString += 'Initial Ping Passed\n'
185 else:
186 main.assertReturnString += 'Initial Ping Failed\n'
187 testResult = main.FALSE
188
189 # Test rerouting if these variables exist
190 if sw1 and sw2 and expectedLink:
191 # Take link down
192 if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "down" ) ):
193 main.assertReturnString += 'Link Down Passed\n'
194 else:
195 main.assertReturnString += 'Link Down Failed\n'
196 testResult = main.FALSE
197
198 # Check intent state
199 if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
200 main.assertReturnString += 'Link Down Intent State Passed\n'
201 else:
202 main.assertReturnString += 'Link Down Intent State Failed\n'
203 testResult = main.FALSE
204
205 # Check flows count in each node
206 if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ] ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ] ):
207 main.assertReturnString += 'Link Down Flow State Passed\n'
208 else:
209 main.assertReturnString += 'Link Down Flow State Failed\n'
210 testResult = main.FALSE
211
212 # Check OnosTopology
213 if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink ) ):
214 main.assertReturnString += 'Link Down Topology State Passed\n'
215 else:
216 main.assertReturnString += 'Link Down Topology State Failed\n'
217 testResult = main.FALSE
218
219 # Check Connection
220 if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames ) ):
221 main.assertReturnString += 'Link Down Pingall Passed\n'
222 else:
223 main.assertReturnString += 'Link Down Pingall Failed\n'
224 testResult = main.FALSE
225
226 # Bring link up
227 if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "up" ) ):
228 main.assertReturnString += 'Link Up Passed\n'
229 else:
230 main.assertReturnString += 'Link Up Failed\n'
231 testResult = main.FALSE
232
233 # Wait for reroute
234 time.sleep( main.rerouteSleep )
235
236 # Check Intents
237 if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
238 main.assertReturnString += 'Link Up Intent State Passed\n'
239 else:
240 main.assertReturnString += 'Link Up Intent State Failed\n'
241 testResult = main.FALSE
242
243 # Check flows count in each node
244 if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ] ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ] ):
245 main.assertReturnString += 'Link Up Flow State Passed\n'
246 else:
247 main.assertReturnString += 'Link Up Flow State Failed\n'
248 testResult = main.FALSE
249
250 # Check OnosTopology
251 if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, main.numLinks ) ):
252 main.assertReturnString += 'Link Up Topology State Passed\n'
253 else:
254 main.assertReturnString += 'Link Up Topology State Failed\n'
255 testResult = main.FALSE
256
257 # Check Connection
258 if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames ) ):
259 main.assertReturnString += 'Link Up Pingall Passed\n'
260 else:
261 main.assertReturnString += 'Link Up Pingall Failed\n'
262 testResult = main.FALSE
263
264 # Remove all intents
265 if utilities.retry( f=removeAllIntents, retValue=main.FALSE, args=( main, [ intentId ] ) ):
266 main.assertReturnString += 'Remove Intents Passed'
267 else:
268 main.assertReturnString += 'Remove Intents Failed'
269 testResult = main.FALSE
270
271 return testResult
272
273def installPointIntent( main,
274 name,
275 senders,
276 recipients,
277 onosNode=0,
278 ethType="",
279 bandwidth="",
280 lambdaAlloc=False,
281 ipProto="",
282 ipSrc="",
283 ipDst="",
284 tcpSrc="",
285 tcpDst=""):
286 """
287 Installs a Single to Single Point Intent
288
289 Description:
290 Install a single to single point intent
291
292 Steps:
293 - Fetch host data if not given
294 - Add point intent
295 - Ingress device is the first sender device
296 - Egress device is the first recipient device
297 - Ports if defined in senders or recipients
298 - MAC address ethSrc loaded from Ingress device
299 - Check intent state with retry
300 Required:
301 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
302 senders - List of host dictionaries i.e.
303 [ { "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" } ]
304 recipients - List of host dictionaries i.e.
305 [ { "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" } ]
306 Optional:
307 onosNode - ONOS node to install the intents in main.CLIs[ ]
308 0 by default so that it will always use the first
309 ONOS node
310 ethType - Ethernet type eg. IPV4, IPV6
311 bandwidth - Bandwidth capacity
312 lambdaAlloc - Allocate lambda, defaults to False
313 ipProto - IP protocol
314 tcp - TCP ports in the same order as the hosts in hostNames
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700315 sw1 - First switch to bring down & up for rerouting purpose
316 sw2 - Second switch to bring down & up for rerouting purpose
317 expectedLink - Expected link when the switches are down, it should
318 be two links lower than the links before the two
319 switches are down
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700320 """
321
322 assert main, "There is no main variable"
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800323 assert senders, "You must specify a sender"
324 assert recipients, "You must specify a recipient"
325 # Assert devices or main.hostsData, "You must specify devices"
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700326
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800327 global itemName # The name of this run. Used for logs.
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700328 itemName = name
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700329 onosNode = int( onosNode )
330
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800331 main.log.info( itemName + ": Adding mutli to single point intents" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700332
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800333 for sender in senders:
334 if not sender.get( "device" ):
335 main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
336 sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
337
338 for recipient in recipients:
339 if not recipient.get( "device" ):
340 main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
341 recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
342
343
344 ingressDevice = senders[ 0 ].get( "device" )
345 egressDevice = recipients[ 0 ].get( "device" )
346
347 portIngress = senders[ 0 ].get( "port", "" )
348 portEgress = recipients[ 0 ].get( "port", "" )
349
350 dstMac = recipients[ 0 ].get( "mac" )
351
352 ipSrc = senders[ 0 ].get( "ip" )
353 ipDst = recipients[ 0 ].get( "ip" )
354
355 # Adding point intent
356 intentId = main.CLIs[ onosNode ].addPointIntent(
357 ingressDevice=ingressDevice,
358 egressDevice=egressDevice,
359 portIngress=portIngress,
360 portEgress=portEgress,
361 ethType=ethType,
362 ethDst=dstMac,
363 bandwidth=bandwidth,
364 lambdaAlloc=lambdaAlloc,
365 ipProto=ipProto,
366 ipSrc=ipSrc,
367 ipDst=ipDst,
368 tcpSrc=tcpSrc,
369 tcpDst=tcpDst )
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700370
371 # Check intents state
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800372 if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
373 return intentId
acsmarsd4862d12015-10-06 17:57:34 -0700374 else:
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800375 main.log.error( "Point Intent did not install correctly" )
376 return main.FALSE
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700377
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700378def pointIntentTcp( main,
379 name,
380 host1,
381 host2,
382 onosNode=0,
383 deviceId1="",
384 deviceId2="",
385 port1="",
386 port2="",
387 ethType="",
388 mac1="",
389 mac2="",
390 bandwidth="",
391 lambdaAlloc=False,
392 ipProto="",
393 ip1="",
394 ip2="",
395 tcp1="",
396 tcp2="",
397 sw1="",
398 sw2="",
399 expectedLink=0 ):
400
401 """
402 Description:
403 Verify add-point-intent only for TCP
404 Steps:
405 - Get device ids | ports
406 - Add point intents
407 - Check intents
408 - Verify flows
409 - Ping hosts
410 - Reroute
411 - Link down
412 - Verify flows
413 - Check topology
414 - Ping hosts
415 - Link up
416 - Verify flows
417 - Check topology
418 - Ping hosts
419 - Remove intents
420 Required:
421 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
422 host1 - Name of first host
423 host2 - Name of second host
424 Optional:
425 onosNode - ONOS node to install the intents in main.CLIs[ ]
426 0 by default so that it will always use the first
427 ONOS node
428 deviceId1 - ONOS device id of the first switch, the same as the
429 location of the first host eg. of:0000000000000001/1,
430 located at device 1 port 1
431 deviceId2 - ONOS device id of the second switch
432 port1 - The port number where the first host is attached
433 port2 - The port number where the second host is attached
434 ethType - Ethernet type eg. IPV4, IPV6
435 mac1 - Mac address of first host
436 mac2 - Mac address of the second host
437 bandwidth - Bandwidth capacity
438 lambdaAlloc - Allocate lambda, defaults to False
439 ipProto - IP protocol
440 ip1 - IP address of first host
441 ip2 - IP address of second host
442 tcp1 - TCP port of first host
443 tcp2 - TCP port of second host
444 sw1 - First switch to bring down & up for rerouting purpose
445 sw2 - Second switch to bring down & up for rerouting purpose
446 expectedLink - Expected link when the switches are down, it should
447 be two links lower than the links before the two
448 switches are down
449 """
450
451 assert main, "There is no main variable"
452 assert name, "variable name is empty"
453 assert host1 and host2, "You must specify hosts"
454
455 global itemName
456 itemName = name
457 host1 = host1
458 host2 = host2
459 hostNames = [ host1, host2 ]
460 intentsId = []
461
462 iperfResult = main.TRUE
463 intentResult = main.TRUE
464 removeIntentResult = main.TRUE
465 flowResult = main.TRUE
466 topoResult = main.TRUE
467 linkDownResult = main.TRUE
468 linkUpResult = main.TRUE
469 onosNode = int( onosNode )
470
471 # Adding bidirectional point intents
472 main.log.info( itemName + ": Adding point intents" )
473 intent1 = main.CLIs[ onosNode ].addPointIntent( ingressDevice=deviceId1,
474 egressDevice=deviceId2,
475 portIngress=port1,
476 portEgress=port2,
477 ethType=ethType,
478 ethSrc=mac1,
479 ethDst=mac2,
480 bandwidth=bandwidth,
481 lambdaAlloc=lambdaAlloc,
482 ipProto=ipProto,
483 ipSrc=ip1,
484 ipDst=ip2,
485 tcpSrc=tcp1,
486 tcpDst="" )
487
488 intent2 = main.CLIs[ onosNode ].addPointIntent( ingressDevice=deviceId2,
489 egressDevice=deviceId1,
490 portIngress=port2,
491 portEgress=port1,
492 ethType=ethType,
493 ethSrc=mac2,
494 ethDst=mac1,
495 bandwidth=bandwidth,
496 lambdaAlloc=lambdaAlloc,
497 ipProto=ipProto,
498 ipSrc=ip2,
499 ipDst=ip1,
500 tcpSrc=tcp2,
501 tcpDst="" )
502
503 intent3 = main.CLIs[ onosNode ].addPointIntent( ingressDevice=deviceId1,
504 egressDevice=deviceId2,
505 portIngress=port1,
506 portEgress=port2,
507 ethType=ethType,
508 ethSrc=mac1,
509 ethDst=mac2,
510 bandwidth=bandwidth,
511 lambdaAlloc=lambdaAlloc,
512 ipProto=ipProto,
513 ipSrc=ip1,
514 ipDst=ip2,
515 tcpSrc="",
516 tcpDst=tcp2 )
517
518 intent4 = main.CLIs[ onosNode ].addPointIntent( ingressDevice=deviceId2,
519 egressDevice=deviceId1,
520 portIngress=port2,
521 portEgress=port1,
522 ethType=ethType,
523 ethSrc=mac2,
524 ethDst=mac1,
525 bandwidth=bandwidth,
526 lambdaAlloc=lambdaAlloc,
527 ipProto=ipProto,
528 ipSrc=ip2,
529 ipDst=ip1,
530 tcpSrc="",
531 tcpDst=tcp1 )
532 intentsId.append( intent1 )
533 intentsId.append( intent2 )
534 intentsId.append( intent3 )
535 intentsId.append( intent4 )
536
537 # Check intents state
538 time.sleep( main.checkIntentSleep )
539 intentResult = checkIntentState( main, intentsId )
540 # Check flows count in each node
541 checkFlowsCount( main )
542
543 # Check intents state again if first check fails...
544 if not intentResult:
545 intentResult = checkIntentState( main, intentsId )
546
547 # Check flows count in each node
548 checkFlowsCount( main )
549
550 # Verify flows
551 checkFlowsState( main )
552
553 # Run iperf to both host
acsmarsd4862d12015-10-06 17:57:34 -0700554 iperfTemp = main.Mininet1.iperftcp( host1,host2,10 )
555 iperfResult = iperfResult and iperfTemp
556 if iperfTemp:
557 main.assertReturnString += 'Initial Iperf Passed\n'
558 else:
559 main.assertReturnString += 'Initial Iperf Failed\n'
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700560
561 # Test rerouting if these variables exist
562 if sw1 and sw2 and expectedLink:
563 # link down
564 linkDownResult = link( main, sw1, sw2, "down" )
acsmarsd4862d12015-10-06 17:57:34 -0700565
566 if linkDownResult:
567 main.assertReturnString += 'Link Down Passed\n'
568 else:
569 main.assertReturnString += 'Link Down Failed\n'
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700570
571 # Check flows count in each node
572 checkFlowsCount( main )
573 # Verify flows
574 checkFlowsState( main )
575
576 # Check OnosTopology
577 topoResult = checkTopology( main, expectedLink )
acsmarsd4862d12015-10-06 17:57:34 -0700578 if topoResult:
579 main.assertReturnString += 'Link Down Topology State Passed\n'
580 else:
581 main.assertReturnString += 'Link Down Topology State Failed\n'
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700582
583 # Run iperf to both host
acsmarsd4862d12015-10-06 17:57:34 -0700584 iperfTemp = main.Mininet1.iperftcp( host1,host2,10 )
585 iperfResult = iperfResult and iperfTemp
586 if iperfTemp:
587 main.assertReturnString += 'Link Down Iperf Passed\n'
588 else:
589 main.assertReturnString += 'Link Down Iperf Failed\n'
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700590
acsmarsd4862d12015-10-06 17:57:34 -0700591 # Check intent state
592 intentTemp = checkIntentState( main, intentsId )
593 intentResult = intentResult and intentTemp
594 if intentTemp:
595 main.assertReturnString += 'Link Down Intent State Passed\n'
596 else:
597 main.assertReturnString += 'Link Down Intent State Failed\n'
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700598
599 # Checks ONOS state in link down
600 if linkDownResult and topoResult and iperfResult and intentResult:
601 main.log.info( itemName + ": Successfully brought link down" )
602 else:
603 main.log.error( itemName + ": Failed to bring link down" )
604
605 # link up
606 linkUpResult = link( main, sw1, sw2, "up" )
acsmarsd4862d12015-10-06 17:57:34 -0700607 if linkUpTemp:
608 main.assertReturnString += 'Link Up Passed\n'
609 else:
610 main.assertReturnString += 'Link Up Failed\n'
611
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700612 time.sleep( main.rerouteSleep )
613
614 # Check flows count in each node
615 checkFlowsCount( main )
616 # Verify flows
617 checkFlowsState( main )
618
619 # Check OnosTopology
620 topoResult = checkTopology( main, main.numLinks )
621
acsmarsd4862d12015-10-06 17:57:34 -0700622 if topoResult:
623 main.assertReturnString += 'Link Up Topology State Passed\n'
624 else:
625 main.assertReturnString += 'Link Up Topology State Failed\n'
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700626
acsmarsd4862d12015-10-06 17:57:34 -0700627 # Run iperf to both host
628 iperfTemp = main.Mininet1.iperftcp( host1,host2,10 )
629 iperfResult = iperfResult and iperfTemp
630 if iperfTemp:
631 main.assertReturnString += 'Link Up Iperf Passed\n'
632 else:
633 main.assertReturnString += 'Link Up Iperf Failed\n'
634
635 # Check intent state
636 intentTemp = checkIntentState( main, intentsId )
637 intentResult = intentResult and intentTemp
638 if intentTemp:
639 main.assertReturnString += 'Link Down Intent State Passed\n'
640 else:
641 main.assertReturnString += 'Link Down Intent State Failed\n'
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700642
643 # Checks ONOS state in link up
644 if linkUpResult and topoResult and iperfResult and intentResult:
645 main.log.info( itemName + ": Successfully brought link back up" )
646 else:
647 main.log.error( itemName + ": Failed to bring link back up" )
648
649 # Remove all intents
650 removeIntentResult = removeAllIntents( main, intentsId )
acsmarsd4862d12015-10-06 17:57:34 -0700651 if removeIntentResult:
652 main.assertReturnString += 'Remove Intents Passed'
653 else:
654 main.assertReturnString += 'Remove Intents Failed'
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700655
656 stepResult = iperfResult and linkDownResult and linkUpResult \
657 and intentResult and removeIntentResult
658
659 return stepResult
660
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800661def installSingleToMultiIntent( main,
662 name,
663 senders,
664 recipients,
665 onosNode=0,
666 ethType="",
667 bandwidth="",
668 lambdaAlloc=False,
669 ipProto="",
670 ipAddresses="",
671 tcp="",
672 sw1="",
673 sw2=""):
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700674 """
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800675 Installs a Single to Multi Point Intent
676
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700677 Description:
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800678 Install a single to multi point intent using
679 add-single-to-multi-intent
680
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700681 Steps:
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800682 - Fetch host data if not given
683 - Add single to multi intent
684 - Ingress device is the first sender host
685 - Egress devices are the recipient devices
686 - Ports if defined in senders or recipients
687 - MAC address ethSrc loaded from Ingress device
688 - Check intent state with retry
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700689 Required:
690 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800691 senders - List of host dictionaries i.e.
692 { "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" }
693 recipients - List of host dictionaries i.e.
694 { "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" }
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700695 Optional:
696 onosNode - ONOS node to install the intents in main.CLIs[ ]
697 0 by default so that it will always use the first
698 ONOS node
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700699 ethType - Ethernet type eg. IPV4, IPV6
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700700 bandwidth - Bandwidth capacity
701 lambdaAlloc - Allocate lambda, defaults to False
702 ipProto - IP protocol
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700703 tcp - TCP ports in the same order as the hosts in hostNames
704 sw1 - First switch to bring down & up for rerouting purpose
705 sw2 - Second switch to bring down & up for rerouting purpose
706 expectedLink - Expected link when the switches are down, it should
707 be two links lower than the links before the two
708 switches are down
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700709 """
710
711 assert main, "There is no main variable"
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800712 assert senders, "You must specify a sender"
713 assert recipients, "You must specify a recipient"
714 # Assert devices or main.hostsData, "You must specify devices"
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700715
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800716 global itemName # The name of this run. Used for logs.
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700717 itemName = name
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700718 onosNode = int( onosNode )
719
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700720 main.log.info( itemName + ": Adding single point to multi point intents" )
721
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800722 for sender in senders:
723 if not sender.get( "device" ):
724 main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
725 sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700726
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800727 for recipient in recipients:
728 if not recipient.get( "device" ):
729 main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
730 recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700731
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700732
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800733 ingressDevice = senders[ 0 ].get( "device" )
734 egressDeviceList = [ x.get( "device" ) for x in recipients if x.get( "device" ) ]
735
736 portIngress = senders[ 0 ].get( "port", "" )
737 portEgressList = [ x.get( "port" ) for x in recipients if x.get( "port" ) ]
738 if not portEgressList:
739 portEgressList = None
740
741 srcMac = senders[ 0 ].get( "mac" )
742
743 # Adding point intent
744 intentId = main.CLIs[ onosNode ].addSinglepointToMultipointIntent(
745 ingressDevice=ingressDevice,
746 egressDeviceList=egressDeviceList,
747 portIngress=portIngress,
748 portEgressList=portEgressList,
749 ethType=ethType,
750 ethSrc=srcMac,
751 bandwidth=bandwidth,
752 lambdaAlloc=lambdaAlloc,
753 ipProto=ipProto,
754 ipSrc="",
755 ipDst="",
756 tcpSrc="",
757 tcpDst="" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700758
759 # Check intents state
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800760 if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
761 return intentId
acsmarsd4862d12015-10-06 17:57:34 -0700762 else:
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800763 main.log.error( "Single to Multi Intent did not install correctly" )
764 return main.FALSE
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700765
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800766def installMultiToSingleIntent( main,
767 name,
768 senders,
769 recipients,
770 onosNode=0,
771 ethType="",
772 bandwidth="",
773 lambdaAlloc=False,
774 ipProto="",
775 ipAddresses="",
776 tcp="",
777 sw1="",
778 sw2=""):
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700779 """
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800780 Installs a Multi to Single Point Intent
781
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700782 Description:
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800783 Install a multi to single point intent using
784 add-multi-to-single-intent
785
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700786 Steps:
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800787 - Fetch host data if not given
788 - Add multi to single intent
789 - Ingress devices are the senders devices
790 - Egress device is the first recipient host
791 - Ports if defined in senders or recipients
792 - MAC address ethSrc loaded from Ingress device
793 - Check intent state with retry
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700794 Required:
795 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800796 senders - List of host dictionaries i.e.
797 [ { "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" } ]
798 recipients - List of host dictionaries i.e.
799 [ { "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" } ]
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700800 Optional:
801 onosNode - ONOS node to install the intents in main.CLIs[ ]
802 0 by default so that it will always use the first
803 ONOS node
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700804 ethType - Ethernet type eg. IPV4, IPV6
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700805 bandwidth - Bandwidth capacity
806 lambdaAlloc - Allocate lambda, defaults to False
807 ipProto - IP protocol
kelvin-onlab58dc39e2015-08-06 08:11:09 -0700808 tcp - TCP ports in the same order as the hosts in hostNames
809 sw1 - First switch to bring down & up for rerouting purpose
810 sw2 - Second switch to bring down & up for rerouting purpose
811 expectedLink - Expected link when the switches are down, it should
812 be two links lower than the links before the two
813 switches are down
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700814 """
815
816 assert main, "There is no main variable"
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800817 assert senders, "You must specify a sender"
818 assert recipients, "You must specify a recipient"
819 # Assert devices or main.hostsData, "You must specify devices"
820
821 global itemName # The name of this run. Used for logs.
822 itemName = name
823 onosNode = int( onosNode )
824
825 main.log.info( itemName + ": Adding mutli to single point intents" )
826
827 for sender in senders:
828 if not sender.get( "device" ):
829 main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
830 sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
831
832 for recipient in recipients:
833 if not recipient.get( "device" ):
834 main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
835 recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
836
837
838 ingressDeviceList = [ x.get( "device" ) for x in senders if x.get( "device" ) ]
839 egressDevice = recipients[ 0 ].get( "device" )
840
841 portIngressList = [ x.get( "port" ) for x in senders if x.get( "port" ) ]
842 portEgress = recipients[ 0 ].get( "port", "" )
843 if not portIngressList:
844 portIngressList = None
845
846 dstMac = recipients[ 0 ].get( "mac" )
847
848 # Adding point intent
849 intentId = main.CLIs[ onosNode ].addMultipointToSinglepointIntent(
850 ingressDeviceList=ingressDeviceList,
851 egressDevice=egressDevice,
852 portIngressList=portIngressList,
853 portEgress=portEgress,
854 ethType=ethType,
855 ethDst=dstMac,
856 bandwidth=bandwidth,
857 lambdaAlloc=lambdaAlloc,
858 ipProto=ipProto,
859 ipSrc="",
860 ipDst="",
861 tcpSrc="",
862 tcpDst="" )
863
864 # Check intents state
865 if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
866 return intentId
867 else:
868 main.log.error( "Multi to Single Intent did not install correctly" )
869 return main.FALSE
870
871def testPointIntent( main,
872 name,
873 intentId,
874 senders,
875 recipients,
876 badSenders={},
877 badRecipients={},
878 onosNode=0,
879 ethType="",
880 bandwidth="",
881 lambdaAlloc=False,
882 ipProto="",
883 ipAddresses="",
884 tcp="",
885 sw1="s5",
886 sw2="s2",
887 expectedLink=0):
888 """
889 Test a Point Intent
890
891 Description:
892 Test a point intent
893
894 Steps:
895 - Fetch host data if not given
896 - Check Intent State
897 - Check Flow State
898 - Check Connectivity
899 - Check Lack of Connectivity Between Hosts not in the Intent
900 - Reroute
901 - Take Expected Link Down
902 - Check Intent State
903 - Check Flow State
904 - Check Topology
905 - Check Connectivity
906 - Bring Expected Link Up
907 - Check Intent State
908 - Check Flow State
909 - Check Topology
910 - Check Connectivity
911 - Remove Topology
912
913 Required:
914 name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
915
916 senders - List of host dictionaries i.e.
917 { "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" }
918 recipients - List of host dictionaries i.e.
919 { "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" }
920 Optional:
921 onosNode - ONOS node to install the intents in main.CLIs[ ]
922 0 by default so that it will always use the first
923 ONOS node
924 ethType - Ethernet type eg. IPV4, IPV6
925 bandwidth - Bandwidth capacity
926 lambdaAlloc - Allocate lambda, defaults to False
927 ipProto - IP protocol
928 tcp - TCP ports in the same order as the hosts in hostNames
929 sw1 - First switch to bring down & up for rerouting purpose
930 sw2 - Second switch to bring down & up for rerouting purpose
931 expectedLink - Expected link when the switches are down, it should
932 be two links lower than the links before the two
933 switches are down
934
935 """
936
937 # Parameter Validity Check
938 assert main, "There is no main variable"
939 assert senders, "You must specify a sender"
940 assert recipients, "You must specify a recipient"
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700941
942 global itemName
943 itemName = name
944 tempHostsData = {}
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700945 onosNode = int( onosNode )
946
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800947 main.log.info( itemName + ": Testing Point Intent" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700948
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800949 # Names for scapy
950 senderNames = [ x.get( "name" ) for x in senders ]
951 recipientNames = [ x.get( "name" ) for x in recipients ]
952 badSenderNames = [ x.get( "name" ) for x in badSenders ]
953 badRecipientNames = [ x.get( "name" ) for x in badRecipients ]
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700954
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800955 for sender in senders:
956 if not sender.get( "device" ):
957 main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
958 sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700959
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800960 for recipient in recipients:
961 if not recipient.get( "device" ):
962 main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
963 recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700964
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800965 testResult = main.TRUE
966 main.log.info( itemName + ": Adding single point to multi point intents" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -0700967
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800968 # Check intent state
969 if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
970 main.assertReturnString += 'Initial Intent State Passed\n'
acsmarsd4862d12015-10-06 17:57:34 -0700971 else:
Jeremy Songster1f39bf02016-01-20 17:17:25 -0800972 main.assertReturnString += 'Initial Intent State Failed\n'
973 testResult = main.FALSE
974
975 # Check flows count in each node
976 if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ] ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ] ):
977 main.assertReturnString += 'Initial Flow State Passed\n'
978 else:
979 main.assertReturnString += 'Intial Flow State Failed\n'
980 testResult = main.FALSE
981
982 # Check Connectivity
983 if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames ) ):
984 main.assertReturnString += 'Initial Ping Passed\n'
985 else:
986 main.assertReturnString += 'Initial Ping Failed\n'
987 testResult = main.FALSE
988
989 # Check connections that shouldn't work
990 if badSenderNames:
991 main.log.info( "Checking that packets from incorrect sender do not go through" )
992 if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, badSenderNames, recipientNames ), kwargs={ "expectFailure":True } ):
993 main.assertReturnString += 'Bad Sender Ping Passed\n'
994 else:
995 main.assertReturnString += 'Bad Sender Ping Failed\n'
996 testResult = main.FALSE
997
998 if badRecipientNames:
999 main.log.info( "Checking that packets to incorrect recipients do not go through" )
1000 if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, badRecipientNames ), kwargs={ "expectFailure":True } ):
1001 main.assertReturnString += 'Bad Recipient Ping Passed\n'
1002 else:
1003 main.assertReturnString += 'Bad Recipient Ping Failed\n'
1004 testResult = main.FALSE
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001005
1006 # Test rerouting if these variables exist
1007 if sw1 and sw2 and expectedLink:
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001008 # Take link down
1009 if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "down" ) ):
acsmarsd4862d12015-10-06 17:57:34 -07001010 main.assertReturnString += 'Link Down Passed\n'
1011 else:
1012 main.assertReturnString += 'Link Down Failed\n'
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001013 testResult = main.FALSE
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001014
acsmarsd4862d12015-10-06 17:57:34 -07001015 # Check intent state
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001016 if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
acsmarsd4862d12015-10-06 17:57:34 -07001017 main.assertReturnString += 'Link Down Intent State Passed\n'
1018 else:
1019 main.assertReturnString += 'Link Down Intent State Failed\n'
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001020 testResult = main.FALSE
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001021
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001022 # Check flows count in each node
1023 if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ] ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ] ):
1024 main.assertReturnString += 'Link Down Flow State Passed\n'
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001025 else:
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001026 main.assertReturnString += 'Link Down Flow State Failed\n'
1027 testResult = main.FALSE
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001028
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001029 # Check OnosTopology
1030 if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink ) ):
1031 main.assertReturnString += 'Link Down Topology State Passed\n'
1032 else:
1033 main.assertReturnString += 'Link Down Topology State Failed\n'
1034 testResult = main.FALSE
1035
1036 # Check Connection
1037 if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames ) ):
1038 main.assertReturnString += 'Link Down Pingall Passed\n'
1039 else:
1040 main.assertReturnString += 'Link Down Pingall Failed\n'
1041 testResult = main.FALSE
1042
1043 # Bring link up
1044 if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "up" ) ):
acsmarsd4862d12015-10-06 17:57:34 -07001045 main.assertReturnString += 'Link Up Passed\n'
1046 else:
1047 main.assertReturnString += 'Link Up Failed\n'
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001048 testResult = main.FALSE
acsmarsd4862d12015-10-06 17:57:34 -07001049
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001050 # Wait for reroute
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001051 time.sleep( main.rerouteSleep )
1052
acsmarsd4862d12015-10-06 17:57:34 -07001053 # Check Intents
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001054 if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
acsmarsd4862d12015-10-06 17:57:34 -07001055 main.assertReturnString += 'Link Up Intent State Passed\n'
1056 else:
1057 main.assertReturnString += 'Link Up Intent State Failed\n'
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001058 testResult = main.FALSE
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001059
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001060 # Check flows count in each node
1061 if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ] ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ] ):
1062 main.assertReturnString += 'Link Up Flow State Passed\n'
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001063 else:
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001064 main.assertReturnString += 'Link Up Flow State Failed\n'
1065 testResult = main.FALSE
1066
1067 # Check OnosTopology
1068 if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, main.numLinks ) ):
1069 main.assertReturnString += 'Link Up Topology State Passed\n'
1070 else:
1071 main.assertReturnString += 'Link Up Topology State Failed\n'
1072 testResult = main.FALSE
1073
1074 # Check Connection
1075 if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames ) ):
1076 main.assertReturnString += 'Link Up Scapy Packet Received Passed\n'
1077 else:
1078 main.assertReturnString += 'Link Up Scapy Packet Recieved Failed\n'
1079 testResult = main.FALSE
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001080
1081 # Remove all intents
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001082 if utilities.retry( f=removeAllIntents, retValue=main.FALSE, args=( main, [ intentId ] ) ):
acsmarsd4862d12015-10-06 17:57:34 -07001083 main.assertReturnString += 'Remove Intents Passed'
1084 else:
1085 main.assertReturnString += 'Remove Intents Failed'
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001086 testResult = main.FALSE
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001087
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001088 return testResult
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001089
kelvin-onlab58dc39e2015-08-06 08:11:09 -07001090def pingallHosts( main, hostList ):
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001091 """
1092 Ping all host in the hosts list variable
1093 """
Jon Halla5cb3412015-08-18 14:08:22 -07001094 main.log.info( "Pinging: " + str( hostList ) )
1095 return main.Mininet1.pingallHosts( hostList )
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001096
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001097def fwdPingall( main ):
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001098 """
1099 Use fwd app and pingall to discover all the hosts
1100 """
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001101 activateResult = main.TRUE
1102 appCheck = main.TRUE
1103 getDataResult = main.TRUE
1104 main.log.info( "Activating reactive forwarding app " )
1105 activateResult = main.CLIs[ 0 ].activateApp( "org.onosproject.fwd" )
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001106
1107 # Wait for forward app activation to propagate
kelvin-onlab0ad05d12015-07-23 14:21:15 -07001108 time.sleep( main.fwdSleep )
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001109
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001110 # Check that forwarding is enabled on all nodes
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001111 for i in range( main.numCtrls ):
1112 appCheck = appCheck and main.CLIs[ i ].appToIDCheck()
1113 if appCheck != main.TRUE:
1114 main.log.warn( main.CLIs[ i ].apps() )
1115 main.log.warn( main.CLIs[ i ].appIDs() )
1116
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001117 # Send pingall in mininet
1118 main.log.info( "Run Pingall" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001119 pingResult = main.Mininet1.pingall( timeout = 600 )
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001120
1121 main.log.info( "Deactivating reactive forwarding app " )
1122 deactivateResult = main.CLIs[ 0 ].deactivateApp( "org.onosproject.fwd" )
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001123 if activateResult and deactivateResult:
1124 main.log.info( "Successfully used fwd app to discover hosts" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001125 getDataResult = main.TRUE
1126 else:
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001127 main.log.info( "Failed to use fwd app to discover hosts" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001128 getDataResult = main.FALSE
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001129 return getDataResult
1130
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001131def confirmHostDiscovery( main ):
1132 """
1133 Confirms that all ONOS nodes have discovered all scapy hosts
1134 """
1135 import collections
1136 scapyHostCount = len( main.scapyHosts )
1137 hosts = main.topo.getAllHosts( main ) # Get host data from each ONOS node
1138 hostFails = [] # Reset for each failed attempt
1139
1140 # Check for matching hosts on each node
1141 scapyHostIPs = [ x.hostIp for x in main.scapyHosts if x.hostIp != "0.0.0.0" ]
1142 for controller in range( main.numCtrls ):
1143 controllerStr = str( controller + 1 ) # ONOS node number
1144 # Compare Hosts
1145 # Load hosts data for controller node
1146 if hosts[ controller ] and "Error" not in hosts[ controller ]:
1147 try:
1148 hostData = json.loads( hosts[ controller ] )
1149 except ( TypeError, ValueError ):
1150 main.log.error( "Could not load json:" + str( hosts[ controller ] ) )
1151 hostFails.append( controllerStr )
1152 else:
1153 onosHostIPs = [ x.get( "ipAddresses" )[ 0 ]
1154 for x in hostData
1155 if len( x.get( "ipAddresses" ) ) > 0 ]
1156 if not set( collections.Counter( scapyHostIPs ) ).issubset( set ( collections.Counter( onosHostIPs ) ) ):
1157 main.log.warn( "Controller {0} only sees nodes with {1} IPs. It should see all of the following: {2}".format( controllerStr, onosHostIPs, scapyHostIPs ) )
1158 hostFails.append( controllerStr )
1159 else:
1160 main.log.error( "Hosts returned nothing or an error." )
1161 hostFails.append( controllerStr )
1162
1163 if hostFails:
1164 main.log.error( "List of failed ONOS Nodes:" + ', '.join(map(str, hostFails )) )
1165 return main.FALSE
1166 else:
1167 return main.TRUE
1168
1169def sendDiscoveryArp( main, hosts=None ):
1170 """
1171 Sends Discovery ARP packets from each host provided
1172 Defaults to each host in main.scapyHosts
1173 """
1174 # Send an arp ping from each host
1175 if not hosts:
1176 hosts = main.scapyHosts
1177 for host in hosts:
1178 pkt = 'Ether( src="{0}")/ARP( psrc="{1}")'.format( host.hostMac ,host.hostIp )
1179 # Send from the VLAN interface if there is one so ONOS discovers the VLAN correctly
1180 iface = None
1181 for interface in host.getIfList():
1182 if '.' in interface:
1183 main.log.debug( "Detected VLAN interface {0}. Sending ARP packet from {0}".format( interface ) )
1184 iface = interface
1185 break
1186 host.sendPacket( packet=pkt, iface=iface )
1187 main.log.info( "Sending ARP packet from {0}".format( host.name ) )
1188
1189def populateHostData( main ):
1190 """
1191 Populates hostsData
1192 """
1193 import json
1194 try:
1195 hostsJson = json.loads( main.CLIs[ 0 ].hosts() )
1196 hosts = main.Mininet1.getHosts().keys()
1197 # TODO: Make better use of new getHosts function
1198 for host in hosts:
1199 main.hostsData[ host ] = {}
1200 main.hostsData[ host ][ 'mac' ] = \
1201 main.Mininet1.getMacAddress( host ).upper()
1202 for hostj in hostsJson:
1203 if main.hostsData[ host ][ 'mac' ] == hostj[ 'mac' ]:
1204 main.hostsData[ host ][ 'id' ] = hostj[ 'id' ]
1205 main.hostsData[ host ][ 'vlan' ] = hostj[ 'vlan' ]
1206 main.hostsData[ host ][ 'location' ] = \
1207 hostj[ 'location' ][ 'elementId' ] + '/' + \
1208 hostj[ 'location' ][ 'port' ]
1209 main.hostsData[ host ][ 'ipAddresses' ] = hostj[ 'ipAddresses' ]
1210 return main.TRUE
1211 except KeyError:
1212 main.log.error( "KeyError while populating hostsData")
1213 return main.FALSE
1214
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001215def checkTopology( main, expectedLink ):
1216 statusResult = main.TRUE
1217 # Check onos topology
1218 main.log.info( itemName + ": Checking ONOS topology " )
1219
1220 for i in range( main.numCtrls ):
1221 topologyResult = main.CLIs[ i ].topology()
1222 statusResult = main.ONOSbench.checkStatus( topologyResult,
1223 main.numSwitch,
1224 expectedLink )\
1225 and statusResult
1226 if not statusResult:
1227 main.log.error( itemName + ": Topology mismatch" )
1228 else:
1229 main.log.info( itemName + ": Topology match" )
1230 return statusResult
1231
1232def checkIntentState( main, intentsId ):
1233 """
1234 This function will check intent state to make sure all the intents
1235 are in INSTALLED state
1236 """
1237
1238 intentResult = main.TRUE
1239 results = []
1240
1241 main.log.info( itemName + ": Checking intents state" )
1242 # First check of intents
1243 for i in range( main.numCtrls ):
1244 tempResult = main.CLIs[ i ].checkIntentState( intentsId=intentsId )
1245 results.append( tempResult )
1246
1247 expectedState = [ 'INSTALLED', 'INSTALLING' ]
1248
1249 if all( result == main.TRUE for result in results ):
1250 main.log.info( itemName + ": Intents are installed correctly" )
1251 else:
1252 # Wait for at least 5 second before checking the intents again
acsmarsb9a92692015-10-08 16:43:01 -07001253 main.log.error( "Intents are not installed correctly. Waiting 5 sec" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001254 time.sleep( 5 )
1255 results = []
1256 # Second check of intents since some of the intents may be in
1257 # INSTALLING state, they should be in INSTALLED at this time
1258 for i in range( main.numCtrls ):
1259 tempResult = main.CLIs[ i ].checkIntentState(
1260 intentsId=intentsId )
1261 results.append( tempResult )
1262 if all( result == main.TRUE for result in results ):
1263 main.log.info( itemName + ": Intents are installed correctly" )
acsmarsb9a92692015-10-08 16:43:01 -07001264 intentResult = main.TRUE
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001265 else:
1266 main.log.error( itemName + ": Intents are NOT installed correctly" )
1267 intentResult = main.FALSE
1268
1269 return intentResult
1270
1271def checkFlowsState( main ):
1272
1273 main.log.info( itemName + ": Check flows state" )
1274 checkFlowsResult = main.CLIs[ 0 ].checkFlowsState()
1275 return checkFlowsResult
1276
1277def link( main, sw1, sw2, option):
1278
1279 # link down
1280 main.log.info( itemName + ": Bring link " + option + "between " +
1281 sw1 + " and " + sw2 )
1282 linkResult = main.Mininet1.link( end1=sw1, end2=sw2, option=option )
1283 return linkResult
1284
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001285def scapyCheckConnection( main, senders, recipients, packet=None, packetFilter=None, expectFailure=False ):
1286 """
1287 Checks the connectivity between all given sender hosts and all given recipient hosts
1288 Packet may be specified. Defaults to Ether/IP packet
1289 Packet Filter may be specified. Defaults to Ether/IP from current sender MAC
1290 Todo: Optional packet and packet filter attributes for sender and recipients
1291 Expect Failure when the sender and recipient are not supposed to have connectivity
1292 Timeout of 1 second, returns main.TRUE if the filter is not triggered and kills the filter
1293
1294 """
1295 connectionsFunctional = main.TRUE
1296
1297 if not packetFilter:
1298 packetFilter = 'ether host {}'
1299
1300 if expectFailure:
1301 timeout = 1
1302 else:
1303 timeout = 10
1304
1305 for sender in senders:
1306 try:
1307 senderComp = getattr( main, sender )
1308 except AttributeError:
1309 main.log.error( "main has no attribute {}".format( sender ) )
1310 connectionsFunctional = main.FALSE
1311 continue
1312
1313 for recipient in recipients:
1314 # Do not send packets to self since recipient CLI will already be busy
1315 if recipient == sender:
1316 continue
1317 try:
1318 recipientComp = getattr( main, recipient )
1319 except AttributeError:
1320 main.log.error( "main has no attribute {}".format( recipient ) )
1321 connectionsFunctional = main.FALSE
1322 continue
1323
1324 recipientComp.startFilter( pktFilter = packetFilter.format( senderComp.hostMac ) )
1325
1326 if not packet:
1327 pkt = 'Ether( src="{0}", dst="{2}" )/IP( src="{1}", dst="{3}" )'.format(
1328 senderComp.hostMac,
1329 senderComp.hostIp,
1330 recipientComp.hostMac,
1331 recipientComp.hostIp )
1332 else:
1333 pkt = packet
1334 senderComp.sendPacket( packet = pkt )
1335
1336 if recipientComp.checkFilter( timeout ):
1337 if expectFailure:
1338 main.log.error( "Packet from {0} successfully received by {1} when it should not have been".format( sender , recipient ) )
1339 connectionsFunctional = main.FALSE
1340 else:
1341 main.log.info( "Packet from {0} successfully received by {1}".format( sender , recipient ) )
1342 else:
1343 recipientComp.killFilter()
1344 if expectFailure:
1345 main.log.info( "As expected, packet from {0} was not received by {1}".format( sender , recipient ) )
1346 else:
1347 main.log.error( "Packet from {0} was not received by {1}".format( sender , recipient ) )
1348 connectionsFunctional = main.FALSE
1349
1350 return connectionsFunctional
1351
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001352def removeAllIntents( main, intentsId ):
1353 """
1354 Remove all intents in the intentsId
1355 """
1356
kelvin-onlab5c706ff2015-07-20 10:56:52 -07001357 onosSummary = []
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001358 removeIntentResult = main.TRUE
1359 # Remove intents
1360 for intent in intentsId:
1361 main.CLIs[ 0 ].removeIntent( intentId=intent, purge=True )
1362
acsmarscfa52272015-08-06 15:21:45 -07001363 time.sleep( main.removeIntentSleep )
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001364
kelvin-onlab5c706ff2015-07-20 10:56:52 -07001365 # If there is remianing intents then remove intents should fail
1366 for i in range( main.numCtrls ):
1367 onosSummary.append( json.loads( main.CLIs[ i ].summary() ) )
1368
1369 for summary in onosSummary:
1370 if summary.get( 'intents' ) != 0:
1371 main.log.warn( itemName + ": There are " +
1372 str( summary.get( 'intents' ) ) +
1373 " intents remaining in node " +
1374 str( summary.get( 'node' ) ) +
1375 ", failed to remove all the intents " )
1376 removeIntentResult = main.FALSE
1377
1378 if removeIntentResult:
1379 main.log.info( itemName + ": There are no more intents remaining, " +
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001380 "successfully removed all the intents." )
kelvin-onlab5c706ff2015-07-20 10:56:52 -07001381
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001382 return removeIntentResult
1383
1384def checkFlowsCount( main ):
1385 """
1386 Check flows count in each node
1387 """
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001388 flowsCount = []
1389 main.log.info( itemName + ": Checking flows count in each ONOS node" )
1390 for i in range( main.numCtrls ):
1391 summaryResult = main.CLIs[ i ].summary()
1392 if not summaryResult:
1393 main.log.error( itemName + ": There is something wrong with " +
1394 "summary command" )
1395 return main.FALSE
1396 else:
1397 summaryJson = json.loads( summaryResult )
1398 flowsCount.append( summaryJson.get( 'flows' ) )
1399
1400 if flowsCount:
1401 if all( flows==flowsCount[ 0 ] for flows in flowsCount ):
1402 main.log.info( itemName + ": There are " + str( flowsCount[ 0 ] ) +
1403 " flows in all ONOS node" )
1404 else:
1405 for i in range( main.numCtrls ):
1406 main.log.debug( itemName + ": ONOS node " + str( i ) + " has " +
kelvin-onlab6dea6e62015-07-23 13:07:26 -07001407 str( flowsCount[ i ] ) + " flows" )
kelvin-onlabd48a68c2015-07-13 16:01:36 -07001408 else:
1409 main.log.error( "Checking flows count failed, check summary command" )
1410 return main.FALSE
1411
1412 return main.TRUE
1413
kelvin-onlab58dc39e2015-08-06 08:11:09 -07001414def checkLeaderChange( leaders1, leaders2 ):
acsmarse6b410f2015-07-17 14:39:34 -07001415 """
1416 Checks for a change in intent partition leadership.
1417
1418 Takes the output of leaders -c in json string format before and after
1419 a potential change as input
1420
1421 Returns main.TRUE if no mismatches are detected
1422 Returns main.FALSE if there is a mismatch or on error loading the input
1423 """
1424 try:
1425 leaders1 = json.loads( leaders1 )
1426 leaders2 = json.loads( leaders2 )
1427 except ( AttributeError, TypeError):
1428 main.log.exception( self.name + ": Object not as expected" )
1429 return main.FALSE
1430 except Exception:
1431 main.log.exception( self.name + ": Uncaught exception!" )
1432 main.cleanup()
1433 main.exit()
1434 main.log.info( "Checking Intent Paritions for Change in Leadership" )
1435 mismatch = False
1436 for dict1 in leaders1:
1437 if "intent" in dict1.get( "topic", [] ):
1438 for dict2 in leaders2:
1439 if dict1.get( "topic", 0 ) == dict2.get( "topic", 0 ) and \
1440 dict1.get( "leader", 0 ) != dict2.get( "leader", 0 ):
1441 mismatch = True
1442 main.log.error( "{0} changed leader from {1} to {2}".\
1443 format( dict1.get( "topic", "no-topic" ),\
1444 dict1.get( "leader", "no-leader" ),\
1445 dict2.get( "leader", "no-leader" ) ) )
1446 if mismatch:
1447 return main.FALSE
1448 else:
1449 return main.TRUE
kelvin-onlab016dce22015-08-10 09:54:11 -07001450
1451def report( main ):
1452 """
Jeremy Songster1f39bf02016-01-20 17:17:25 -08001453 Report errors/warnings/exceptions
kelvin-onlab016dce22015-08-10 09:54:11 -07001454 """
kelvin-onlab016dce22015-08-10 09:54:11 -07001455 main.ONOSbench.logReport( main.ONOSip[ 0 ],
1456 [ "INFO",
1457 "FOLLOWER",
1458 "WARN",
1459 "flow",
1460 "ERROR",
1461 "Except" ],
1462 "s" )
1463
1464 main.log.info( "ERROR report: \n" )
1465 for i in range( main.numCtrls ):
1466 main.ONOSbench.logReport( main.ONOSip[ i ],
1467 [ "ERROR" ],
1468 "d" )
1469
1470 main.log.info( "EXCEPTIONS report: \n" )
1471 for i in range( main.numCtrls ):
1472 main.ONOSbench.logReport( main.ONOSip[ i ],
1473 [ "Except" ],
1474 "d" )
1475
1476 main.log.info( "WARNING report: \n" )
1477 for i in range( main.numCtrls ):
1478 main.ONOSbench.logReport( main.ONOSip[ i ],
1479 [ "WARN" ],
1480 "d" )