[ONOS-7747] Add router failure test cases to SRRouting
Change-Id: I06706c36caa181fff50c0f13c5976298e017940f
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index af69d68..84930de 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -3888,7 +3888,7 @@
host + " ifconfig"
]
for cmd in commands:
- print "cmd= ", cmd
+ main.log.info( "cmd={}".format( cmd ) )
self.handle.sendline( cmd )
self.handle.expect( "mininet>" )
main.log.info( "====> %s ", self.handle.before )
@@ -3995,7 +3995,7 @@
host + " ifconfig"
]
for cmd in commands:
- print "cmd= ", cmd
+ main.log.info( "cmd={}".format( cmd ) )
self.handle.sendline( cmd )
self.handle.expect( "mininet>" )
main.log.info( "====> %s ", self.handle.before )
diff --git a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params
index 027aeb1..72d8925 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params
+++ b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params
@@ -1,5 +1,5 @@
<PARAMS>
- <testcases>101,102,103,104,105,106,107,108,109,201,202,203,204,205,206,207,208,209,301,302,303,304,305,306,307,308,309,601,602,603,604,605,606,620,621,622,630,640,641,642,643,651,652,653</testcases>
+ <testcases>101,102,103,104,105,106,107,108,109,201,202,203,204,205,206,207,208,209,301,302,303,304,305,306,307,308,309,601,602,603,604,605,606,620,621,622,630,640,641,642,643,651,652,653,660,661,662,663,664,665</testcases>
<GRAPH>
<nodeCluster>Fabric</nodeCluster>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.py b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.py
index 281e7a5..f379896 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.py
@@ -1446,3 +1446,173 @@
lib.verifyTraffic( main, main.internalIpv4Hosts, "10.2.21.1", "h5v4Scapy", "h5v4-bond1" )
lib.cleanup( main, copyKarafLog=False, removeHostComponent=True )
+
+ def CASE660( self, main ):
+ """
+ External router failure
+ - Bring down quagga external router-1. Hosts that are behind router-2 should still be reachable. Hosts that are behind router-1 should not be reachable.
+ - Bring router up again, all external hosts are reachable again.
+ - Repeat this with external router-2.
+ """
+ from tests.USECASE.SegmentRouting.SRRouting.dependencies.SRRoutingTest import *
+ from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+ main.case( "External router failure with cross-link" )
+ setupTest( main, test_idx=660, onosNodes=3, static=True )
+ main.externalIpv4Hosts += main.staticIpv4Hosts
+ main.externalIpv6Hosts += main.staticIpv6Hosts
+ verify( main, disconnected=False )
+ # Bring down/up external router-1
+ verifyRouterFailure( main, "r1", [ "rh5v4" ], [ "rh11v6", "rh5v6" ] )
+ # Bring down/up external router-2
+ verifyRouterFailure( main, "r2", [], [ "rh22v6" ] )
+ lib.cleanup( main, copyKarafLog=False, removeHostComponent=True )
+
+ def CASE661( self, main ):
+ """
+ External router link failure
+ - Drop a non-cross-link for external router-1. All external hosts should be reachable (via cross-link).
+ - Bring up the link. All external hosts should be reachable.
+ - Repeat the steps above with the cross-link of external router-1
+ - Repeat all steps above with external router-2
+ """
+ from tests.USECASE.SegmentRouting.SRRouting.dependencies.SRRoutingTest import *
+ from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+ main.case( "External router link failure with cross-link" )
+ setupTest( main, test_idx=661, onosNodes=3, static=True )
+ main.externalIpv4Hosts += main.staticIpv4Hosts
+ main.externalIpv6Hosts += main.staticIpv6Hosts
+ verify( main, disconnected=False )
+ # Bring down/up a non-cross-link for external router-1
+ portsToDisable = [ [ "of:0000000000000005", 13 ] ]
+ lib.disablePortBatch( main, portsToDisable, 10, 48 )
+ verify( main, disconnected=False, internal=False )
+ lib.enablePortBatch( main, portsToDisable, 10, 48 )
+ verify( main, disconnected=False, internal=False )
+ # Bring down/up a cross-link for external router-1
+ portsToDisable = [ [ "of:0000000000000005", 14 ] ]
+ lib.disablePortBatch( main, portsToDisable, 10, 48 )
+ verify( main, disconnected=False, internal=False )
+ lib.enablePortBatch( main, portsToDisable, 10, 48 )
+ verify( main, disconnected=False, internal=False )
+ # Bring down/up a non-cross-link for external router-2
+ portsToDisable = [ [ "of:0000000000000004", 14 ] ]
+ lib.disablePortBatch( main, portsToDisable, 10, 48 )
+ verify( main, disconnected=False, internal=False )
+ lib.enablePortBatch( main, portsToDisable, 10, 48 )
+ verify( main, disconnected=False, internal=False )
+ # Bring down/up a cross-link for external router-2
+ portsToDisable = [ [ "of:0000000000000004", 13 ] ]
+ lib.disablePortBatch( main, portsToDisable, 10, 48 )
+ verify( main, disconnected=False, internal=False )
+ lib.enablePortBatch( main, portsToDisable, 10, 48 )
+ verify( main, disconnected=False, internal=False )
+ lib.cleanup( main, copyKarafLog=False, removeHostComponent=True )
+
+ def CASE662( self, main ):
+ """
+ Internal router failure
+ - Bring down quagga internal router-1. All external hosts should be reachable (via cross-link).
+ - Bring the router up. All external hosts should be reachable.
+ - Repeat this with internal router-2.
+ """
+ from tests.USECASE.SegmentRouting.SRRouting.dependencies.SRRoutingTest import *
+ from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+ main.case( "Internal router failure with cross-link" )
+ setupTest( main, test_idx=662, onosNodes=3, static=True )
+ main.externalIpv4Hosts += main.staticIpv4Hosts
+ main.externalIpv6Hosts += main.staticIpv6Hosts
+ verify( main, disconnected=False )
+ # Bring down/up internal router-1
+ verifyRouterFailure( main, "bgp1" )
+ # Bring down/up internal router-2
+ verifyRouterFailure( main, "bgp2" )
+ lib.cleanup( main, copyKarafLog=False, removeHostComponent=True )
+
+ def CASE663( self, main ):
+ """
+ External router failure without cross-link
+ - Drop the cross-link for both external routers. All external hosts should be reachable.
+ - Bring down quagga external router-1. Hosts that are behind router-2 should still be reachable. Hosts that are behind router-1 should not be reachable.
+ - Bring router up again, all external hosts are reachable again.
+ - Repeat this with external router-2.
+ """
+ from tests.USECASE.SegmentRouting.SRRouting.dependencies.SRRoutingTest import *
+ from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+ main.case( "External router failure without cross-link" )
+ setupTest( main, test_idx=663, onosNodes=3, static=True )
+ main.externalIpv4Hosts += main.staticIpv4Hosts
+ main.externalIpv6Hosts += main.staticIpv6Hosts
+ verify( main, disconnected=False )
+ # Drop the cross-link
+ portsToDisable = [ [ "of:0000000000000004", 13 ], [ "of:0000000000000005", 14 ] ]
+ lib.disablePortBatch( main, portsToDisable, 10, 48 )
+ verify( main, disconnected=False, internal=False )
+ # Bring down/up external router-1
+ verifyRouterFailure( main, "r1", [ "rh5v4" ], [ "rh11v6", "rh5v6" ] )
+ # Bring down/up external router-2
+ verifyRouterFailure( main, "r2", [], [ "rh22v6" ] )
+ lib.cleanup( main, copyKarafLog=False, removeHostComponent=True )
+
+ def CASE664( self, main ):
+ """
+ External router link failure without cross-link
+ - Drop the cross-link for both external routers. All external hosts should be reachable.
+ - Drop an extra link for external router-1. Only hosts connected to router-2 should be reachable.
+ - Bring up single link for external router-1. All external hosts should be reachable.
+ - Repeat the two steps above with external router-2
+ """
+ from tests.USECASE.SegmentRouting.SRRouting.dependencies.SRRoutingTest import *
+ from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+ main.case( "External router link failure without cross-link" )
+ setupTest( main, test_idx=664, onosNodes=3, static=True )
+ main.externalIpv4Hosts += main.staticIpv4Hosts
+ main.externalIpv6Hosts += main.staticIpv6Hosts
+ verify( main, disconnected=False )
+ # Drop the cross-link
+ portsToDisable = [ [ "of:0000000000000004", 13 ], [ "of:0000000000000005", 14 ] ]
+ lib.disablePortBatch( main, portsToDisable, 10, 48 )
+ verify( main, disconnected=False, internal=False )
+ # Bring down/up a non-cross-link for external router-1
+ portsToDisable = [ [ "of:0000000000000005", 13 ] ]
+ lib.disablePortBatch( main, portsToDisable, 10, 48 )
+ main.disconnectedExternalIpv4Hosts = [ 'rh5v4' ]
+ main.disconnectedExternalIpv6Hosts = [ "rh11v6", "rh5v6" ]
+ verify( main, internal=False )
+ lib.enablePortBatch( main, portsToDisable, 10, 48 )
+ main.disconnectedExternalIpv4Hosts = []
+ main.disconnectedExternalIpv6Hosts = []
+ verify( main, disconnected=False, internal=False )
+ # Bring down/up a non-cross-link for external router-2
+ portsToDisable = [ [ "of:0000000000000004", 14 ] ]
+ lib.disablePortBatch( main, portsToDisable, 10, 48 )
+ main.disconnectedExternalIpv6Hosts = [ "rh22v6" ]
+ verify( main, internal=False )
+ lib.enablePortBatch( main, portsToDisable, 10, 48 )
+ main.disconnectedExternalIpv6Hosts = []
+ verify( main, disconnected=False, internal=False )
+ lib.cleanup( main, copyKarafLog=False, removeHostComponent=True )
+
+ def CASE665( self, main ):
+ """
+ Internal router failure without cross-link
+ - Drop the cross-link for both external routers. All external hosts should be reachable.
+ - Bring down quagga internal router-1. Hosts that are behind router-2 should still be reachable. Hosts that are behind router-1 should not be reachable.
+ - Bring router up again, all external hosts are reachable again.
+ - Repeat this with internal router-2.
+ """
+ from tests.USECASE.SegmentRouting.SRRouting.dependencies.SRRoutingTest import *
+ from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+ main.case( "Internal router failure without cross-link" )
+ setupTest( main, test_idx=665, onosNodes=3, static=True )
+ main.externalIpv4Hosts += main.staticIpv4Hosts
+ main.externalIpv6Hosts += main.staticIpv6Hosts
+ verify( main, disconnected=False )
+ # Drop the cross-link
+ portsToDisable = [ [ "of:0000000000000004", 13 ], [ "of:0000000000000005", 14 ] ]
+ lib.disablePortBatch( main, portsToDisable, 10, 48 )
+ verify( main, disconnected=False, internal=False )
+ # Bring down/up internal router-1
+ verifyRouterFailure( main, "bgp1", [], [ "rh22v6" ] )
+ # Bring down/up internal router-2
+ verifyRouterFailure( main, "bgp2", [ "rh5v4" ], [ "rh11v6", "rh5v6" ] )
+ lib.cleanup( main, copyKarafLog=False, removeHostComponent=True )
diff --git a/TestON/tests/USECASE/SegmentRouting/SRRouting/dependencies/SRRoutingTest.py b/TestON/tests/USECASE/SegmentRouting/SRRouting/dependencies/SRRoutingTest.py
index 0611abc..738b6b4 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRRouting/dependencies/SRRoutingTest.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRRouting/dependencies/SRRoutingTest.py
@@ -67,8 +67,10 @@
if static:
if ipv4:
lib.addStaticOnosRoute( main, "10.0.88.0/24", "10.0.1.1")
+ lib.addStaticOnosRoute( main, "10.0.88.0/24", "10.0.5.1")
if ipv6:
lib.addStaticOnosRoute( main, "2000::8700/120", "2000::101")
+ lib.addStaticOnosRoute( main, "2000::8700/120", "2000::501")
if countFlowsGroups:
lib.loadCount( main )
@@ -248,3 +250,18 @@
lib.checkFlowsGroupsFromFile( main )
# ping hosts
verifyPing( main, ipv4, ipv6, disconnected, internal, external )
+
+def verifyRouterFailure( main, routerToKill, affectedIpv4Hosts=[], affectedIpv6Hosts=[],
+ ipv4=True, ipv6=True, countFlowsGroups=False ):
+ """
+ Kill and recover a quagga router and verify connectivities to external hosts
+ """
+ from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+ lib.killRouter( main, routerToKill, 5 )
+ main.disconnectedExternalIpv4Hosts = affectedIpv4Hosts
+ main.disconnectedExternalIpv6Hosts = affectedIpv6Hosts
+ verify( main, ipv4, ipv6, True if (affectedIpv4Hosts or affectedIpv6Hosts) else False, False, True, countFlowsGroups )
+ lib.recoverRouter( main, routerToKill, 5 )
+ main.disconnectedExternalIpv4Hosts = []
+ main.disconnectedExternalIpv6Hosts = []
+ verify( main, ipv4, ipv6, False, False, True, countFlowsGroups )
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py b/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
index 5bd3bdd..7ec46f2 100644
--- a/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
+++ b/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
@@ -781,6 +781,40 @@
onfail="Failed to recover switch?" )
@staticmethod
+ def killRouter( main, router, sleep=None ):
+ """
+ Kill bgpd process on a quagga router
+ router: name of the router to be killed. E.g. "bgp1"
+ """
+ sleep = float( sleep )
+ main.step( "Kill " + str( router ) )
+ if hasattr( main, 'Mininet1' ):
+ main.Mininet1.handle.sendline( "px {}.stopProtocols()".format( router ) )
+ main.Mininet1.handle.expect( "mininet>" )
+ else:
+ # TODO: support killing router in physical network
+ pass
+ main.log.info( "Waiting %s seconds for router down to be discovered" % ( sleep ) )
+ time.sleep( sleep )
+
+ @staticmethod
+ def recoverRouter( main, router, sleep=None ):
+ """
+ Restart bgpd process on a quagga router
+ router: name of the router to be recovered. E.g. "bgp1"
+ """
+ sleep = float( sleep )
+ main.step( "Recovering " + str( router ) )
+ if hasattr( main, 'Mininet1' ):
+ main.Mininet1.handle.sendline( "px {}.startProtocols()".format( router ) )
+ main.Mininet1.handle.expect( "mininet>" )
+ else:
+ # TODO: support recovering router in physical network
+ pass
+ main.log.info( "Waiting %s seconds for router up to be discovered" % ( sleep ) )
+ time.sleep( sleep )
+
+ @staticmethod
def cleanup( main, copyKarafLog=True, removeHostComponent=False ):
"""
Stop Onos-cluster.
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/routinglib.py b/TestON/tests/USECASE/SegmentRouting/dependencies/routinglib.py
index 621b372..13a75e2 100644
--- a/TestON/tests/USECASE/SegmentRouting/dependencies/routinglib.py
+++ b/TestON/tests/USECASE/SegmentRouting/dependencies/routinglib.py
@@ -156,6 +156,14 @@
if self.defaultRoute:
self.cmd('ip route add default via %s' % self.defaultRoute)
+ def stopProtocols(self, **kwargs):
+ for p in self.protocols:
+ p.stop(**kwargs)
+
+ def startProtocols(self, **kwargs):
+ for p in self.protocols:
+ p.start(**kwargs)
+
def terminate(self, **kwargs):
self.cmd("ps ax | grep '%s' | awk '{print $1}' | xargs kill"
% (self.socket))
@@ -175,6 +183,12 @@
def config(self, **kwargs):
pass
+ def stop(self, **kwargs):
+ pass
+
+ def start(self, **kwargs):
+ pass
+
def terminate(self, **kwargs):
pass
@@ -199,6 +213,14 @@
self.qr.cmd('%s/bgpd -d -f %s -z %s -i %s'
% (QuaggaRouter.binDir, self.configFile, self.qr.socket, bgpdPidFile))
+ def stop(self, **kwargs):
+ self.qr.cmd('pkill -f %s' % self.configFile)
+
+ def start(self, **kwargs):
+ bgpdPidFile = '%s/bgpd%s.pid' % (self.qr.runDir, self.qr.name)
+ self.qr.cmd('%s/bgpd -d -f %s -z %s -i %s'
+ % (QuaggaRouter.binDir, self.configFile, self.qr.socket, bgpdPidFile))
+
def generateConfig(self):
conf = ConfigurationWriter(self.configFile)