Stratum Support for Segement Rounting Suite
- Add Stratum Bmv2 switch support for SRDhcpRelay and SRRouting tests
- Add Support for 0x1 topology on a Stratum Tofino HW switch
- Support for dockerized mininet with Stratum BMv2 switches
- Update scapy driver to work with newer versions of scapy
- Simple parsing for scapy ping output
- Add support for fetching and installing external onos apps
- Add support for onos-diagnostics profiles
- Move onos log levels to params file
- Add onos cfg settings to SR tests
Change-Id: I7c4a71484c8fd5735da9ef09b96d8990283b199b
(cherry picked from commit bef6d9bd943996483fed32130cb30ad26a06aac0)
diff --git a/TestON/drivers/common/cli/networkdriver.py b/TestON/drivers/common/cli/networkdriver.py
index 1cd242c..968973d 100755
--- a/TestON/drivers/common/cli/networkdriver.py
+++ b/TestON/drivers/common/cli/networkdriver.py
@@ -31,6 +31,9 @@
import os
import re
import types
+import time
+import itertools
+import random
from drivers.common.clidriver import CLI
from core.graph import Graph
@@ -126,7 +129,7 @@
try:
for key, value in main.componentDictionary.items():
if hasattr( main, key ):
- if value[ 'type' ] in [ 'MininetSwitchDriver', 'OFDPASwitchDriver' ]:
+ if value[ 'type' ] in [ 'MininetSwitchDriver', 'OFDPASwitchDriver', 'StratumOSSwitchDriver' ]:
component = getattr( main, key )
shortName = component.options[ 'shortName' ]
localName = self.name + "-" + shortName
@@ -275,7 +278,12 @@
continue
if not includeStopped and not switchComponent.isup:
continue
- dpid = switchComponent.dpid.replace( '0x', '' ).zfill( 16 )
+ try:
+ dpid = switchComponent.dpid
+ except AttributeError:
+ main.log.warn( "Switch has no dpid, ignore this if not an OpenFlow switch" )
+ dpid = "0x0"
+ dpid = dpid.replace( '0x', '' ).zfill( 16 )
ports = switchComponent.ports
swClass = 'Unknown'
pid = None
@@ -344,7 +352,6 @@
"""
Return MAC address of a host
"""
- import re
try:
hostComponent = self.hosts[ host ]
response = hostComponent.ifconfig()
@@ -460,8 +467,6 @@
main.TRUE if pingall completes with no pings dropped
otherwise main.FALSE
"""
- import time
- import itertools
try:
timeout = int( timeout )
main.log.info( self.name + ": Checking reachabilty to the hosts using ping" )
@@ -495,7 +500,7 @@
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanAndExit()
- def pingallHosts( self, hostList, wait=1 ):
+ def pingallHosts( self, hostList, ipv6=False, wait=1, useScapy=False ):
"""
Ping all specified IPv4 hosts
@@ -507,8 +512,6 @@
Returns main.FALSE if one or more of hosts specified
cannot reach each other"""
- import time
- import itertools
hostComponentList = []
for hostName in hostList:
hostComponent = self.hosts[ hostName ]
@@ -522,8 +525,49 @@
hostPairs = itertools.permutations( list( hostComponentList ), 2 )
for hostPair in list( hostPairs ):
pingResponse += hostPair[ 0 ].options[ 'shortName' ] + " -> "
- ipDst = hostPair[ 1 ].options[ 'ip6' ] if ipv6 else hostPair[ 1 ].options[ 'ip' ]
- pingResult = hostPair[ 0 ].ping( ipDst, wait=int( wait ) )
+ ipDst = hostPair[ 1 ].options.get( 'ip6', hostPair[ 1 ].options[ 'ip' ] ) if ipv6 else hostPair[ 1 ].options[ 'ip' ]
+ srcIface = hostPair[ 0 ].interfaces[0].get( 'name' )
+ dstIface = hostPair[ 1 ].interfaces[0].get( 'name' )
+ srcMac = hostPair[0].interfaces[0].get( 'mac' )
+ dstMac = hostPair[1].interfaces[0].get( 'mac' )
+ if useScapy:
+ main.log.debug( "Pinging from " + str( hostPair[ 0 ].shortName ) + " to " + str( hostPair[ 1 ].shortName ) )
+ srcIPs = hostPair[ 0 ].interfaces[0].get( 'ips' )
+ dstIPs = hostPair[ 1 ].interfaces[0].get( 'ips' )
+ # Use scapy to send and recieve packets
+ hostPair[ 1 ].startScapy( ifaceName=dstIface )
+ hostPair[ 1 ].addRoutes()
+ hostPair[ 1 ].startFilter( ifaceName=dstIface, pktFilter="ether host %s and ip host %s" % ( srcMac, srcIPs[0] ) )
+
+ hostPair[ 0 ].startScapy( ifaceName=srcIface )
+ hostPair[ 0 ].addRoutes()
+ hostPair[ 0 ].buildEther( dst=dstMac )
+ hostPair[ 0 ].buildIP( src=srcIPs, dst=dstIPs )
+ hostPair[ 0 ].buildICMP( )
+ hostPair[ 0 ].sendPacket( iface=srcIface )
+
+ waiting = not hostPair[ 1 ].checkFilter()
+ if not waiting:
+ pingResult = main.FALSE
+ packets = hostPair[ 1 ].readPackets()
+ main.log.warn( packets )
+ for packet in packets.splitlines():
+ main.log.debug( packet )
+ if srcIPs[0] in packet:
+ pingResult = main.TRUE
+ else:
+ main.log.warn( "Did not receive packets, killing filter" )
+ kill = hostPair[ 1 ].killFilter()
+ main.log.debug( kill )
+ hostPair[ 1 ].handle.sendline( "" )
+ hostPair[ 1 ].handle.expect( hostPair[ 1 ].scapyPrompt )
+ main.log.debug( hostPair[ 1 ].handle.before )
+ # One of the host to host pair is unreachable
+ pingResult = main.FALSE
+ hostPair[ 0 ].stopScapy()
+ hostPair[ 1 ].stopScapy()
+ else:
+ pingResult = hostPair[ 0 ].ping( ipDst, interface=srcIface, wait=int( wait ) )
if pingResult:
pingResponse += hostPair[ 1 ].options[ 'shortName' ]
else:
@@ -538,6 +582,122 @@
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanAndExit()
+ def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0, useScapy=False ):
+ """
+ Verify ping from each host in srcList to each host in dstList
+
+ acceptableFailed: max number of acceptable failed pings
+
+ Returns main.TRUE if all src hosts can reach all dst hosts
+ Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
+ """
+ try:
+ main.log.info( "Verifying ping from each src host to each dst host" )
+
+ srcComponentList = []
+ for hostName in srcList:
+ hostComponent = self.hosts[ hostName ]
+ if hostComponent:
+ main.log.debug( repr( hostComponent ) )
+ srcComponentList.append( hostComponent )
+ dstComponentList = []
+ for hostName in dstList:
+ hostComponent = self.hosts[ hostName ]
+ if hostComponent:
+ main.log.debug( repr( hostComponent ) )
+ dstComponentList.append( hostComponent )
+
+ isReachable = main.TRUE
+ wait = int( wait )
+ cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
+ pingResponse = "Ping output:\n"
+ failedPingsTotal = 0
+ for srcHost in srcComponentList:
+ pingResponse += str( str( srcHost.shortName ) + " -> " )
+ for dstHost in dstComponentList:
+ failedPings = 0
+ dstIP = dstHost.ip
+ assert dstIP, "Not able to get IP address of host {}".format( dstHost )
+ for iface in srcHost.interfaces:
+ # FIXME This only works if one iface name is configured
+ # NOTE: We can use an IP with -I instead of an interface name as well
+ name = iface.get( 'name' )
+ if name:
+ cmd += " -I %s " % name
+
+ if useScapy:
+ while failedPings <= acceptableFailed:
+ main.log.debug( "Pinging from " + str( srcHost.shortName ) + " to " + str( dstHost.shortName ) )
+ # Use scapy to send and recieve packets
+ dstHost.startFilter()
+ srcHost.buildEther( dst=srcHost.interfaces[0].get( 'mac') )
+ srcHost.sendPacket()
+ output = dstHost.checkFilter()
+ main.log.debug( output )
+ if output:
+ #TODO: parse output?
+ packets = dstHost.readPackets()
+ for packet in packets.splitlines():
+ main.log.debug( packet )
+ pingResponse += " " + str( dstHost.shortName )
+ break
+ else:
+ kill = dstHost.killFilter()
+ main.log.debug( kill )
+ dstHost.handle.sendline( "" )
+ dstHost.handle.expect( dstHost.scapyPrompt )
+ main.log.debug( dstHost.handle.before )
+ failedPings += 1
+ time.sleep(1)
+ if failedPings > acceptableFailed:
+ # One of the host to host pair is unreachable
+ pingResponse += " X"
+ isReachable = main.FALSE
+ failedPingsTotal += 1
+
+ else:
+ pingCmd = cmd + str( dstIP )
+ while failedPings <= acceptableFailed:
+ main.log.debug( "Pinging from " + str( srcHost.shortName ) + " to " + str( dstHost.shortName ) )
+ self.handle.sendline( pingCmd )
+ self.handle.expect( self.prompt, timeout=wait + 5 )
+ response = self.handle.before
+ if re.search( ',\s0\%\spacket\sloss', response ):
+ pingResponse += " " + str( dstHost.shortName )
+ break
+ else:
+ failedPings += 1
+ time.sleep(1)
+ if failedPings > acceptableFailed:
+ # One of the host to host pair is unreachable
+ pingResponse += " X"
+ isReachable = main.FALSE
+ failedPingsTotal += 1
+ pingResponse += "\n"
+ main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
+ return isReachable
+ except AssertionError:
+ main.log.exception( "" )
+ return main.FALSE
+ except pexpect.TIMEOUT:
+ main.log.exception( self.name + ": TIMEOUT exception" )
+ response = self.handle.before
+ # NOTE: Send ctrl-c to make sure command is stopped
+ self.exitFromCmd( [ "Interrupt", self.prompt ] )
+ response += self.handle.before + self.handle.after
+ self.handle.sendline( "" )
+ self.handle.expect( self.prompt )
+ response += self.handle.before + self.handle.after
+ main.log.debug( response )
+ return main.FALSE
+ except pexpect.EOF:
+ main.log.error( self.name + ": EOF exception found" )
+ main.log.error( self.name + ": " + self.handle.before )
+ main.cleanAndExit()
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanAndExit()
+
def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
'''
Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
@@ -658,7 +818,6 @@
Any link that has either end included in skipLinks will be excluded.
Returns the link as a list, e.g. [ 's1', 's2' ].
"""
- import random
candidateLinks = []
try:
if not nonCut:
@@ -708,7 +867,6 @@
Switches specified in skipSwitches will be excluded.
Returns the name of the chosen switch.
"""
- import random
candidateSwitches = []
try:
if not nonCut:
@@ -896,9 +1054,11 @@
for host in hostList:
flushCmd = ""
cmd = ""
- if self.getIPAddress( host ):
+ if self.getIPAddress( host ) or hosts[host]['interfaces'][0].get( 'ips', False ) :
flushCmd = "sudo ip neigh flush all"
- cmd = "arping -c 1 -w {} {}".format( wait, dstIp )
+ intf = hosts[host]['interfaces'][0].get( 'name' )
+ intfStr = "-i {}".format( intf ) if intf else ""
+ cmd = "sudo arping -c 1 -w {} {} {}".format( wait, intfStr, dstIp )
main.log.debug( "Sending IPv4 arping from host {}".format( host ) )
elif self.getIPAddress( host, proto='IPV6' ):
flushCmd = "sudo ip -6 neigh flush all"