blob: 0e563be176ae111f1516ce6646e047a4744ffcc2 [file] [log] [blame]
"""
Wrapper functions for FuncIntent
This functions include Onosclidriver and Mininetclidriver driver functions
Author: kelvin@onlab.us
"""
import time
import copy
import json
def __init__( self ):
self.default = ''
def installHostIntent( main,
name,
host1,
host2,
onosNode=0,
ethType="",
bandwidth="",
lambdaAlloc=False,
ipProto="",
ipAddresses="",
tcp="",
sw1="",
sw2="",
setVlan="",
encap="" ):
"""
Installs a Host Intent
Description:
Install a host intent using
add-host-intent
Steps:
- Fetch host data if not given
- Add host intent
- Ingress device is the first sender host
- Egress devices are the recipient devices
- Ports if defined in senders or recipients
- MAC address ethSrc loaded from Ingress device
- Check intent state with retry
Required:
name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
host1 - Dictionary for host1
{ "name":"h8", "id":"of:0000000000000005/8" }
host2 - Dictionary for host2
{ "name":"h16", "id":"of:0000000000000006/8" }
Optional:
onosNode - ONOS node to install the intents in main.CLIs[ ]
0 by default so that it will always use the first
ONOS node
ethType - Ethernet type eg. IPV4, IPV6
bandwidth - Bandwidth capacity
lambdaAlloc - Allocate lambda, defaults to False
ipProto - IP protocol
tcp - TCP ports in the same order as the hosts in hostNames
"""
assert main, "There is no main variable"
assert host1, "You must specify host1"
assert host2, "You must specify host2"
global itemName # The name of this run. Used for logs.
itemName = name
onosNode = int( onosNode )
main.log.info( itemName + ": Adding single point to multi point intents" )
try:
if not host1.get( "id" ):
main.log.warn( "ID not given for host1 {0}. Loading from main.hostData".format( host1.get( "name" ) ) )
main.log.debug( main.hostsData.get( host1.get( "name" ) ) )
host1[ "id" ] = main.hostsData.get( host1.get( "name" ) ).get( "id" )
if not host2.get( "id" ):
main.log.warn( "ID not given for host2 {0}. Loading from main.hostData".format( host2.get( "name" ) ) )
host2[ "id" ] = main.hostsData.get( host2.get( "name" ) ).get( "id" )
# Adding point intent
vlanId = host1.get( "vlan" )
intentId = main.CLIs[ onosNode ].addHostIntent( hostIdOne=host1.get( "id" ),
hostIdTwo=host2.get( "id" ),
vlanId=vlanId,
setVlan=setVlan,
encap=encap )
except( KeyError, TypeError ):
errorMsg = "There was a problem loading the hosts data."
if intentId:
errorMsg += " There was a problem installing host to host intent."
main.log.error( errorMsg )
return main.FALSE
# Check intents state
if utilities.retry( f=checkIntentState, retValue=main.FALSE,
args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Install Intent State Passed\n'
if flowDuration( main ):
main.assertReturnString += 'Flow duration check Passed\n'
return intentId
else:
main.assertReturnString += 'Flow duration check failed\n'
return main.FALSE
else:
main.log.error( "Host Intent did not install correctly" )
main.assertReturnString += 'Install Intent State Failed\n'
return main.FALSE
def testHostIntent( main,
name,
intentId,
host1,
host2,
onosNode=0,
sw1="s5",
sw2="s2",
expectedLink=0 ):
"""
Test a Host Intent
Description:
Test a host intent of given ID between given hosts
Steps:
- Fetch host data if not given
- Check Intent State
- Check Flow State
- Check Connectivity
- Check Lack of Connectivity Between Hosts not in the Intent
- Reroute
- Take Expected Link Down
- Check Intent State
- Check Flow State
- Check Topology
- Check Connectivity
- Bring Expected Link Up
- Check Intent State
- Check Flow State
- Check Topology
- Check Connectivity
- Remove Topology
Required:
name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
intentId - intent ID to be tested ( and removed )
host1 - Dictionary for host1
{ "name":"h8", "id":"of:0000000000000005/8" }
host2 - Dictionary for host2
{ "name":"h16", "id":"of:0000000000000006/8" }
Optional:
onosNode - ONOS node to install the intents in main.CLIs[ ]
0 by default so that it will always use the first
ONOS node
sw1 - First switch to bring down & up for rerouting purpose
sw2 - Second switch to bring down & up for rerouting purpose
expectedLink - Expected link when the switches are down, it should
be two links lower than the links before the two
switches are down
"""
# Parameter Validity Check
assert main, "There is no main variable"
assert host1, "You must specify host1"
assert host2, "You must specify host2"
global itemName
itemName = name
tempHostsData = {}
onosNode = int( onosNode )
main.log.info( itemName + ": Testing Host Intent" )
try:
if not host1.get( "id" ):
main.log.warn( "Id not given for host1 {0}. Loading from main.hostData".format( host1.get( "name" ) ) )
host1[ "id" ] = main.hostsData.get( host1.get( "name" ) ).get( "location" )
if not host2.get( "id" ):
main.log.warn( "Id not given for host2 {0}. Loading from main.hostData".format( host2.get( "name" ) ) )
host2[ "id" ] = main.hostsData.get( host2.get( "name" ) ).get( "location" )
senderNames = [ host1.get( "name" ), host2.get( "name" ) ]
recipientNames = [ host1.get( "name" ), host2.get( "name" ) ]
vlanId = host1.get( "vlan" )
testResult = main.TRUE
except( KeyError, TypeError ):
main.log.error( "There was a problem loading the hosts data." )
return main.FALSE
main.log.info( itemName + ": Testing Host to Host intents" )
# Check intent state
if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Initial Intent State Passed\n'
else:
main.assertReturnString += 'Initial Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
main.assertReturnString += 'Initial Flow State Passed\n'
else:
main.assertReturnString += 'Intial Flow State Failed\n'
testResult = main.FALSE
# Check Connectivity
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId ) ):
main.assertReturnString += 'Initial Ping Passed\n'
else:
main.assertReturnString += 'Initial Ping Failed\n'
testResult = main.FALSE
# Test rerouting if these variables exist
if sw1 and sw2 and expectedLink:
# Take link down
if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "down" ) ):
main.assertReturnString += 'Link Down Passed\n'
else:
main.assertReturnString += 'Link Down Failed\n'
testResult = main.FALSE
# Check intent state
if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Link Down Intent State Passed\n'
else:
main.assertReturnString += 'Link Down Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
main.assertReturnString += 'Link Down Flow State Passed\n'
else:
main.assertReturnString += 'Link Down Flow State Failed\n'
testResult = main.FALSE
# Check OnosTopology
if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink ) ):
main.assertReturnString += 'Link Down Topology State Passed\n'
else:
main.assertReturnString += 'Link Down Topology State Failed\n'
testResult = main.FALSE
# Check Connection
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId ) ):
main.assertReturnString += 'Link Down Pingall Passed\n'
else:
main.assertReturnString += 'Link Down Pingall Failed\n'
testResult = main.FALSE
# Bring link up
if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "up" ) ):
main.assertReturnString += 'Link Up Passed\n'
else:
main.assertReturnString += 'Link Up Failed\n'
testResult = main.FALSE
# Wait for reroute
time.sleep( main.rerouteSleep )
# Check Intents
if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Link Up Intent State Passed\n'
else:
main.assertReturnString += 'Link Up Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
main.assertReturnString += 'Link Up Flow State Passed\n'
else:
main.assertReturnString += 'Link Up Flow State Failed\n'
testResult = main.FALSE
# Check OnosTopology
if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, main.numLinks ) ):
main.assertReturnString += 'Link Up Topology State Passed\n'
else:
main.assertReturnString += 'Link Up Topology State Failed\n'
testResult = main.FALSE
# Check Connection
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId ) ):
main.assertReturnString += 'Link Up Pingall Passed\n'
else:
main.assertReturnString += 'Link Up Pingall Failed\n'
testResult = main.FALSE
# Remove all intents
if utilities.retry( f=removeAllIntents, retValue=main.FALSE, args=( main, [ intentId ] ) ):
main.assertReturnString += 'Remove Intents Passed'
else:
main.assertReturnString += 'Remove Intents Failed'
testResult = main.FALSE
return testResult
def installPointIntent( main,
name,
senders,
recipients,
onosNode=0,
ethType="",
bandwidth="",
lambdaAlloc=False,
ipProto="",
ipSrc="",
ipDst="",
tcpSrc="",
tcpDst="",
setVlan="",
encap="" ):
"""
Installs a Single to Single Point Intent
Description:
Install a single to single point intent
Steps:
- Fetch host data if not given
- Add point intent
- Ingress device is the first sender device
- Egress device is the first recipient device
- Ports if defined in senders or recipients
- MAC address ethSrc loaded from Ingress device
- Check intent state with retry
Required:
name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
senders - List of host dictionaries i.e.
[ { "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" } ]
recipients - List of host dictionaries i.e.
[ { "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" } ]
Optional:
onosNode - ONOS node to install the intents in main.CLIs[ ]
0 by default so that it will always use the first
ONOS node
ethType - Ethernet type eg. IPV4, IPV6
bandwidth - Bandwidth capacity
lambdaAlloc - Allocate lambda, defaults to False
ipProto - IP protocol
tcp - TCP ports in the same order as the hosts in hostNames
sw1 - First switch to bring down & up for rerouting purpose
sw2 - Second switch to bring down & up for rerouting purpose
expectedLink - Expected link when the switches are down, it should
be two links lower than the links before the two
switches are down
"""
assert main, "There is no main variable"
assert senders, "You must specify a sender"
assert recipients, "You must specify a recipient"
# Assert devices or main.hostsData, "You must specify devices"
global itemName # The name of this run. Used for logs.
itemName = name
onosNode = int( onosNode )
main.log.info( itemName + ": Adding point to point intents" )
try:
for sender in senders:
if not sender.get( "device" ):
main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
for recipient in recipients:
if not recipient.get( "device" ):
main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
ingressDevice = senders[ 0 ].get( "device" )
egressDevice = recipients[ 0 ].get( "device" )
portIngress = senders[ 0 ].get( "port", "" )
portEgress = recipients[ 0 ].get( "port", "" )
dstMac = recipients[ 0 ].get( "mac" )
ipSrc = senders[ 0 ].get( "ip" )
ipDst = recipients[ 0 ].get( "ip" )
vlanId = senders[ 0 ].get( "vlan" )
# Adding point intent
intentId = main.CLIs[ onosNode ].addPointIntent(
ingressDevice=ingressDevice,
egressDevice=egressDevice,
portIngress=portIngress,
portEgress=portEgress,
ethType=ethType,
ethDst=dstMac,
bandwidth=bandwidth,
lambdaAlloc=lambdaAlloc,
ipProto=ipProto,
ipSrc=ipSrc,
ipDst=ipDst,
tcpSrc=tcpSrc,
tcpDst=tcpDst,
vlanId=vlanId,
setVlan=setVlan,
encap=encap )
except( KeyError, TypeError ):
errorMsg = "There was a problem loading the hosts data."
if intentId:
errorMsg += " There was a problem installing Point to Point intent."
main.log.error( errorMsg )
return main.FALSE
# Check intents state
if utilities.retry( f=checkIntentState, retValue=main.FALSE,
args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Install Intent State Passed\n'
if flowDuration( main ):
main.assertReturnString += 'Flow duration check Passed\n'
return intentId
else:
main.assertReturnString += 'Flow duration check failed\n'
return main.FALSE
else:
main.log.error( "Point Intent did not install correctly" )
return main.FALSE
def pointIntentTcp( main,
name,
host1,
host2,
onosNode=0,
deviceId1="",
deviceId2="",
port1="",
port2="",
ethType="",
mac1="",
mac2="",
bandwidth="",
lambdaAlloc=False,
ipProto="",
ip1="",
ip2="",
tcp1="",
tcp2="",
sw1="",
sw2="",
expectedLink=0 ):
"""
Description:
Verify add-point-intent only for TCP
Steps:
- Get device ids | ports
- Add point intents
- Check intents
- Verify flows
- Ping hosts
- Reroute
- Link down
- Verify flows
- Check topology
- Ping hosts
- Link up
- Verify flows
- Check topology
- Ping hosts
- Remove intents
Required:
name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
host1 - Name of first host
host2 - Name of second host
Optional:
onosNode - ONOS node to install the intents in main.CLIs[ ]
0 by default so that it will always use the first
ONOS node
deviceId1 - ONOS device id of the first switch, the same as the
location of the first host eg. of:0000000000000001/1,
located at device 1 port 1
deviceId2 - ONOS device id of the second switch
port1 - The port number where the first host is attached
port2 - The port number where the second host is attached
ethType - Ethernet type eg. IPV4, IPV6
mac1 - Mac address of first host
mac2 - Mac address of the second host
bandwidth - Bandwidth capacity
lambdaAlloc - Allocate lambda, defaults to False
ipProto - IP protocol
ip1 - IP address of first host
ip2 - IP address of second host
tcp1 - TCP port of first host
tcp2 - TCP port of second host
sw1 - First switch to bring down & up for rerouting purpose
sw2 - Second switch to bring down & up for rerouting purpose
expectedLink - Expected link when the switches are down, it should
be two links lower than the links before the two
switches are down
"""
assert main, "There is no main variable"
assert name, "variable name is empty"
assert host1 and host2, "You must specify hosts"
global itemName
itemName = name
host1 = host1
host2 = host2
hostNames = [ host1, host2 ]
intentsId = []
iperfResult = main.TRUE
intentResult = main.TRUE
removeIntentResult = main.TRUE
flowResult = main.TRUE
topoResult = main.TRUE
linkDownResult = main.TRUE
linkUpResult = main.TRUE
onosNode = int( onosNode )
# Adding bidirectional point intents
main.log.info( itemName + ": Adding point intents" )
intent1 = main.CLIs[ onosNode ].addPointIntent( ingressDevice=deviceId1,
egressDevice=deviceId2,
portIngress=port1,
portEgress=port2,
ethType=ethType,
ethSrc=mac1,
ethDst=mac2,
bandwidth=bandwidth,
lambdaAlloc=lambdaAlloc,
ipProto=ipProto,
ipSrc=ip1,
ipDst=ip2,
tcpSrc=tcp1,
tcpDst="" )
intent2 = main.CLIs[ onosNode ].addPointIntent( ingressDevice=deviceId2,
egressDevice=deviceId1,
portIngress=port2,
portEgress=port1,
ethType=ethType,
ethSrc=mac2,
ethDst=mac1,
bandwidth=bandwidth,
lambdaAlloc=lambdaAlloc,
ipProto=ipProto,
ipSrc=ip2,
ipDst=ip1,
tcpSrc=tcp2,
tcpDst="" )
intent3 = main.CLIs[ onosNode ].addPointIntent( ingressDevice=deviceId1,
egressDevice=deviceId2,
portIngress=port1,
portEgress=port2,
ethType=ethType,
ethSrc=mac1,
ethDst=mac2,
bandwidth=bandwidth,
lambdaAlloc=lambdaAlloc,
ipProto=ipProto,
ipSrc=ip1,
ipDst=ip2,
tcpSrc="",
tcpDst=tcp2 )
intent4 = main.CLIs[ onosNode ].addPointIntent( ingressDevice=deviceId2,
egressDevice=deviceId1,
portIngress=port2,
portEgress=port1,
ethType=ethType,
ethSrc=mac2,
ethDst=mac1,
bandwidth=bandwidth,
lambdaAlloc=lambdaAlloc,
ipProto=ipProto,
ipSrc=ip2,
ipDst=ip1,
tcpSrc="",
tcpDst=tcp1 )
intentsId.append( intent1 )
intentsId.append( intent2 )
intentsId.append( intent3 )
intentsId.append( intent4 )
# Check intents state
time.sleep( main.checkIntentSleep )
intentResult = checkIntentState( main, intentsId )
# Check flows count in each node
checkFlowsCount( main )
# Check intents state again if first check fails...
if not intentResult:
intentResult = checkIntentState( main, intentsId )
# Check flows count in each node
checkFlowsCount( main )
# Verify flows
checkFlowsState( main )
# Run iperf to both host
iperfTemp = main.Mininet1.iperftcp( host1, host2 ,10 )
iperfResult = iperfResult and iperfTemp
if iperfTemp:
main.assertReturnString += 'Initial Iperf Passed\n'
else:
main.assertReturnString += 'Initial Iperf Failed\n'
# Test rerouting if these variables exist
if sw1 and sw2 and expectedLink:
# link down
linkDownResult = link( main, sw1, sw2, "down" )
if linkDownResult:
main.assertReturnString += 'Link Down Passed\n'
else:
main.assertReturnString += 'Link Down Failed\n'
# Check flows count in each node
checkFlowsCount( main )
# Verify flows
checkFlowsState( main )
# Check OnosTopology
topoResult = checkTopology( main, expectedLink )
if topoResult:
main.assertReturnString += 'Link Down Topology State Passed\n'
else:
main.assertReturnString += 'Link Down Topology State Failed\n'
# Run iperf to both host
iperfTemp = main.Mininet1.iperftcp( host1, host2, 10 )
iperfResult = iperfResult and iperfTemp
if iperfTemp:
main.assertReturnString += 'Link Down Iperf Passed\n'
else:
main.assertReturnString += 'Link Down Iperf Failed\n'
# Check intent state
intentTemp = checkIntentState( main, intentsId )
intentResult = intentResult and intentTemp
if intentTemp:
main.assertReturnString += 'Link Down Intent State Passed\n'
else:
main.assertReturnString += 'Link Down Intent State Failed\n'
# Checks ONOS state in link down
if linkDownResult and topoResult and iperfResult and intentResult:
main.log.info( itemName + ": Successfully brought link down" )
else:
main.log.error( itemName + ": Failed to bring link down" )
# link up
linkUpResult = link( main, sw1, sw2, "up" )
if linkUpTemp:
main.assertReturnString += 'Link Up Passed\n'
else:
main.assertReturnString += 'Link Up Failed\n'
time.sleep( main.rerouteSleep )
# Check flows count in each node
checkFlowsCount( main )
# Verify flows
checkFlowsState( main )
# Check OnosTopology
topoResult = checkTopology( main, main.numLinks )
if topoResult:
main.assertReturnString += 'Link Up Topology State Passed\n'
else:
main.assertReturnString += 'Link Up Topology State Failed\n'
# Run iperf to both host
iperfTemp = main.Mininet1.iperftcp( host1, host2, 10 )
iperfResult = iperfResult and iperfTemp
if iperfTemp:
main.assertReturnString += 'Link Up Iperf Passed\n'
else:
main.assertReturnString += 'Link Up Iperf Failed\n'
# Check intent state
intentTemp = checkIntentState( main, intentsId )
intentResult = intentResult and intentTemp
if intentTemp:
main.assertReturnString += 'Link Down Intent State Passed\n'
else:
main.assertReturnString += 'Link Down Intent State Failed\n'
# Checks ONOS state in link up
if linkUpResult and topoResult and iperfResult and intentResult:
main.log.info( itemName + ": Successfully brought link back up" )
else:
main.log.error( itemName + ": Failed to bring link back up" )
# Remove all intents
removeIntentResult = removeAllIntents( main, intentsId )
if removeIntentResult:
main.assertReturnString += 'Remove Intents Passed'
else:
main.assertReturnString += 'Remove Intents Failed'
stepResult = iperfResult and linkDownResult and linkUpResult \
and intentResult and removeIntentResult
return stepResult
def installSingleToMultiIntent( main,
name,
senders,
recipients,
onosNode=0,
ethType="",
bandwidth="",
lambdaAlloc=False,
ipProto="",
ipAddresses="",
tcp="",
sw1="",
sw2="",
setVlan="",
partial=False,
encap="" ):
"""
Installs a Single to Multi Point Intent
Description:
Install a single to multi point intent using
add-single-to-multi-intent
Steps:
- Fetch host data if not given
- Add single to multi intent
- Ingress device is the first sender host
- Egress devices are the recipient devices
- Ports if defined in senders or recipients
- MAC address ethSrc loaded from Ingress device
- Check intent state with retry
Required:
name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
senders - List of host dictionaries i.e.
{ "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" }
recipients - List of host dictionaries i.e.
{ "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" }
Optional:
onosNode - ONOS node to install the intents in main.CLIs[ ]
0 by default so that it will always use the first
ONOS node
ethType - Ethernet type eg. IPV4, IPV6
bandwidth - Bandwidth capacity
lambdaAlloc - Allocate lambda, defaults to False
ipProto - IP protocol
tcp - TCP ports in the same order as the hosts in hostNames
sw1 - First switch to bring down & up for rerouting purpose
sw2 - Second switch to bring down & up for rerouting purpose
expectedLink - Expected link when the switches are down, it should
be two links lower than the links before the two
switches are down
"""
assert main, "There is no main variable"
assert senders, "You must specify a sender"
assert recipients, "You must specify a recipient"
# Assert devices or main.hostsData, "You must specify devices"
global itemName # The name of this run. Used for logs.
itemName = name
onosNode = int( onosNode )
main.log.info( itemName + ": Adding single point to multi point intents" )
try:
for sender in senders:
if not sender.get( "device" ):
main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
for recipient in recipients:
if not recipient.get( "device" ):
main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
ingressDevice = senders[ 0 ].get( "device" )
egressDeviceList = [ x.get( "device" ) for x in recipients if x.get( "device" ) ]
portIngress = senders[ 0 ].get( "port", "" )
portEgressList = [ x.get( "port" ) for x in recipients if x.get( "port" ) ]
if not portEgressList:
portEgressList = None
srcMac = senders[ 0 ].get( "mac" )
vlanId = senders[ 0 ].get( "vlan" )
# Adding point intent
intentId = main.CLIs[ onosNode ].addSinglepointToMultipointIntent(
ingressDevice=ingressDevice,
egressDeviceList=egressDeviceList,
portIngress=portIngress,
portEgressList=portEgressList,
ethType=ethType,
ethSrc=srcMac,
bandwidth=bandwidth,
lambdaAlloc=lambdaAlloc,
ipProto=ipProto,
ipSrc="",
ipDst="",
tcpSrc="",
tcpDst="",
vlanId=vlanId,
setVlan=setVlan,
partial=partial,
encap=encap )
except( KeyError, TypeError ):
errorMsg = "There was a problem loading the hosts data."
if intentId:
errorMsg += " There was a problem installing Singlepoint to Multipoint intent."
main.log.error( errorMsg )
return main.FALSE
# Check intents state
if utilities.retry( f=checkIntentState, retValue=main.FALSE,
args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Install Intent State Passed\n'
if flowDuration( main ):
main.assertReturnString += 'Flow duration check Passed\n'
return intentId
else:
main.assertReturnString += 'Flow duration check failed\n'
return main.FALSE
else:
main.log.error( "Single to Multi Intent did not install correctly" )
return main.FALSE
def installMultiToSingleIntent( main,
name,
senders,
recipients,
onosNode=0,
ethType="",
bandwidth="",
lambdaAlloc=False,
ipProto="",
ipAddresses="",
tcp="",
sw1="",
sw2="",
setVlan="",
partial=False,
encap="" ):
"""
Installs a Multi to Single Point Intent
Description:
Install a multi to single point intent using
add-multi-to-single-intent
Steps:
- Fetch host data if not given
- Add multi to single intent
- Ingress devices are the senders devices
- Egress device is the first recipient host
- Ports if defined in senders or recipients
- MAC address ethSrc loaded from Ingress device
- Check intent state with retry
Required:
name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
senders - List of host dictionaries i.e.
[ { "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" } ]
recipients - List of host dictionaries i.e.
[ { "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" } ]
Optional:
onosNode - ONOS node to install the intents in main.CLIs[ ]
0 by default so that it will always use the first
ONOS node
ethType - Ethernet type eg. IPV4, IPV6
bandwidth - Bandwidth capacity
lambdaAlloc - Allocate lambda, defaults to False
ipProto - IP protocol
tcp - TCP ports in the same order as the hosts in hostNames
sw1 - First switch to bring down & up for rerouting purpose
sw2 - Second switch to bring down & up for rerouting purpose
expectedLink - Expected link when the switches are down, it should
be two links lower than the links before the two
switches are down
"""
assert main, "There is no main variable"
assert senders, "You must specify a sender"
assert recipients, "You must specify a recipient"
# Assert devices or main.hostsData, "You must specify devices"
global itemName # The name of this run. Used for logs.
itemName = name
onosNode = int( onosNode )
main.log.info( itemName + ": Adding mutli to single point intents" )
try:
for sender in senders:
if not sender.get( "device" ):
main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
for recipient in recipients:
if not recipient.get( "device" ):
main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
ingressDeviceList = [ x.get( "device" ) for x in senders if x.get( "device" ) ]
egressDevice = recipients[ 0 ].get( "device" )
portIngressList = [ x.get( "port" ) for x in senders if x.get( "port" ) ]
portEgress = recipients[ 0 ].get( "port", "" )
if not portIngressList:
portIngressList = None
dstMac = recipients[ 0 ].get( "mac" )
vlanId = senders[ 0 ].get( "vlan" )
# Adding point intent
intentId = main.CLIs[ onosNode ].addMultipointToSinglepointIntent(
ingressDeviceList=ingressDeviceList,
egressDevice=egressDevice,
portIngressList=portIngressList,
portEgress=portEgress,
ethType=ethType,
ethDst=dstMac,
bandwidth=bandwidth,
lambdaAlloc=lambdaAlloc,
ipProto=ipProto,
ipSrc="",
ipDst="",
tcpSrc="",
tcpDst="",
vlanId=vlanId,
setVlan=setVlan,
partial=partial,
encap=encap )
except( KeyError, TypeError ):
errorMsg = "There was a problem loading the hosts data."
if intentId:
errorMsg += " There was a problem installing Multipoint to Singlepoint intent."
main.log.error( errorMsg )
return main.FALSE
# Check intents state
if utilities.retry( f=checkIntentState, retValue=main.FALSE,
args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Install Intent State Passed\n'
if flowDuration( main ):
main.assertReturnString += 'Flow duration check Passed\n'
return intentId
else:
main.assertReturnString += 'Flow duration check failed\n'
return main.FALSE
else:
main.log.error( "Multi to Single Intent did not install correctly" )
return main.FALSE
def testPointIntent( main,
name,
intentId,
senders,
recipients,
badSenders={},
badRecipients={},
onosNode=0,
ethType="",
bandwidth="",
lambdaAlloc=False,
ipProto="",
ipAddresses="",
tcp="",
sw1="s5",
sw2="s2",
expectedLink=0,
useTCP=False ):
"""
Test a Point Intent
Description:
Test a point intent
Steps:
- Fetch host data if not given
- Check Intent State
- Check Flow State
- Check Connectivity
- Check Lack of Connectivity Between Hosts not in the Intent
- Reroute
- Take Expected Link Down
- Check Intent State
- Check Flow State
- Check Topology
- Check Connectivity
- Bring Expected Link Up
- Check Intent State
- Check Flow State
- Check Topology
- Check Connectivity
- Remove Topology
Required:
name - Type of point intent to add eg. IPV4 | VLAN | Dualstack
senders - List of host dictionaries i.e.
{ "name":"h8", "device":"of:0000000000000005/8","mac":"00:00:00:00:00:08" }
recipients - List of host dictionaries i.e.
{ "name":"h16", "device":"of:0000000000000006/8", "mac":"00:00:00:00:00:10" }
Optional:
onosNode - ONOS node to install the intents in main.CLIs[ ]
0 by default so that it will always use the first
ONOS node
ethType - Ethernet type eg. IPV4, IPV6
bandwidth - Bandwidth capacity
lambdaAlloc - Allocate lambda, defaults to False
ipProto - IP protocol
tcp - TCP ports in the same order as the hosts in hostNames
sw1 - First switch to bring down & up for rerouting purpose
sw2 - Second switch to bring down & up for rerouting purpose
expectedLink - Expected link when the switches are down, it should
be two links lower than the links before the two
switches are down
"""
# Parameter Validity Check
assert main, "There is no main variable"
assert senders, "You must specify a sender"
assert recipients, "You must specify a recipient"
global itemName
itemName = name
tempHostsData = {}
onosNode = int( onosNode )
main.log.info( itemName + ": Testing Point Intent" )
try:
# Names for scapy
senderNames = [ x.get( "name" ) for x in senders ]
recipientNames = [ x.get( "name" ) for x in recipients ]
badSenderNames = [ x.get( "name" ) for x in badSenders ]
badRecipientNames = [ x.get( "name" ) for x in badRecipients ]
for sender in senders:
if not sender.get( "device" ):
main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
for recipient in recipients:
if not recipient.get( "device" ):
main.log.warn( "Device not given for recipient {0}. Loading from main.hostData".format( recipient.get( "name" ) ) )
recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
vlanId = senders[ 0 ].get( "vlan" )
except( KeyError, TypeError ):
main.log.error( "There was a problem loading the hosts data." )
return main.FALSE
testResult = main.TRUE
main.log.info( itemName + ": Adding single point to multi point intents" )
# Check intent state
if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Initial Intent State Passed\n'
else:
main.assertReturnString += 'Initial Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
main.assertReturnString += 'Initial Flow State Passed\n'
else:
main.assertReturnString += 'Intial Flow State Failed\n'
testResult = main.FALSE
# Check Connectivity
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId, useTCP ), attempts=3, sleep=5 ):
main.assertReturnString += 'Initial Ping Passed\n'
else:
main.assertReturnString += 'Initial Ping Failed\n'
testResult = main.FALSE
# Check connections that shouldn't work
if badSenderNames:
main.log.info( "Checking that packets from incorrect sender do not go through" )
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, badSenderNames, recipientNames ), kwargs={ "expectFailure":True } ):
main.assertReturnString += 'Bad Sender Ping Passed\n'
else:
main.assertReturnString += 'Bad Sender Ping Failed\n'
testResult = main.FALSE
if badRecipientNames:
main.log.info( "Checking that packets to incorrect recipients do not go through" )
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, badRecipientNames ), kwargs={ "expectFailure":True } ):
main.assertReturnString += 'Bad Recipient Ping Passed\n'
else:
main.assertReturnString += 'Bad Recipient Ping Failed\n'
testResult = main.FALSE
# Test rerouting if these variables exist
if sw1 and sw2 and expectedLink:
# Take link down
if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "down" ) ):
main.assertReturnString += 'Link Down Passed\n'
else:
main.assertReturnString += 'Link Down Failed\n'
testResult = main.FALSE
# Check intent state
if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Link Down Intent State Passed\n'
else:
main.assertReturnString += 'Link Down Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=5 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=5 ):
main.assertReturnString += 'Link Down Flow State Passed\n'
else:
main.assertReturnString += 'Link Down Flow State Failed\n'
testResult = main.FALSE
# Check OnosTopology
if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink ) ):
main.assertReturnString += 'Link Down Topology State Passed\n'
else:
main.assertReturnString += 'Link Down Topology State Failed\n'
testResult = main.FALSE
# Check Connection
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId, useTCP ) ):
main.assertReturnString += 'Link Down Pingall Passed\n'
else:
main.assertReturnString += 'Link Down Pingall Failed\n'
testResult = main.FALSE
# Bring link up
if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "up" ) ):
main.assertReturnString += 'Link Up Passed\n'
else:
main.assertReturnString += 'Link Up Failed\n'
testResult = main.FALSE
# Wait for reroute
time.sleep( main.rerouteSleep )
# Check Intents
if utilities.retry( f=checkIntentState, retValue=main.FALSE, args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Link Up Intent State Passed\n'
else:
main.assertReturnString += 'Link Up Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ) and utilities.retry( f=checkFlowsState, retValue=main.FALSE, args=[ main ], sleep=20, attempts=3 ):
main.assertReturnString += 'Link Up Flow State Passed\n'
else:
main.assertReturnString += 'Link Up Flow State Failed\n'
testResult = main.FALSE
# Check OnosTopology
if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, main.numLinks ) ):
main.assertReturnString += 'Link Up Topology State Passed\n'
else:
main.assertReturnString += 'Link Up Topology State Failed\n'
testResult = main.FALSE
# Check Connection
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE, args=( main, senderNames, recipientNames, vlanId, useTCP ) ):
main.assertReturnString += 'Link Up Scapy Packet Received Passed\n'
else:
main.assertReturnString += 'Link Up Scapy Packet Recieved Failed\n'
testResult = main.FALSE
# Remove all intents
if utilities.retry( f=removeAllIntents, retValue=main.FALSE, args=( main, [ intentId ] ) ):
main.assertReturnString += 'Remove Intents Passed'
else:
main.assertReturnString += 'Remove Intents Failed'
testResult = main.FALSE
return testResult
def testEndPointFail( main,
name,
intentId,
senders,
recipients,
isolatedSenders,
isolatedRecipients,
onosNode=0,
ethType="",
bandwidth="",
lambdaAlloc=False,
ipProto="",
ipAddresses="",
tcp="",
sw1="",
sw2="",
sw3="",
sw4="",
sw5="",
expectedLink1=0,
expectedLink2=0,
partial=False ):
"""
Test Single to Multipoint Topology for Endpoint failures
"""
# Parameter Validity Check
assert main, "There is no main variable"
assert senders, "You must specify a sender"
assert recipients, "You must specify a recipient"
global itemName
itemName = name
tempHostsData = {}
onosNode = int( onosNode )
main.log.info( itemName + ": Testing Point Intent" )
try:
# Names for scapy
senderNames = [ x.get( "name" ) for x in senders ]
recipientNames = [ x.get( "name" ) for x in recipients ]
isolatedSenderNames = [ x.get( "name" ) for x in isolatedSenders ]
isolatedRecipientNames = [ x.get( "name" ) for x in isolatedRecipients ]
connectedSenderNames = [x.get("name") for x in senders if x.get("name") not in isolatedSenderNames]
connectedRecipientNames = [x.get("name") for x in recipients if x.get("name") not in isolatedRecipientNames]
for sender in senders:
if not sender.get( "device" ):
main.log.warn( "Device not given for sender {0}. Loading from main.hostData".format( sender.get( "name" ) ) )
sender[ "device" ] = main.hostsData.get( sender.get( "name" ) ).get( "location" )
for recipient in recipients:
if not recipient.get( "device" ):
main.log.warn( "Device not given for recipient {0}. Loading from " +\
main.hostData.format( recipient.get( "name" ) ) )
recipient[ "device" ] = main.hostsData.get( recipient.get( "name" ) ).get( "location" )
except( KeyError, TypeError ):
main.log.error( "There was a problem loading the hosts data." )
return main.FALSE
testResult = main.TRUE
main.log.info( itemName + ": Adding multi point to single point intents" )
# Check intent state
if utilities.retry( f=checkIntentState, retValue=main.FALSE,
args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Initial Intent State Passed\n'
else:
main.assertReturnString += 'Initial Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE,
args=[ main ], attempts=5 ) and utilities.retry( f=checkFlowsState,
retValue=main.FALSE,
args=[ main ], attempts=5 ):
main.assertReturnString += 'Initial Flow State Passed\n'
else:
main.assertReturnString += 'Intial Flow State Failed\n'
testResult = main.FALSE
# Check Connectivity
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE,
args=( main, senderNames, recipientNames ) ):
main.assertReturnString += 'Initial Connectivity Check Passed\n'
else:
main.assertReturnString += 'Initial Connectivity Check Failed\n'
testResult = main.FALSE
# Take two links down
# Take first link down
if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "down" ) ):
main.assertReturnString += 'Link Down Passed\n'
else:
main.assertReturnString += 'Link Down Failed\n'
testResult = main.FALSE
# Take second link down
if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw3, sw4, "down" ) ):
main.assertReturnString += 'Link Down Passed\n'
else:
main.assertReturnString += 'Link Down Failed\n'
testResult = main.FALSE
# Check intent state
if utilities.retry( f=checkIntentState, retValue=main.FALSE,
args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Link Down Intent State Passed\n'
else:
main.assertReturnString += 'Link Down Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE,
args=[ main ] ) and utilities.retry( f=checkFlowsState,
retValue=main.FALSE, args=[ main ] ):
main.assertReturnString += 'Link Down Flow State Passed\n'
else:
main.assertReturnString += 'Link Down Flow State Failed\n'
testResult = main.FALSE
# Check OnosTopology
if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink1 ) ):
main.assertReturnString += 'Link Down Topology State Passed\n'
else:
main.assertReturnString += 'Link Down Topology State Failed\n'
testResult = main.FALSE
# Check Connection
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE,
args=( main, senderNames, recipientNames ) ):
main.assertReturnString += 'Link Down Connectivity Check Passed\n'
else:
main.assertReturnString += 'Link Down Connectivity Check Failed\n'
testResult = main.FALSE
# Take a third link down to isolate one node
if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw3, sw5, "down" ) ):
main.assertReturnString += 'Isolation link Down Passed\n'
else:
main.assertReturnString += 'Isolation link Down Failed\n'
testResult = main.FALSE
if partial:
# Check intent state
if utilities.retry( f=checkIntentState, retValue=main.FALSE,
args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Partial failure isolation link Down Intent State Passed\n'
else:
main.assertReturnString += 'Partial failure isolation link Down Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE,
args=[ main ], attempts=5 ) and utilities.retry( f=checkFlowsState,
retValue=main.FALSE,
args=[ main ], attempts=5 ):
main.assertReturnString += 'Partial failure isolation link Down Flow State Passed\n'
else:
main.assertReturnString += 'Partial failure isolation link Down Flow State Failed\n'
testResult = main.FALSE
# Check OnosTopology
if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink2 ) ):
main.assertReturnString += 'Partial failure isolation link Down Topology State Passed\n'
else:
main.assertReturnString += 'Partial failure isolation link Down Topology State Failed\n'
testResult = main.FALSE
# Check Connectivity
# First check connectivity of any isolated senders to recipients
if isolatedSenderNames:
if scapyCheckConnection( main, isolatedSenderNames, recipientNames, None, None, None, None, main.TRUE ):
main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Passed\n'
else:
main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Failed\n'
testResult = main.FALSE
# Next check connectivity of senders to any isolated recipients
if isolatedRecipientNames:
if scapyCheckConnection( main, senderNames, isolatedRecipientNames, None, None, None, None, main.TRUE ):
main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Passed\n'
else:
main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Failed\n'
testResult = main.FALSE
# Next check connectivity of connected senders and recipients
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE,
args=( main, connectedSenderNames , connectedRecipientNames ) ):
main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Passed\n'
else:
main.assertReturnString += 'Partial failure isolation link Down Connectivity Check Failed\n'
testResult = main.FALSE
else:
# Check intent state
if not utilities.retry( f=checkIntentState, retValue=main.TRUE,
args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Isolation link Down Intent State Passed\n'
else:
main.assertReturnString += 'Isolation link Down Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE,
args=[ main ], attempts=5 ) and utilities.retry( f=checkFlowsState,
retValue=main.FALSE,
args=[ main ], attempts=5 ):
main.assertReturnString += 'Isolation link Down Flow State Passed\n'
else:
main.assertReturnString += 'Isolation link Down Flow State Failed\n'
testResult = main.FALSE
# Check OnosTopology
if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, expectedLink2 ) ):
main.assertReturnString += 'Isolation link Down Topology State Passed\n'
else:
main.assertReturnString += 'Isolation link Down Topology State Failed\n'
testResult = main.FALSE
# Check Connectivity
# First check connectivity of any isolated senders to recipients
if isolatedSenderNames:
if scapyCheckConnection( main, isolatedSenderNames, recipientNames, None, None, None, None, main.TRUE ):
main.assertReturnString += 'Isolation link Down Connectivity Check Passed\n'
else:
main.assertReturnString += 'Isolation link Down Connectivity Check Failed\n'
testResult = main.FALSE
# Next check connectivity of senders to any isolated recipients
if isolatedRecipientNames:
if scapyCheckConnection( main, senderNames, isolatedRecipientNames, None, None, None, None, main.TRUE ):
main.assertReturnString += 'Isolation link Down Connectivity Check Passed\n'
else:
main.assertReturnString += 'Isolation link Down Connectivity Check Failed\n'
testResult = main.FALSE
# Next check connectivity of connected senders and recipients
if utilities.retry( f=scapyCheckConnection, retValue=main.TRUE,
args=( main, connectedSenderNames , connectedRecipientNames, None, None, None, None, main.TRUE ) ):
main.assertReturnString += 'Isolation link Down Connectivity Check Passed\n'
else:
main.assertReturnString += 'Isolation link Down Connectivity Check Failed\n'
testResult = main.FALSE
# Bring the links back up
# Bring first link up
if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw1, sw2, "up" ) ):
main.assertReturnString += 'Link Up Passed\n'
else:
main.assertReturnString += 'Link Up Failed\n'
testResult = main.FALSE
# Bring second link up
if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw3, sw5, "up" ) ):
main.assertReturnString += 'Link Up Passed\n'
else:
main.assertReturnString += 'Link Up Failed\n'
testResult = main.FALSE
# Bring third link up
if utilities.retry( f=link, retValue=main.FALSE, args=( main, sw3, sw4, "up" ) ):
main.assertReturnString += 'Link Up Passed\n'
else:
main.assertReturnString += 'Link Up Failed\n'
testResult = main.FALSE
# Wait for reroute
time.sleep( main.rerouteSleep )
# Check Intents
if utilities.retry( f=checkIntentState, retValue=main.FALSE,
args=( main, [ intentId ] ), sleep=main.checkIntentSleep ):
main.assertReturnString += 'Link Up Intent State Passed\n'
else:
main.assertReturnString += 'Link Up Intent State Failed\n'
testResult = main.FALSE
# Check flows count in each node
if utilities.retry( f=checkFlowsCount, retValue=main.FALSE,
args=[ main ], sleep=5, attempts=5 ) and utilities.retry( f=checkFlowsState,
retValue=main.FALSE,
args=[ main ], sleep=5, attempts=5 ):
main.assertReturnString += 'Link Up Flow State Passed\n'
else:
main.assertReturnString += 'Link Up Flow State Failed\n'
testResult = main.FALSE
# Check OnosTopology
if utilities.retry( f=checkTopology, retValue=main.FALSE, args=( main, main.numLinks ) ):
main.assertReturnString += 'Link Up Topology State Passed\n'
else:
main.assertReturnString += 'Link Up Topology State Failed\n'
testResult = main.FALSE
# Check Connection
if utilities.retry( f=scapyCheckConnection, retValue=main.FALSE,
args=( main, senderNames, recipientNames ) ):
main.assertReturnString += 'Link Up Scapy Packet Received Passed\n'
else:
main.assertReturnString += 'Link Up Scapy Packet Recieved Failed\n'
testResult = main.FALSE
# Remove all intents
if utilities.retry( f=removeAllIntents, retValue=main.FALSE, args=( main, [ intentId ] ) ):
main.assertReturnString += 'Remove Intents Passed'
else:
main.assertReturnString += 'Remove Intents Failed'
testResult = main.FALSE
return testResult
def pingallHosts( main, hostList ):
"""
Ping all host in the hosts list variable
"""
main.log.info( "Pinging: " + str( hostList ) )
return main.Mininet1.pingallHosts( hostList )
def fwdPingall( main ):
"""
Use fwd app and pingall to discover all the hosts
"""
activateResult = main.TRUE
appCheck = main.TRUE
getDataResult = main.TRUE
main.log.info( "Activating reactive forwarding app " )
activateResult = main.CLIs[ 0 ].activateApp( "org.onosproject.fwd" )
# Wait for forward app activation to propagate
time.sleep( main.fwdSleep )
# Check that forwarding is enabled on all nodes
for i in range( main.numCtrls ):
appCheck = appCheck and main.CLIs[ i ].appToIDCheck()
if appCheck != main.TRUE:
main.log.warn( main.CLIs[ i ].apps() )
main.log.warn( main.CLIs[ i ].appIDs() )
# Send pingall in mininet
main.log.info( "Run Pingall" )
pingResult = main.Mininet1.pingall( timeout = 600 )
main.log.info( "Deactivating reactive forwarding app " )
deactivateResult = main.CLIs[ 0 ].deactivateApp( "org.onosproject.fwd" )
if activateResult and deactivateResult:
main.log.info( "Successfully used fwd app to discover hosts" )
getDataResult = main.TRUE
else:
main.log.info( "Failed to use fwd app to discover hosts" )
getDataResult = main.FALSE
return getDataResult
def confirmHostDiscovery( main ):
"""
Confirms that all ONOS nodes have discovered all scapy hosts
"""
import collections
scapyHostCount = len( main.scapyHosts )
hosts = main.topo.getAllHosts( main ) # Get host data from each ONOS node
hostFails = [] # Reset for each failed attempt
# Check for matching hosts on each node
scapyHostIPs = [ x.hostIp for x in main.scapyHosts if x.hostIp != "0.0.0.0" ]
for controller in range( main.numCtrls ):
controllerStr = str( controller + 1 ) # ONOS node number
# Compare Hosts
# Load hosts data for controller node
try:
if hosts[ controller ]:
main.log.info( "Hosts discovered" )
else:
main.log.error( "Problem discovering hosts" )
if hosts[ controller ] and "Error" not in hosts[ controller ]:
try:
hostData = json.loads( hosts[ controller ] )
except ( TypeError, ValueError ):
main.log.error( "Could not load json:" + str( hosts[ controller ] ) )
hostFails.append( controllerStr )
else:
onosHostIPs = [ x.get( "ipAddresses" )[ 0 ]
for x in hostData
if len( x.get( "ipAddresses" ) ) > 0 ]
if not set( collections.Counter( scapyHostIPs ) ).issubset( set ( collections.Counter( onosHostIPs ) ) ):
main.log.warn( "Controller {0} only sees nodes with {1} IPs. It should see all of the following: {2}".format( controllerStr, onosHostIPs, scapyHostIPs ) )
hostFails.append( controllerStr )
else:
main.log.error( "Hosts returned nothing or an error." )
hostFails.append( controllerStr )
except IndexError:
main.log.error( "Hosts returned nothing, Failed to discover hosts." )
return main.FALSE
if hostFails:
main.log.error( "List of failed ONOS Nodes:" + ', '.join( map( str, hostFails ) ) )
return main.FALSE
else:
return main.TRUE
def sendDiscoveryArp( main, hosts=None ):
"""
Sends Discovery ARP packets from each host provided
Defaults to each host in main.scapyHosts
"""
# Send an arp ping from each host
if not hosts:
hosts = main.scapyHosts
for host in hosts:
pkt = 'Ether( src="{0}")/ARP( psrc="{1}")'.format( host.hostMac, host.hostIp )
# Send from the VLAN interface if there is one so ONOS discovers the VLAN correctly
iface = None
for interface in host.getIfList():
if '.' in interface:
main.log.debug( "Detected VLAN interface {0}. Sending ARP packet from {0}".format( interface ) )
iface = interface
break
host.sendPacket( packet=pkt, iface=iface )
main.log.info( "Sending ARP packet from {0}".format( host.name ) )
def populateHostData( main ):
"""
Populates hostsData
"""
import json
try:
hostsJson = json.loads( main.CLIs[ 0 ].hosts() )
hosts = main.Mininet1.getHosts().keys()
# TODO: Make better use of new getHosts function
for host in hosts:
main.hostsData[ host ] = {}
main.hostsData[ host ][ 'mac' ] = \
main.Mininet1.getMacAddress( host ).upper()
for hostj in hostsJson:
if main.hostsData[ host ][ 'mac' ] == hostj[ 'mac' ]:
main.hostsData[ host ][ 'id' ] = hostj[ 'id' ]
main.hostsData[ host ][ 'vlan' ] = hostj[ 'vlan' ]
main.hostsData[ host ][ 'location' ] = \
hostj[ 'location' ][ 'elementId' ] + '/' + \
hostj[ 'location' ][ 'port' ]
main.hostsData[ host ][ 'ipAddresses' ] = hostj[ 'ipAddresses' ]
return main.TRUE
except ValueError:
main.log.error( "ValueError while populating hostsData" )
return main.FALSE
except KeyError:
main.log.error( "KeyError while populating hostsData" )
return main.FALSE
except IndexError:
main.log.error( "IndexError while populating hostsData" )
return main.FALSE
except TypeError:
main.log.error( "TypeError while populating hostsData" )
return main.FALSE
def checkTopology( main, expectedLink ):
statusResult = main.TRUE
# Check onos topology
main.log.info( itemName + ": Checking ONOS topology " )
for i in range( main.numCtrls ):
statusResult = main.CLIs[ i ].checkStatus( main.numSwitch,
expectedLink )\
and statusResult
if not statusResult:
main.log.error( itemName + ": Topology mismatch" )
else:
main.log.info( itemName + ": Topology match" )
return statusResult
def checkIntentState( main, intentsId ):
"""
This function will check intent state to make sure all the intents
are in INSTALLED state
"""
intentResult = main.TRUE
results = []
main.log.info( itemName + ": Checking intents state" )
# First check of intents
for i in range( main.numCtrls ):
tempResult = main.CLIs[ i ].checkIntentState( intentsId=intentsId )
results.append( tempResult )
expectedState = [ 'INSTALLED', 'INSTALLING' ]
if all( result == main.TRUE for result in results ):
main.log.info( itemName + ": Intents are installed correctly" )
else:
# Wait for at least 5 second before checking the intents again
main.log.error( "Intents are not installed correctly. Waiting 5 sec" )
time.sleep( 5 )
results = []
# Second check of intents since some of the intents may be in
# INSTALLING state, they should be in INSTALLED at this time
for i in range( main.numCtrls ):
tempResult = main.CLIs[ i ].checkIntentState( intentsId=intentsId )
results.append( tempResult )
if all( result == main.TRUE for result in results ):
main.log.info( itemName + ": Intents are installed correctly" )
intentResult = main.TRUE
else:
main.log.error( itemName + ": Intents are NOT installed correctly" )
intentResult = main.FALSE
return intentResult
def checkFlowsState( main ):
main.log.info( itemName + ": Check flows state" )
checkFlowsResult = main.CLIs[ 0 ].checkFlowsState( isPENDING=False )
return checkFlowsResult
def link( main, sw1, sw2, option ):
# link down
main.log.info( itemName + ": Bring link " + option + "between " +
sw1 + " and " + sw2 )
linkResult = main.Mininet1.link( end1=sw1, end2=sw2, option=option )
return linkResult
def scapyCheckConnection( main, senders, recipients, vlanId=None, useTCP=False, packet=None, packetFilter=None, expectFailure=False ):
"""
Checks the connectivity between all given sender hosts and all given recipient hosts
Packet may be specified. Defaults to Ether/IP packet
Packet Filter may be specified. Defaults to Ether/IP from current sender MAC
Todo: Optional packet and packet filter attributes for sender and recipients
Expect Failure when the sender and recipient are not supposed to have connectivity
Timeout of 1 second, returns main.TRUE if the filter is not triggered and kills the filter
"""
connectionsFunctional = main.TRUE
if not packetFilter:
packetFilter = 'ether host {}'
if useTCP:
packetFilter += ' ip proto \\tcp tcp port {}'.format(main.params[ 'SDNIP' ][ 'dstPort' ])
if expectFailure:
timeout = 1
else:
timeout = 10
for sender in senders:
try:
senderComp = getattr( main, sender )
except AttributeError:
main.log.error( "main has no attribute {}".format( sender ) )
connectionsFunctional = main.FALSE
continue
for recipient in recipients:
# Do not send packets to self since recipient CLI will already be busy
if recipient == sender:
continue
try:
recipientComp = getattr( main, recipient )
except AttributeError:
main.log.error( "main has no attribute {}".format( recipient ) )
connectionsFunctional = main.FALSE
continue
if vlanId:
recipientComp.startFilter( pktFilter = ( "vlan {}".format( vlanId ) + " && " + packetFilter.format( senderComp.hostMac ) ) )
else:
recipientComp.startFilter( pktFilter = packetFilter.format( senderComp.hostMac ) )
if not packet:
if vlanId:
pkt = 'Ether( src="{0}", dst="{2}" )/Dot1Q(vlan={4})/IP( src="{1}", dst="{3}" )'.format(
senderComp.hostMac,
senderComp.hostIp,
recipientComp.hostMac,
recipientComp.hostIp,
vlanId )
else:
pkt = 'Ether( src="{0}", dst="{2}" )/IP( src="{1}", dst="{3}" )'.format(
senderComp.hostMac,
senderComp.hostIp,
recipientComp.hostMac,
recipientComp.hostIp )
else:
pkt = packet
if vlanId:
senderComp.sendPacket( iface=( "{0}-eth0.{1}".format( sender, vlanId ) ), packet = pkt )
else:
senderComp.sendPacket( packet = pkt )
if recipientComp.checkFilter( timeout ):
if expectFailure:
main.log.error( "Packet from {0} successfully received by {1} when it should not have been".format( sender , recipient ) )
connectionsFunctional = main.FALSE
else:
main.log.info( "Packet from {0} successfully received by {1}".format( sender , recipient ) )
else:
recipientComp.killFilter()
if expectFailure:
main.log.info( "As expected, packet from {0} was not received by {1}".format( sender , recipient ) )
else:
main.log.error( "Packet from {0} was not received by {1}".format( sender , recipient ) )
connectionsFunctional = main.FALSE
return connectionsFunctional
def removeAllIntents( main, intentsId ):
"""
Remove all intents in the intentsId
"""
onosSummary = []
removeIntentResult = main.TRUE
# Remove intents
for intent in intentsId:
main.CLIs[ 0 ].removeIntent( intentId=intent, purge=True )
time.sleep( main.removeIntentSleep )
# If there is remianing intents then remove intents should fail
for i in range( main.numCtrls ):
onosSummary.append( json.loads( main.CLIs[ i ].summary() ) )
for summary in onosSummary:
if summary.get( 'intents' ) != 0:
main.log.warn( itemName + ": There are " +
str( summary.get( 'intents' ) ) +
" intents remaining in node " +
str( summary.get( 'node' ) ) +
", failed to remove all the intents " )
removeIntentResult = main.FALSE
if removeIntentResult:
main.log.info( itemName + ": There are no more intents remaining, " +
"successfully removed all the intents." )
return removeIntentResult
def checkFlowsCount( main ):
"""
Check flows count in each node
"""
flowsCount = []
main.log.info( itemName + ": Checking flows count in each ONOS node" )
for i in range( main.numCtrls ):
summaryResult = main.CLIs[ i ].summary()
if not summaryResult:
main.log.error( itemName + ": There is something wrong with " +
"summary command" )
return main.FALSE
else:
summaryJson = json.loads( summaryResult )
flowsCount.append( summaryJson.get( 'flows' ) )
if flowsCount:
if all( flows==flowsCount[ 0 ] for flows in flowsCount ):
main.log.info( itemName + ": There are " + str( flowsCount[ 0 ] ) +
" flows in all ONOS node" )
else:
for i in range( main.numCtrls ):
main.log.debug( itemName + ": ONOS node " + str( i ) + " has " +
str( flowsCount[ i ] ) + " flows" )
else:
main.log.error( "Checking flows count failed, check summary command" )
return main.FALSE
return main.TRUE
def checkLeaderChange( leaders1, leaders2 ):
"""
Checks for a change in intent partition leadership.
Takes the output of leaders -c in json string format before and after
a potential change as input
Returns main.TRUE if no mismatches are detected
Returns main.FALSE if there is a mismatch or on error loading the input
"""
try:
leaders1 = json.loads( leaders1 )
leaders2 = json.loads( leaders2 )
except( AttributeError, TypeError ):
main.log.exception( self.name + ": Object not as expected" )
return main.FALSE
except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanup()
main.exit()
main.log.info( "Checking Intent Paritions for Change in Leadership" )
mismatch = False
for dict1 in leaders1:
if "intent" in dict1.get( "topic", [] ):
for dict2 in leaders2:
if dict1.get( "topic", 0 ) == dict2.get( "topic", 0 ) and \
dict1.get( "leader", 0 ) != dict2.get( "leader", 0 ):
mismatch = True
main.log.error( "{0} changed leader from {1} to {2}".\
format( dict1.get( "topic", "no-topic" ),\
dict1.get( "leader", "no-leader" ),\
dict2.get( "leader", "no-leader" ) ) )
if mismatch:
return main.FALSE
else:
return main.TRUE
def report( main ):
"""
Report errors/warnings/exceptions
"""
main.ONOSbench.logReport( main.ONOSip[ 0 ],
[ "INFO",
"FOLLOWER",
"WARN",
"flow",
"ERROR",
"Except" ],
"s" )
main.log.info( "ERROR report: \n" )
for i in range( main.numCtrls ):
main.ONOSbench.logReport( main.ONOSip[ i ],
[ "ERROR" ],
"d" )
main.log.info( "EXCEPTIONS report: \n" )
for i in range( main.numCtrls ):
main.ONOSbench.logReport( main.ONOSip[ i ],
[ "Except" ],
"d" )
main.log.info( "WARNING report: \n" )
for i in range( main.numCtrls ):
main.ONOSbench.logReport( main.ONOSip[ i ],
[ "WARN" ],
"d" )
def flowDuration( main ):
"""
Check age of flows to see if flows are being overwritten
"""
import time
main.log.info( "Getting current flow durations" )
flowsJson1 = main.CLIs[ 0 ].flows( noCore=True )
try:
flowsJson1 = json.loads( flowsJson1 )
except ValueError:
main.log.error( "Unable to read flows" )
return main.FALSE
flowLife = []
waitFlowLife = []
for device in flowsJson1:
if device.get( 'flowcount', 0 ) > 0:
for i in range( device[ 'flowCount' ] ):
flowLife.append( device[ 'flows' ][ i ][ 'life' ] )
main.log.info( "Sleeping for {} seconds".format( main.flowDurationSleep ) )
time.sleep( main.flowDurationSleep )
main.log.info( "Getting new flow durations" )
flowsJson2 = main.CLIs[ 0 ].flows( noCore=True )
try:
flowsJson2 = json.loads( flowsJson2 )
except ValueError:
main.log.error( "Unable to read flows" )
return main.FALSE
for device in flowsJson2:
if device.get( 'flowcount', 0 ) > 0:
for i in range( device[ 'flowCount' ] ):
waitFlowLife.append( device[ 'flows' ][ i ][ 'life' ] )
main.log.info( "Determining whether flows where overwritten" )
if len( flowLife ) == len( waitFlowLife ):
for i in range( len( flowLife) ):
if waitFlowLife[ i ] - flowLife[ i ] < main.flowDurationSleep:
return main.FALSE
else:
return main.FALSE
return main.TRUE