Merge "[ONOS-7625] Refactor SRMulticast for complex test scenarios"
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index c61bf84..6342efc 100755
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -6241,7 +6241,7 @@
         Delete multicast sink(s) by calling 'mcast-host-delete' command
         sAddr: we can provide * for ASM or a specific address for SSM
         gAddr: specifies multicast group address
-        hosts: HostId of the sink e.g. "00:AA:00:00:01:05/40",
+        host: HostId of the sink e.g. "00:AA:00:00:01:05/40",
                will delete the route if not specified
         Returns main.TRUE if the mcast sink is deleted; Otherwise main.FALSE
         """
diff --git a/TestON/tests/USECASE/SegmentRouting/SRLinkFailure/dependencies/SRLinkFailFuncs.py b/TestON/tests/USECASE/SegmentRouting/SRLinkFailure/dependencies/SRLinkFailFuncs.py
index 1837cf4..1ed1c55 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRLinkFailure/dependencies/SRLinkFailFuncs.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRLinkFailure/dependencies/SRLinkFailFuncs.py
@@ -57,8 +57,8 @@
         # link failure
         run.killLink( main, self.switchOne, self.switchTwo, switches='{}'.format( switch ), links='{}'.format( link - 2 ) )
         run.pingAll( main, "CASE{}_Failure".format( caseNum ) )
-        run.restoreLink( main, self.switchOne, self.switchTwo, self.dpidOne,
-                         self.dpidTwo, self.portOne, self.portTwo, '{}'.format( switch ), '{}'.format( link ) )
+        run.restoreLink( main, self.switchOne, self.switchTwo, '{}'.format( switch ), '{}'.format( link ),
+                         True, self.dpidOne, self.dpidTwo, self.portOne, self.portTwo )
         run.pingAll( main, "CASE{}_Recovery".format( caseNum ) )
         # TODO Dynamic config of hosts in subnet
         # TODO Dynamic config of host not in subnet
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/SRMulticast.params b/TestON/tests/USECASE/SegmentRouting/SRMulticast/SRMulticast.params
index 6af0cde..f687a40 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/SRMulticast.params
+++ b/TestON/tests/USECASE/SegmentRouting/SRMulticast/SRMulticast.params
@@ -1,5 +1,5 @@
 <PARAMS>
-    <testcases>1,2,3,4,5,6,7,8,101,102,103,201</testcases>
+    <testcases>1,2,3,4,5,6,7,8,101,102,103,104,105,106,201,202,203,204,205,301,401,402,403,404</testcases>
 
     <GRAPH>
         <nodeCluster>Fabric</nodeCluster>
@@ -34,9 +34,9 @@
     </CTRL>
 
     <timers>
-        <LinkDiscovery>30</LinkDiscovery>
-        <SwitchDiscovery>30</SwitchDiscovery>
-        <OnosDiscovery>30</OnosDiscovery>
+        <LinkDiscovery>45</LinkDiscovery>
+        <SwitchDiscovery>45</SwitchDiscovery>
+        <OnosDiscovery>45</OnosDiscovery>
         <loadNetcfgSleep>5</loadNetcfgSleep>
         <startMininetSleep>60</startMininetSleep>
         <balanceMasterSleep>10</balanceMasterSleep>
@@ -44,7 +44,12 @@
     </timers>
 
     <SCAPY>
-        <HOSTNAMES>h1v4,h3v4,h4v4,h8v4,h1v6,h3v6,h4v6,h8v6</HOSTNAMES>
+        <HOSTNAMES>h3v4,h4v4,h8v4,h10v4,h1v6,h3v6</HOSTNAMES>
     </SCAPY>
 
+    <TOPO>
+        <switchNum>10</switchNum>
+        <linkNum>48</linkNum>
+    </TOPO>
+
 </PARAMS>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/SRMulticast.py b/TestON/tests/USECASE/SegmentRouting/SRMulticast/SRMulticast.py
index b2a7139..67614f4 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/SRMulticast.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRMulticast/SRMulticast.py
@@ -11,19 +11,16 @@
         Remove sink
         Verify flows and groups
         """
-        try:
-            from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import SRMulticastTest
-        except ImportError:
-            main.log.error( "SRMulticastTest not found. Exiting the test" )
-            main.cleanAndExit()
-        try:
-            main.funcs
-        except ( NameError, AttributeError ):
-            main.funcs = SRMulticastTest()
-        main.funcs.runTest( main,
-                            test_idx=1,
-                            onosNodes=3,
-                            description="Create a Multicast flow between a source and sink on the same dual-tor leaf" )
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Create a Multicast flow between a source and sink on the same dual-tor leaf" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=1, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifyMcastSinkRemoval( main, "ipv4", 0, False )
+        verifyMcastSourceRemoval( main, "ipv4", 0, False )
+        lib.cleanup( main, copyKarafLog=False )
 
     def CASE2( self, main ):
         """
@@ -34,19 +31,16 @@
         Remove sink
         Verify flows and groups
         """
-        try:
-            from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import SRMulticastTest
-        except ImportError:
-            main.log.error( "SRMulticastTest not found. Exiting the test" )
-            main.cleanAndExit()
-        try:
-            main.funcs
-        except ( NameError, AttributeError ):
-            main.funcs = SRMulticastTest()
-        main.funcs.runTest( main,
-                            test_idx=2,
-                            onosNodes=3,
-                            description="Create a Multicast flow between a source and sink on different dual-tor leaves" )
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Create a Multicast flow between a source and sink on different dual-tor leaves" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 1 ] } }
+        setupTest( main, test_idx=2, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifyMcastSinkRemoval( main, "ipv4", 1, False )
+        verifyMcastSourceRemoval( main, "ipv4", 0, False )
+        lib.cleanup( main, copyKarafLog=False )
 
     def CASE3( self, main ):
         """
@@ -57,19 +51,15 @@
         Remove sink
         Verify flows and groups
         """
-        try:
-            from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import SRMulticastTest
-        except ImportError:
-            main.log.error( "SRMulticastTest not found. Exiting the test" )
-            main.cleanAndExit()
-        try:
-            main.funcs
-        except ( NameError, AttributeError ):
-            main.funcs = SRMulticastTest()
-        main.funcs.runTest( main,
-                            test_idx=3,
-                            onosNodes=3,
-                            description="Create a Multicast flow between a source and sink on different leaves (sink on single-tor)" )
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Create a Multicast flow between a source and sink on different leaves (sink on single-tor)" )
+        main.mcastRoutes = { "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=3, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifyMcastRouteRemoval( main, "ipv6" )
+        lib.cleanup( main, copyKarafLog=False )
 
     def CASE4( self, main ):
         """
@@ -80,19 +70,17 @@
         Remove sinks
         Verify flows and groups
         """
-        try:
-            from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import SRMulticastTest
-        except ImportError:
-            main.log.error( "SRMulticastTest not found. Exiting the test" )
-            main.cleanAndExit()
-        try:
-            main.funcs
-        except ( NameError, AttributeError ):
-            main.funcs = SRMulticastTest()
-        main.funcs.runTest( main,
-                            test_idx=4,
-                            onosNodes=3,
-                            description="Combines CASE1 and CASE2" )
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Combines CASE1 and CASE2" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1 ] } }
+        setupTest( main, test_idx=4, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifyMcastSinkRemoval( main, "ipv4", 0, False )
+        verifyMcastSinkRemoval( main, "ipv4", 1, False )
+        verifyMcastSourceRemoval( main, "ipv4", 0, False )
+        lib.cleanup( main, copyKarafLog=False )
 
     def CASE5( self, main ):
         """
@@ -103,19 +91,17 @@
         Remove sinks
         Verify flows and groups
         """
-        try:
-            from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import SRMulticastTest
-        except ImportError:
-            main.log.error( "SRMulticastTest not found. Exiting the test" )
-            main.cleanAndExit()
-        try:
-            main.funcs
-        except ( NameError, AttributeError ):
-            main.funcs = SRMulticastTest()
-        main.funcs.runTest( main,
-                            test_idx=5,
-                            onosNodes=3,
-                            description="Combines CASE2 and CASE3" )
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Combines CASE2 and CASE3" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 1 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=5, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifyMcastRouteRemoval( main, "ipv6" )
+        verifyMcastSinkRemoval( main, "ipv4", 1, False )
+        verifyMcastSourceRemoval( main, "ipv4", 0, False )
+        lib.cleanup( main, copyKarafLog=False )
 
     def CASE6( self, main ):
         """
@@ -126,19 +112,17 @@
         Remove sinks
         Verify flows and groups
         """
-        try:
-            from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import SRMulticastTest
-        except ImportError:
-            main.log.error( "SRMulticastTest not found. Exiting the test" )
-            main.cleanAndExit()
-        try:
-            main.funcs
-        except ( NameError, AttributeError ):
-            main.funcs = SRMulticastTest()
-        main.funcs.runTest( main,
-                            test_idx=5,
-                            onosNodes=3,
-                            description="Combines CASE1 and CASE3" )
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Combines CASE1 and CASE3" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=6, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifyMcastRouteRemoval( main, "ipv6" )
+        verifyMcastSinkRemoval( main, "ipv4", 0, False )
+        verifyMcastSourceRemoval( main, "ipv4", 0, False )
+        lib.cleanup( main, copyKarafLog=False )
 
     def CASE7( self, main ):
         """
@@ -149,179 +133,372 @@
         Remove sinks
         Verify flows and groups
         """
-        try:
-            from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import SRMulticastTest
-        except ImportError:
-            main.log.error( "SRMulticastTest not found. Exiting the test" )
-            main.cleanAndExit()
-        try:
-            main.funcs
-        except ( NameError, AttributeError ):
-            main.funcs = SRMulticastTest()
-        main.funcs.runTest( main,
-                            test_idx=7,
-                            onosNodes=3,
-                            description="Combines CASE7 with route removal" )
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Combines CASE1, CASE2 and CASE3" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=7, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifyMcastRouteRemoval( main, "ipv6" )
+        verifyMcastSinkRemoval( main, "ipv4", 0, False )
+        verifyMcastSinkRemoval( main, "ipv4", 1, False )
+        verifyMcastSourceRemoval( main, "ipv4", 0, False )
+        lib.cleanup( main, copyKarafLog=False )
 
     def CASE8( self, main ):
         """
         Sets up 3 ONOS instances, start H-AGG topology
-        Combines CASE7 with route removal
+        Use all of the four sinks
+        Verify flows and groups
+        Verify traffic
+        Remove sinks
         Verify flows and groups
         """
-        try:
-            from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import SRMulticastTest
-        except ImportError:
-            main.log.error( "SRMulticastTest not found. Exiting the test" )
-            main.cleanAndExit()
-        try:
-            main.funcs
-        except ( NameError, AttributeError ):
-            main.funcs = SRMulticastTest()
-        main.funcs.runTest( main,
-                            test_idx=8,
-                            onosNodes=3,
-                            description="Combines CASE7 with route removal",
-                            removeRoute=True )
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Use all of the four sinks" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=8, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifyMcastRemoval( main )
+        lib.cleanup( main, copyKarafLog=False )
 
     def CASE101( self, main ):
         """
         Sets up 3 ONOS instances, start H-AGG topology
-        Combines CASE7 with a link failure (link ingress-spine)
+        Combines CASE8 with a link failure (link ingress-spine)
         Verify flows and groups
         Verify traffic
         """
-        try:
-            from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import SRMulticastTest
-        except ImportError:
-            main.log.error( "SRMulticastTest not found. Exiting the test" )
-            main.cleanAndExit()
-        try:
-            main.funcs
-        except ( NameError, AttributeError ):
-            main.funcs = SRMulticastTest()
-        main.funcs.runTest( main,
-                            test_idx=101,
-                            onosNodes=3,
-                            description="Combines CASE7 with a link failure (link ingress-spine)",
-                            linkFailure=True )
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Combines CASE8 with a link failure (link ingress-spine)" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=101, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifyLinkDown( main, [ "leaf2", "spine101" ], 4 )
+        verifyMcastRemoval( main )
+        lib.cleanup( main, copyKarafLog=False )
 
     def CASE102( self, main ):
         """
         Sets up 3 ONOS instances, start H-AGG topology
-        Combines CASE7 with a link failure (link spine-egress-dt-leaf)
+        Combines CASE8 with a link failure (link spine-egress-dt-leaf)
         Verify flows and groups
         Verify traffic
         """
-        try:
-            from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import SRMulticastTest
-        except ImportError:
-            main.log.error( "SRMulticastTest not found. Exiting the test" )
-            main.cleanAndExit()
-        try:
-            main.funcs
-        except ( NameError, AttributeError ):
-            main.funcs = SRMulticastTest()
-        main.funcs.runTest( main,
-                            test_idx=102,
-                            onosNodes=3,
-                            description="Combines CASE7 with a link failure (link spine-engress-dt-leaf)",
-                            linkFailure=True )
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Combines CASE8 with a link failure (link spine-engress-dt-leaf)" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=102, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifyLinkDown( main, [ "leaf5", "spine101" ], 4 )
+        verifyMcastRemoval( main )
+        lib.cleanup( main, copyKarafLog=False )
 
     def CASE103( self, main ):
         """
         Sets up 3 ONOS instances, start H-AGG topology
-        Combines CASE7 with a link failure (link spine-egress-st-leaf)
+        Combines CASE8 with a link failure (link spine-egress-st-leaf)
         Verify flows and groups
         Verify traffic
         """
-        try:
-            from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import SRMulticastTest
-        except ImportError:
-            main.log.error( "SRMulticastTest not found. Exiting the test" )
-            main.cleanAndExit()
-        try:
-            main.funcs
-        except ( NameError, AttributeError ):
-            main.funcs = SRMulticastTest()
-        main.funcs.runTest( main,
-                            test_idx=103,
-                            onosNodes=3,
-                            description="Combines CASE7 with a link failure (link spine-engress-st-leaf)",
-                            linkFailure=True )
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Combines CASE8 with a link failure (link spine-engress-st-leaf)" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=103, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifyLinkDown( main, [ "spine103", "spine101" ], 4 )
+        verifyMcastRemoval( main )
+        lib.cleanup( main, copyKarafLog=False )
+
+    def CASE104( self, main ):
+        """
+        Sets up 3 ONOS instances, start H-AGG topology
+        Combines CASE8 with a link failure (link spine-egress-st-leaf-2)
+        Verify flows and groups
+        Verify traffic
+        """
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Combines CASE8 with a link failure (link spine-engress-st-leaf-2)" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=104, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifyLinkDown( main, [ "leaf4", "spine101" ], 4 )
+        verifyMcastRemoval( main )
+        lib.cleanup( main, copyKarafLog=False )
+
+    def CASE105( self, main ):
+        """
+        Sets up 3 ONOS instances, start H-AGG topology
+        Combines CASE8 with a link failure (link dt-leaf-sink)
+        Verify flows and groups
+        Verify traffic
+        """
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Combines CASE8 with a link failure (link dt-leaf-sink)" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=105, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifyLinkDown( main, [ "leaf2", "h4v4" ], 0 )
+        verifyMcastRemoval( main )
+        lib.cleanup( main, copyKarafLog=False )
+
+    def CASE106( self, main ):
+        """
+        Sets up 3 ONOS instances, start H-AGG topology
+        Combines CASE8 with a link failure (link dt-leaf-sink-2)
+        Verify flows and groups
+        Verify traffic
+        """
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Combines CASE8 with a link failure (link dt-leaf-sink-2)" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=106, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifyLinkDown( main, [ "leaf5", "h10v4" ], 0 )
+        verifyMcastRemoval( main )
+        lib.cleanup( main, copyKarafLog=False )
 
     def CASE201( self, main ):
         """
         Sets up 3 ONOS instances, start H-AGG topology
-        Combines CASE7 with spine failure
+        Combines CASE8 with spine failure
         Verify flows and groups
         Verify traffic
         """
-        try:
-            from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import SRMulticastTest
-        except ImportError:
-            main.log.error( "SRMulticastTest not found. Exiting the test" )
-            main.cleanAndExit()
-        try:
-            main.funcs
-        except ( NameError, AttributeError ):
-            main.funcs = SRMulticastTest()
-        main.funcs.runTest( main,
-                            test_idx=201,
-                            onosNodes=3,
-                            description="Combines CASE7 with spine failure",
-                            switchFailure=True )
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Combines CASE8 with spine failure" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=201, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifySwitchDown( main, "spine101", 18 )
+        verifySwitchDown( main, "spine102", 18 )
+        verifyMcastRemoval( main, removeDHT1=False )
+        lib.cleanup( main, copyKarafLog=False )
 
     def CASE202( self, main ):
         """
         Sets up 3 ONOS instances, start H-AGG topology
-        Combines CASE7 with ingress failure and recovery
+        Combines CASE8 with ingress failure and recovery
         Verify flows and groups are removed (failure)
         Verify flows and groups (recovery)
         Verify traffic (recovery)
         """
-        pass
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Combines CASE8 with ingress failure and recovery" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=202, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifySwitchDown( main, "leaf2", 10, { "ipv4": False, "ipv6": False } )
+        verifyMcastRemoval( main, removeDHT1=False )
+        lib.cleanup( main, copyKarafLog=False )
 
     def CASE203( self, main ):
         """
         Sets up 3 ONOS instances, start H-AGG topology
-        Combines CASE7 with egress-dt-leaf failure and recovery
+        Combines CASE8 with egress-dt-leaf failure and recovery
         Verify flows and groups are removed for the failing sink (failure)
         Verify traffic on remaining sinks (failure)
         Verify flows and groups (recovery)
         Verify traffic (recovery)
         """
-        pass
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Combines CASE8 with egress-dt-leaf failure and recovery" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=203, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifySwitchDown( main, "leaf5", 10 )
+        verifyMcastRemoval( main, removeDHT1=False )
+        lib.cleanup( main, copyKarafLog=False )
 
     def CASE204( self, main ):
         """
         Sets up 3 ONOS instances, start H-AGG topology
-        Combines CASE7 with egress-st-leaf failure and recovery
+        Combines CASE8 with egress-st-leaf failure and recovery
         Verify flows and groups are removed for the failing sink (failure)
         Verify traffic on remaining sinks (failure)
         Verify flows and groups (recovery)
         Verify traffic (recovery)
         """
-        pass
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Combines CASE8 with egress-st-leaf failure and recovery" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=204, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifySwitchDown( main, "leaf4", 10, { "ipv4": [ True, False, True ], "ipv6": True } )
+        verifyMcastRemoval( main, removeDHT1=False )
+        lib.cleanup( main, copyKarafLog=False )
 
     def CASE205( self, main ):
         """
         Sets up 3 ONOS instances, start H-AGG topology
-        Combines CASE7 with egress leaves failure and recovery
+        Combines CASE8 with egress leaves failure and recovery
         Verify flows and groups are removed for the failing sinks (failure)
         Verify traffic on remaining sink (failure)
         Verify flows and groups (recovery)
         Verify traffic (recovery)
         """
-        pass
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Combines CASE8 with leaves failure and recovery" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=205, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifySwitchDown( main, [ "leaf1", "leaf3", "leaf4", "leaf5" ], 32, { "ipv4": [ True, False, False ], "ipv6": False } )
+        verifyMcastRemoval( main, removeDHT1=False )
+        lib.cleanup( main, copyKarafLog=False )
 
     def CASE301( self, main ):
         """
         Sets up 3 ONOS instances, start H-AGG topology
-        Combines CASE7 with ONOS failure and recovery
+        Combines CASE8 with ONOS failure and recovery
         Verify flows and groups (failure)
         Verify traffic (failure)
         Verify flows and groups (recovery)
         Verify traffic (recovery)
         """
-        pass
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Combines CASE8 with leaves failure and recovery" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=205, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifyOnosDown( main )
+        verifyMcastRemoval( main, removeDHT1=False )
+        lib.cleanup( main, copyKarafLog=False )
+
+    def CASE401( self, main ):
+        """
+        Extends MCAST105
+        Create sinks and verify traffic is working
+        Bring down host port and verify traffic is still working for all sinks
+        Bring up host port again and start ping from DTH1 to STS
+        Verify host has both location and stop the ping
+        Kill LEAFA and verify traffic is still working for all sinks
+        Remove IPv6 route
+        Remove DTH2 sink
+        Remove STH2 sink
+        Remove STS
+        """
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Extends MCAST105" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=401, onosNodes=3 )
+        verifyMcastRoutes( main )
+        #TODO: Verify host has both locations
+        # Verify killing one link of dual-homed host h4
+        verifyLinkDown( main, [ "leaf2", "h4v4" ], 0 )
+        verifyLinkDown( main, [ "leaf3", "h4v4" ], 0 )
+        # Verify killing one link of dual-homed host h10
+        verifyLinkDown( main, [ "leaf4", "h10v4" ], 0 )
+        verifyLinkDown( main, [ "leaf5", "h10v4" ], 0 )
+        verifySwitchDown( main, "leaf3", 10 )
+        verifyMcastRemoval( main, removeDHT1=False )
+        lib.cleanup( main, copyKarafLog=False )
+
+    def CASE402( self, main ):
+        """
+        No downstream path for DTH2
+        Create sinks and verify traffic is working
+        Kill all up-links of the LEAFB and verify traffic is still working
+        Remove IPv6 route
+        Remove DTH2 sink
+        Remove STH2 sink
+        Remove STS
+        """
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "No downstream path for DTH2" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=402, onosNodes=3 )
+        verifyMcastRoutes( main )
+        verifyLinkDown( main, [ [ "leaf5", "spine101" ], [ "leaf5", "spine102" ] ], 8 )
+        verifyMcastRemoval( main, removeDHT1=False )
+        lib.cleanup( main, copyKarafLog=False )
+
+    def CASE403( self, main ):
+        """
+        No downstream path for DTH1
+        Create sinks and verify traffic is working
+        Bring down host port and verify traffic is still working for all sinks
+        Bring up host port again and start ping from DTH1 to STS
+        Verify host has both location and stop the ping
+        Kill all up-links of the LEAFA and verify traffic is still working
+        Remove IPv6 route
+        Remove DTH2 sink
+        Remove STH2 sink
+        Remove STS
+        """
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "No downstream path for DTH1" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=403, onosNodes=3 )
+        verifyMcastRoutes( main )
+        # Verify killing one link of dual-homed host h4
+        verifyLinkDown( main, [ "leaf2", "h4v4" ], 0 )
+        verifyLinkDown( main, [ "leaf3", "h4v4" ], 0 )
+        # Verify killing one link of dual-homed host h10
+        verifyLinkDown( main, [ "leaf4", "h10v4" ], 0 )
+        verifyLinkDown( main, [ "leaf5", "h10v4" ], 0 )
+        verifyLinkDown( main, [ [ "leaf3", "spine101" ], [ "leaf3", "spine102" ] ], 8 )
+        verifyMcastRemoval( main, removeDHT1=False )
+        lib.cleanup( main, copyKarafLog=False )
+
+    def CASE404( self, main ):
+        """
+        Extends MCAST 403
+        Create sinks and verify traffic is working
+        Bring down host port and verify traffic is still working for all sinks
+        Bring up host port again and start ping from DTH1 to STS
+        Verify host has both location and stop the ping
+        Kill up-links of the LEAFA towards SPINEA, kill up-links of the SOURCE LEAF towards SPINEC and verify traffic is still working for all sinks
+        Remove IPv6 route
+        Remove DTH2 sink
+        Remove STH2 sink
+        Remove STS
+        """
+        import time
+        from tests.USECASE.SegmentRouting.SRMulticast.dependencies.SRMulticastTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Extends MCASR 403" )
+        main.mcastRoutes = { "ipv4": { "src": [ 0 ], "dst": [ 0, 1, 2 ] }, "ipv6": { "src": [ 0 ], "dst": [ 0 ] } }
+        setupTest( main, test_idx=404, onosNodes=3 )
+        verifyMcastRoutes( main )
+        # Verify killing one link of dual-homed host h4
+        verifyLinkDown( main, [ "leaf2", "h4v4" ], 0 )
+        verifyLinkDown( main, [ "leaf3", "h4v4" ], 0 )
+        # Verify killing one link of dual-homed host h10
+        verifyLinkDown( main, [ "leaf4", "h10v4" ], 0 )
+        verifyLinkDown( main, [ "leaf5", "h10v4" ], 0 )
+        verifyLinkDown( main, [ [ "leaf3", "spine101" ], [ "leaf2", "spine102" ] ], 8 )
+        verifyMcastRemoval( main, removeDHT1=False )
+        lib.cleanup( main, copyKarafLog=False )
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/SRMulticastTest.py b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/SRMulticastTest.py
index 42e646a..30b7e92 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/SRMulticastTest.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/SRMulticastTest.py
@@ -20,96 +20,163 @@
 """
 
 import time
-from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as run
 
-class SRMulticastTest ():
+def setupTest( main, test_idx, onosNodes ):
+    from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+    skipPackage = False
+    init = False
+    if not hasattr( main, "apps" ):
+        init = True
+        lib.initTest( main )
+    # Skip onos packaging if the cluster size stays the same
+    if not init and onosNodes == main.Cluster.numCtrls:
+        skipPackage = True
 
-    def __init__( self ):
-        self.default = ''
-        self.switchNames = [ "leaf205", "leaf206", "spine227", "spine228" ]
+    main.resultFileName = "CASE%03d" % test_idx
+    main.Cluster.setRunningNode( onosNodes )
+    lib.installOnos( main, skipPackage=skipPackage, cliSleep=5 )
+    # Load configuration files
+    main.step( "Load configurations" )
+    main.cfgName = "TEST_CONFIG_ipv4=1_ipv6=1_dhcp=1_routers=1"
+    lib.loadJson( main )
+    time.sleep( float( main.params[ "timers" ][ "loadNetcfgSleep" ] ) )
+    main.cfgName = "common"
+    lib.loadMulticastConfig( main )
 
-    def runTest( self, main, test_idx, onosNodes, description, removeRoute=False, linkFailure=False, switchFailure=False ):
-        skipPackage = False
-        init = False
-        if not hasattr( main, 'apps' ):
-            init = True
-            run.initTest( main )
-        # Skip onos packaging if the cluster size stays the same
-        if not init and onosNodes == main.Cluster.numCtrls:
-            skipPackage = True
+    if hasattr( main, "Mininet1" ):
+        # Run the test with Mininet
+        mininet_args = " --dhcp=1 --routers=1 --ipv6=1 --ipv4=1"
+        lib.startMininet( main, main.params[ "DEPENDENCY" ][ "topology" ], args=mininet_args )
+        time.sleep( float( main.params[ "timers" ][ "startMininetSleep" ] ) )
+    else:
+        # Run the test with physical devices
+        lib.connectToPhysicalNetwork( main, self.switchNames )
+        # Check if the devices are up
+        lib.checkDevices( main, switches=len( self.switchNames ) )
 
-        main.case( '%s, ONOS cluster size: %s' % ( description, onosNodes ) )
+    # Create scapy components
+    lib.startScapyHosts( main )
 
-        main.resultFileName = 'CASE%03d' % test_idx
-        main.Cluster.setRunningNode( onosNodes )
-        run.installOnos( main, skipPackage=skipPackage, cliSleep=5 )
-        # Load configuration files
-        main.step("Load configurations")
-        main.cfgName = 'TEST_CONFIG_ipv4=1_ipv6=1_dhcp=1_routers=1'
-        run.loadJson( main )
-        main.cfgName = 'CASE%03d' % test_idx
-        run.loadMulticastConfig( main )
-        if linkFailure:
-            run.loadLinkFailureChart( main )
-        if switchFailure:
-            run.loadSwitchFailureChart( main )
-        time.sleep( float( main.params[ 'timers' ][ 'loadNetcfgSleep' ] ) )
+def verifyMcastRoutes( main ):
+    """
+    Install multicast routes and check traffic
+    """
+    from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+    for routeName in main.mcastRoutes.keys():
+        main.step( "Verify {} multicast route".format( routeName ) )
+        installMcastRoute( main, routeName )
+        lib.verifyMulticastTraffic( main, routeName, True )
 
-        if hasattr( main, 'Mininet1' ):
-            # Run the test with Mininet
-            mininet_args = ' --dhcp=1 --routers=1 --ipv6=1 --ipv4=1'
-            run.startMininet( main, main.params['DEPENDENCY']['topology'], args=mininet_args )
-            time.sleep( float( main.params[ 'timers' ][ 'startMininetSleep' ] ) )
-        else:
-            # Run the test with physical devices
-            run.connectToPhysicalNetwork( main, self.switchNames )
-            # Check if the devices are up
-            run.checkDevices( main, switches=len( self.switchNames ) )
+def installMcastRoute( main, routeName ):
+    """
+    Install a multicast route
+    """
+    routeData = main.multicastConfig[ routeName ]
+    src = main.mcastRoutes[ routeName ][ "src" ]
+    dst = main.mcastRoutes[ routeName ][ "dst" ]
+    main.Cluster.active( 0 ).CLI.mcastHostJoin( routeData[ "src" ][ src[ 0 ] ][ "ip" ], routeData[ "group" ],
+                                                [ routeData[ "src" ][ i ][ "port" ] for i in src ],
+                                                [ routeData[ "dst" ][ i ][ "id" ] for i in dst ] )
+    time.sleep( float( main.params[ "timers" ][ "mcastSleep" ] ) )
 
-        # Create scapy components
-        run.startScapyHosts( main )
+def verifyMcastRouteRemoval( main, routeName ):
+    """
+    Verify removal of a multicast route
+    """
+    routeData = main.multicastConfig[ routeName ]
+    main.step( "Verify removal of {} route".format( routeName ) )
+    main.Cluster.active( 0 ).CLI.mcastHostDelete( routeData[ "src" ][ 0 ][ "ip" ], routeData[ "group" ] )
+    # TODO: verify the deletion
 
-        for entry in main.multicastConfig:
-            main.step("Verify adding multicast route with group IP {}".format(entry["group"]))
-            # Create a multicast route
-            main.Cluster.active( 0 ).CLI.mcastHostJoin( entry["sIP"], entry["group"], entry["sPorts"], entry["dHosts"] )
-            time.sleep( float( main.params[ 'timers' ][ 'mcastSleep' ] ) )
-            # Check the flows against the devices
-            # run.checkFlows( main, minFlowCount=2, sleep=5 )
-            # Verify multicast traffic
-            run.verifyMulticastTraffic( main, entry, True, skipOnFail=True )
+def verifyMcastSinkRemoval( main, routeName, sinkIndex, expect ):
+    """
+    Verify removal of a multicast sink
+    """
+    from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+    routeData = main.multicastConfig[ routeName ]
+    sinkId = routeData[ "dst" ][ sinkIndex ][ "id" ]
+    main.step( "Verify removal of {} sink {}".format( routeName, sinkId ) )
+    main.Cluster.active( 0 ).CLI.mcastHostDelete( routeData[ "src" ][ 0 ][ "ip" ], routeData[ "group" ], sinkId )
+    time.sleep( float( main.params[ "timers" ][ "mcastSleep" ] ) )
+    lib.verifyMulticastTraffic( main, routeName, expect )
 
-            # Test switch failures
-            if switchFailure:
-                for switch, expected in main.switchFailureChart.items():
-                    run.killSwitch( main, switch, expected['switches_after_failure'], expected['links_after_failure'] )
-                    run.verifyMulticastTraffic( main, entry, True, skipOnFail=True )
+def verifyMcastSourceRemoval( main, routeName, sourceIndex, expect ):
+    """
+    Verify removal of a multicast source
+    """
+    from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+    routeData = main.multicastConfig[ routeName ]
+    sourcePort = [ routeData[ "src" ][ sourceIndex ][ "port" ] ]
+    main.step( "Verify removal of {} source {}".format( routeName, sourcePort ) )
+    main.Cluster.active( 0 ).CLI.mcastSourceDelete( routeData[ "src" ][ 0 ][ "ip" ], routeData[ "group" ], sourcePort )
+    time.sleep( float( main.params[ "timers" ][ "mcastSleep" ] ) )
+    lib.verifyMulticastTraffic( main, routeName, expect )
 
-                    run.recoverSwitch( main, switch, expected['switches_before_failure'], expected['links_before_failure'] )
-                    run.verifyMulticastTraffic( main, entry, True, skipOnFail=True )
+def verifyMcastRemoval( main, removeDHT1=True ):
+    """
+    Verify removal of IPv6 route, IPv4 sinks and IPv4 source
+    """
+    from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+    verifyMcastRouteRemoval( main, "ipv6" )
+    if removeDHT1:
+        verifyMcastSinkRemoval( main, "ipv4", 0, [ False, True, True ] )
+        verifyMcastSinkRemoval( main, "ipv4", 1, [ False, False, True ] )
+    else:
+        verifyMcastSinkRemoval( main, "ipv4", 2, [ True, True, False ] )
+        verifyMcastSinkRemoval( main, "ipv4", 1, [ True, False, False ] )
+    verifyMcastSourceRemoval( main, "ipv4", 0, False )
 
-            # Test link failures
-            if linkFailure:
-                for link_batch_name, info in main.linkFailureChart.items():
-                    linksToRemove = info['links'].values()
-                    linksBefore = info['links_before']
-                    linksAfter = info['links_after']
+def verifyLinkDown( main, link, affectedLinkNum, expectList={ "ipv4": True, "ipv6": True } ):
+    """
+    Kill a batch of links and verify traffic
+    Restore the links and verify traffic
+    """
+    from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+    link = link if ( isinstance( link, list ) and isinstance( link[ 0 ], list ) ) else [ link ]
+    # Kill the link(s)
+    lib.killLinkBatch( main, link, int( main.params[ "TOPO" ][ "linkNum" ] ) - affectedLinkNum, int( main.params[ "TOPO" ][ "switchNum" ] ) )
+    for routeName in expectList.keys():
+        lib.verifyMulticastTraffic( main, routeName, expectList[ routeName ] )
+    # Restore the link(s)
+    lib.restoreLinkBatch( main, link, int( main.params[ "TOPO" ][ "linkNum" ] ), int( main.params[ "TOPO" ][ "switchNum" ] ) )
+    for routeName in expectList.keys():
+        lib.verifyMulticastTraffic( main, routeName, True )
 
-                    run.killLinkBatch( main, linksToRemove, linksAfter, switches=10 )
-                    run.verifyMulticastTraffic( main, entry, True, skipOnFail=True )
+def verifySwitchDown( main, switchName, affectedLinkNum, expectList={ "ipv4": True, "ipv6": True } ):
+    """
+    Kill a batch of switches and verify traffic
+    Recover the swithces and verify traffic
+    """
+    from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+    switchName = switchName if isinstance( switchName, list ) else [ switchName ]
+    # Kill the switch(es)
+    lib.killSwitch( main, switchName, int( main.params[ "TOPO" ][ "switchNum" ] ) - len( switchName ), int( main.params[ "TOPO" ][ "linkNum" ] ) - affectedLinkNum )
+    for routeName in expectList.keys():
+        lib.verifyMulticastTraffic( main, routeName, expectList[ routeName ] )
+    # Recover the switch(es)
+    lib.recoverSwitch( main, switchName, int( main.params[ "TOPO" ][ "switchNum" ] ), int( main.params[ "TOPO" ][ "linkNum" ] ) )
+    for routeName in expectList.keys():
+        lib.verifyMulticastTraffic( main, routeName, True )
 
-                    run.restoreLinkBatch( main, linksToRemove, linksBefore, switches=10 )
-                    run.verifyMulticastTraffic( main, entry, True, skipOnFail=True )
-
-            if removeRoute:
-                main.step("Verify deleting multicast route with group IP {}".format(entry["group"]))
-                # delete a multicast route
-                main.Cluster.active( 0 ).CLI.mcastHostDelete( entry["sIP"], entry["group"] )
-                time.sleep( float( main.params[ 'timers' ][ 'mcastSleep' ] ) )
-                # Check the flows against the devices
-                # run.checkFlows( main, minFlowCount=2, sleep=5 )
-                # Verify multicast traffic (traffic check is expected to fail)
-                run.verifyMulticastTraffic( main, entry, False, skipOnFail=True )
-
-        # Clean up the environment
-        run.cleanup( main, copyKarafLog=False )
+def verifyOnosDown( main, expectList={ "ipv4": True, "ipv6": True } ):
+    """
+    Kill and recover ONOS instances Sequencially and check traffic
+    """
+    from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+    import json
+    numCtrls = len( main.Cluster.runningNodes )
+    links = len( json.loads( main.Cluster.next().links() ) )
+    switches = len( json.loads( main.Cluster.next().devices() ) )
+    for ctrl in xrange( numCtrls ):
+        # Kill node
+        lib.killOnos( main, [ ctrl ], switches, links, ( numCtrls - 1 ) )
+        main.Cluster.active(0).CLI.balanceMasters()
+        time.sleep( float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
+        for routeName in expectList.keys():
+            lib.verifyMulticastTraffic( main, routeName, True )
+        # Recover node
+        lib.recoverOnos( main, [ ctrl ], switches, links, numCtrls )
+        main.Cluster.active(0).CLI.balanceMasters()
+        time.sleep( float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
+        for routeName in expectList.keys():
+            lib.verifyMulticastTraffic( main, routeName, True )
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/linkFailure/CASE101.linkFailureChart b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/linkFailure/CASE101.linkFailureChart
deleted file mode 100644
index 8a9e052..0000000
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/linkFailure/CASE101.linkFailureChart
+++ /dev/null
@@ -1,8 +0,0 @@
-{
-    "link_batch_1" : { "links" : { "link1" : ["leaf2", "spine101"] },
-                       "links_before" : 48,
-                       "links_after" : 44 },
-    "link_batch_2" : { "links" : { "link1" : ["leaf2", "spine102"] },
-                       "links_before" : 48,
-                       "links_after" : 44 }
-}
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/linkFailure/CASE102.linkFailureChart b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/linkFailure/CASE102.linkFailureChart
deleted file mode 100644
index f102be4..0000000
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/linkFailure/CASE102.linkFailureChart
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "link_batch_1" : { "links" : { "link1" : ["leaf4", "spine101"] },
-                       "links_before" : 48,
-                       "links_after" : 44 },
-    "link_batch_2" : { "links" : { "link1" : ["leaf4", "spine102"] },
-                       "links_before" : 48,
-                       "links_after" : 44 }
-}
-
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/linkFailure/CASE103.linkFailureChart b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/linkFailure/CASE103.linkFailureChart
deleted file mode 100644
index 8041a05..0000000
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/linkFailure/CASE103.linkFailureChart
+++ /dev/null
@@ -1,9 +0,0 @@
-{
-    "link_batch_1" : { "links" : { "link1" : ["spine103", "spine101"] },
-                       "links_before" : 48,
-                       "links_after" : 46 },
-    "link_batch_2" : { "links" : { "link1" : ["spine104", "spine102"] },
-                       "links_before" : 48,
-                       "links_after" : 46 }
-}
-
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE001.multicastConfig b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE001.multicastConfig
deleted file mode 100644
index 990507e..0000000
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE001.multicastConfig
+++ /dev/null
@@ -1,48 +0,0 @@
-[
-    {
-        "ipVersion": 4,
-        "sIP": "10.2.0.1",
-        "group": "224.2.0.1",
-        "sPorts": ["of:0000000000000002/9"],
-        "dHosts": ["00:AA:00:00:00:03/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v4",
-                "interface": "h3v4-eth0",
-                "Ether": "01:00:5e:02:00:01",
-                "UDP": 40051,
-                "filter": "ip multicast and dst host 224.2.0.1 and udp dst port 40051",
-                "packet": "dst=01:00:5e:02:00:01 src=00:aa:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v4",
-                    "interface": "h4v4-bond0"
-                }
-            ]
-        }
-    },
-    {
-        "ipVersion": 6,
-        "sIP": "1002::3fe",
-        "group": "ff08::3fe",
-        "sPorts": ["of:0000000000000002/6"],
-        "dHosts": ["00:BB:00:00:00:03/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v6",
-                "interface": "h3v6-eth0",
-                "Ether": "33:33:00:00:03:fe",
-                "UDP": 40051,
-                "filter": "ip6 multicast and dst host ff08::3fe and udp dst port 40051",
-                "packet": "dst=33:33:00:00:03:fe src=00:bb:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v6",
-                    "interface": "h4v6-bond0"
-                }
-            ]
-        }
-    }
-]
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE002.multicastConfig b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE002.multicastConfig
deleted file mode 100644
index 14f770e..0000000
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE002.multicastConfig
+++ /dev/null
@@ -1,46 +0,0 @@
-[
-    {
-        "ipVersion": 4,
-        "sIP": "10.2.0.1",
-        "group": "224.2.0.1",
-        "sPorts": ["of:0000000000000002/9"],
-        "dHosts": ["00:AA:00:00:00:06/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v4",
-                "interface": "h3v4-eth0",
-                "Ether": "01:00:5e:02:00:01",
-                "UDP": 40051,
-                "filter": "ip multicast and dst host 224.2.0.1 and udp dst port 40051",
-                "packet": "dst=01:00:5e:02:00:01 src=00:aa:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h8v4"
-                }
-            ]
-        }
-    },
-    {
-        "ipVersion": 6,
-        "sIP": "1002::3fe",
-        "group": "ff08::3fe",
-        "sPorts": ["of:0000000000000002/6"],
-        "dHosts": ["00:BB:00:00:00:06/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v6",
-                "interface": "h3v6-eth0",
-                "Ether": "33:33:00:00:03:fe",
-                "UDP": 40051,
-                "filter": "ip6 multicast and dst host ff08::3fe and udp dst port 40051",
-                "packet": "dst=33:33:00:00:03:fe src=00:bb:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h8v6"
-                }
-            ]
-        }
-    }
-]
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE003.multicastConfig b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE003.multicastConfig
deleted file mode 100644
index ffd2e6c..0000000
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE003.multicastConfig
+++ /dev/null
@@ -1,46 +0,0 @@
-[
-    {
-        "ipVersion": 4,
-        "sIP": "10.2.0.1",
-        "group": "224.2.0.1",
-        "sPorts": ["of:0000000000000002/9"],
-        "dHosts": ["00:AA:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v4",
-                "interface": "h3v4-eth0",
-                "Ether": "01:00:5e:02:00:01",
-                "UDP": 40051,
-                "filter": "ip multicast and dst host 224.2.0.1 and udp dst port 40051",
-                "packet": "dst=01:00:5e:02:00:01 src=00:aa:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h1v4"
-                }
-            ]
-        }
-    },
-    {
-        "ipVersion": 6,
-        "sIP": "1002::3fe",
-        "group": "ff08::3fe",
-        "sPorts": ["of:0000000000000002/6"],
-        "dHosts": ["00:BB:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v6",
-                "interface": "h3v6-eth0",
-                "Ether": "33:33:00:00:03:fe",
-                "UDP": 40051,
-                "filter": "ip6 multicast and dst host ff08::3fe and udp dst port 40051",
-                "packet": "dst=33:33:00:00:03:fe src=00:bb:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h1v6"
-                }
-            ]
-        }
-    }
-]
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE004.multicastConfig b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE004.multicastConfig
deleted file mode 100644
index 8fc69d1..0000000
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE004.multicastConfig
+++ /dev/null
@@ -1,54 +0,0 @@
-[
-    {
-        "ipVersion": 4,
-        "sIP": "10.2.0.1",
-        "group": "224.2.0.1",
-        "sPorts": ["of:0000000000000002/9"],
-        "dHosts": ["00:AA:00:00:00:03/None", "00:AA:00:00:00:06/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v4",
-                "interface": "h3v4-eth0",
-                "Ether": "01:00:5e:02:00:01",
-                "UDP": 40051,
-                "filter": "ip multicast and dst host 224.2.0.1 and udp dst port 40051",
-                "packet": "dst=01:00:5e:02:00:01 src=00:aa:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v4",
-                    "interface": "h4v4-bond0"
-                },
-                {
-                    "host": "h8v4"
-                }
-            ]
-        }
-    },
-    {
-        "ipVersion": 6,
-        "sIP": "1002::3fe",
-        "group": "ff08::3fe",
-        "sPorts": ["of:0000000000000002/6"],
-        "dHosts": ["00:BB:00:00:00:03/None", "00:BB:00:00:00:06/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v6",
-                "interface": "h3v6-eth0",
-                "Ether": "33:33:00:00:03:fe",
-                "UDP": 40051,
-                "filter": "ip6 multicast and dst host ff08::3fe and udp dst port 40051",
-                "packet": "dst=33:33:00:00:03:fe src=00:bb:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v6",
-                    "interface": "h4v6-bond0"
-                },
-                {
-                    "host": "h8v6"
-                }
-            ]
-        }
-    }
-]
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE005.multicastConfig b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE005.multicastConfig
deleted file mode 100644
index 7d089ae..0000000
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE005.multicastConfig
+++ /dev/null
@@ -1,52 +0,0 @@
-[
-    {
-        "ipVersion": 4,
-        "sIP": "10.2.0.1",
-        "group": "224.2.0.1",
-        "sPorts": ["of:0000000000000002/9"],
-        "dHosts": ["00:AA:00:00:00:06/None", "00:AA:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v4",
-                "interface": "h3v4-eth0",
-                "Ether": "01:00:5e:02:00:01",
-                "UDP": 40051,
-                "filter": "ip multicast and dst host 224.2.0.1 and udp dst port 40051",
-                "packet": "dst=01:00:5e:02:00:01 src=00:aa:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h8v4"
-                },
-                {
-                    "host": "h1v4"
-                }
-            ]
-        }
-    },
-    {
-        "ipVersion": 6,
-        "sIP": "1002::3fe",
-        "group": "ff08::3fe",
-        "sPorts": ["of:0000000000000002/6"],
-        "dHosts": ["00:BB:00:00:00:06/None", "00:BB:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v6",
-                "interface": "h3v6-eth0",
-                "Ether": "33:33:00:00:03:fe",
-                "UDP": 40051,
-                "filter": "ip6 multicast and dst host ff08::3fe and udp dst port 40051",
-                "packet": "dst=33:33:00:00:03:fe src=00:bb:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h8v6"
-                },
-                {
-                    "host": "h1v6"
-                }
-            ]
-        }
-    }
-]
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE006.multicastConfig b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE006.multicastConfig
deleted file mode 100644
index 9c1029a..0000000
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE006.multicastConfig
+++ /dev/null
@@ -1,54 +0,0 @@
-[
-    {
-        "ipVersion": 4,
-        "sIP": "10.2.0.1",
-        "group": "224.2.0.1",
-        "sPorts": ["of:0000000000000002/9"],
-        "dHosts": ["00:AA:00:00:00:03/None", "00:AA:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v4",
-                "interface": "h3v4-eth0",
-                "Ether": "01:00:5e:02:00:01",
-                "UDP": 40051,
-                "filter": "ip multicast and dst host 224.2.0.1 and udp dst port 40051",
-                "packet": "dst=01:00:5e:02:00:01 src=00:aa:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v4",
-                    "interface": "h4v4-bond0"
-                },
-                {
-                    "host": "h1v4"
-                }
-            ]
-        }
-    },
-    {
-        "ipVersion": 6,
-        "sIP": "1002::3fe",
-        "group": "ff08::3fe",
-        "sPorts": ["of:0000000000000002/6"],
-        "dHosts": ["00:BB:00:00:00:03/None", "00:BB:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v6",
-                "interface": "h3v6-eth0",
-                "Ether": "33:33:00:00:03:fe",
-                "UDP": 40051,
-                "filter": "ip6 multicast and dst host ff08::3fe and udp dst port 40051",
-                "packet": "dst=33:33:00:00:03:fe src=00:bb:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v6",
-                    "interface": "h4v6-bond0"
-                },
-                {
-                    "host": "h1v6"
-                }
-            ]
-        }
-    }
-]
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE007.multicastConfig b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE007.multicastConfig
deleted file mode 100644
index 218ed4d..0000000
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE007.multicastConfig
+++ /dev/null
@@ -1,60 +0,0 @@
-[
-    {
-        "ipVersion": 4,
-        "sIP": "10.2.0.1",
-        "group": "224.2.0.1",
-        "sPorts": ["of:0000000000000002/9"],
-        "dHosts": ["00:AA:00:00:00:03/None", "00:AA:00:00:00:06/None", "00:AA:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v4",
-                "interface": "h3v4-eth0",
-                "Ether": "01:00:5e:02:00:01",
-                "UDP": 40051,
-                "filter": "ip multicast and dst host 224.2.0.1 and udp dst port 40051",
-                "packet": "dst=01:00:5e:02:00:01 src=00:aa:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v4",
-                    "interface": "h4v4-bond0"
-                },
-                {
-                    "host": "h8v4"
-                },
-                {
-                    "host": "h1v4"
-                }
-            ]
-        }
-    },
-    {
-        "ipVersion": 6,
-        "sIP": "1002::3fe",
-        "group": "ff08::3fe",
-        "sPorts": ["of:0000000000000002/6"],
-        "dHosts": ["00:BB:00:00:00:03/None", "00:BB:00:00:00:06/None", "00:BB:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v6",
-                "interface": "h3v6-eth0",
-                "Ether": "33:33:00:00:03:fe",
-                "UDP": 40051,
-                "filter": "ip6 multicast and dst host ff08::3fe and udp dst port 40051",
-                "packet": "dst=33:33:00:00:03:fe src=00:bb:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v6",
-                    "interface": "h4v6-bond0"
-                },
-                {
-                    "host": "h8v6"
-                },
-                {
-                    "host": "h1v6"
-                }
-            ]
-        }
-    }
-]
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE008.multicastConfig b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE008.multicastConfig
deleted file mode 100644
index 218ed4d..0000000
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE008.multicastConfig
+++ /dev/null
@@ -1,60 +0,0 @@
-[
-    {
-        "ipVersion": 4,
-        "sIP": "10.2.0.1",
-        "group": "224.2.0.1",
-        "sPorts": ["of:0000000000000002/9"],
-        "dHosts": ["00:AA:00:00:00:03/None", "00:AA:00:00:00:06/None", "00:AA:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v4",
-                "interface": "h3v4-eth0",
-                "Ether": "01:00:5e:02:00:01",
-                "UDP": 40051,
-                "filter": "ip multicast and dst host 224.2.0.1 and udp dst port 40051",
-                "packet": "dst=01:00:5e:02:00:01 src=00:aa:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v4",
-                    "interface": "h4v4-bond0"
-                },
-                {
-                    "host": "h8v4"
-                },
-                {
-                    "host": "h1v4"
-                }
-            ]
-        }
-    },
-    {
-        "ipVersion": 6,
-        "sIP": "1002::3fe",
-        "group": "ff08::3fe",
-        "sPorts": ["of:0000000000000002/6"],
-        "dHosts": ["00:BB:00:00:00:03/None", "00:BB:00:00:00:06/None", "00:BB:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v6",
-                "interface": "h3v6-eth0",
-                "Ether": "33:33:00:00:03:fe",
-                "UDP": 40051,
-                "filter": "ip6 multicast and dst host ff08::3fe and udp dst port 40051",
-                "packet": "dst=33:33:00:00:03:fe src=00:bb:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v6",
-                    "interface": "h4v6-bond0"
-                },
-                {
-                    "host": "h8v6"
-                },
-                {
-                    "host": "h1v6"
-                }
-            ]
-        }
-    }
-]
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE101.multicastConfig b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE101.multicastConfig
deleted file mode 100644
index 218ed4d..0000000
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE101.multicastConfig
+++ /dev/null
@@ -1,60 +0,0 @@
-[
-    {
-        "ipVersion": 4,
-        "sIP": "10.2.0.1",
-        "group": "224.2.0.1",
-        "sPorts": ["of:0000000000000002/9"],
-        "dHosts": ["00:AA:00:00:00:03/None", "00:AA:00:00:00:06/None", "00:AA:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v4",
-                "interface": "h3v4-eth0",
-                "Ether": "01:00:5e:02:00:01",
-                "UDP": 40051,
-                "filter": "ip multicast and dst host 224.2.0.1 and udp dst port 40051",
-                "packet": "dst=01:00:5e:02:00:01 src=00:aa:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v4",
-                    "interface": "h4v4-bond0"
-                },
-                {
-                    "host": "h8v4"
-                },
-                {
-                    "host": "h1v4"
-                }
-            ]
-        }
-    },
-    {
-        "ipVersion": 6,
-        "sIP": "1002::3fe",
-        "group": "ff08::3fe",
-        "sPorts": ["of:0000000000000002/6"],
-        "dHosts": ["00:BB:00:00:00:03/None", "00:BB:00:00:00:06/None", "00:BB:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v6",
-                "interface": "h3v6-eth0",
-                "Ether": "33:33:00:00:03:fe",
-                "UDP": 40051,
-                "filter": "ip6 multicast and dst host ff08::3fe and udp dst port 40051",
-                "packet": "dst=33:33:00:00:03:fe src=00:bb:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v6",
-                    "interface": "h4v6-bond0"
-                },
-                {
-                    "host": "h8v6"
-                },
-                {
-                    "host": "h1v6"
-                }
-            ]
-        }
-    }
-]
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE102.multicastConfig b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE102.multicastConfig
deleted file mode 100644
index 218ed4d..0000000
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE102.multicastConfig
+++ /dev/null
@@ -1,60 +0,0 @@
-[
-    {
-        "ipVersion": 4,
-        "sIP": "10.2.0.1",
-        "group": "224.2.0.1",
-        "sPorts": ["of:0000000000000002/9"],
-        "dHosts": ["00:AA:00:00:00:03/None", "00:AA:00:00:00:06/None", "00:AA:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v4",
-                "interface": "h3v4-eth0",
-                "Ether": "01:00:5e:02:00:01",
-                "UDP": 40051,
-                "filter": "ip multicast and dst host 224.2.0.1 and udp dst port 40051",
-                "packet": "dst=01:00:5e:02:00:01 src=00:aa:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v4",
-                    "interface": "h4v4-bond0"
-                },
-                {
-                    "host": "h8v4"
-                },
-                {
-                    "host": "h1v4"
-                }
-            ]
-        }
-    },
-    {
-        "ipVersion": 6,
-        "sIP": "1002::3fe",
-        "group": "ff08::3fe",
-        "sPorts": ["of:0000000000000002/6"],
-        "dHosts": ["00:BB:00:00:00:03/None", "00:BB:00:00:00:06/None", "00:BB:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v6",
-                "interface": "h3v6-eth0",
-                "Ether": "33:33:00:00:03:fe",
-                "UDP": 40051,
-                "filter": "ip6 multicast and dst host ff08::3fe and udp dst port 40051",
-                "packet": "dst=33:33:00:00:03:fe src=00:bb:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v6",
-                    "interface": "h4v6-bond0"
-                },
-                {
-                    "host": "h8v6"
-                },
-                {
-                    "host": "h1v6"
-                }
-            ]
-        }
-    }
-]
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE103.multicastConfig b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE103.multicastConfig
deleted file mode 100644
index 218ed4d..0000000
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE103.multicastConfig
+++ /dev/null
@@ -1,60 +0,0 @@
-[
-    {
-        "ipVersion": 4,
-        "sIP": "10.2.0.1",
-        "group": "224.2.0.1",
-        "sPorts": ["of:0000000000000002/9"],
-        "dHosts": ["00:AA:00:00:00:03/None", "00:AA:00:00:00:06/None", "00:AA:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v4",
-                "interface": "h3v4-eth0",
-                "Ether": "01:00:5e:02:00:01",
-                "UDP": 40051,
-                "filter": "ip multicast and dst host 224.2.0.1 and udp dst port 40051",
-                "packet": "dst=01:00:5e:02:00:01 src=00:aa:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v4",
-                    "interface": "h4v4-bond0"
-                },
-                {
-                    "host": "h8v4"
-                },
-                {
-                    "host": "h1v4"
-                }
-            ]
-        }
-    },
-    {
-        "ipVersion": 6,
-        "sIP": "1002::3fe",
-        "group": "ff08::3fe",
-        "sPorts": ["of:0000000000000002/6"],
-        "dHosts": ["00:BB:00:00:00:03/None", "00:BB:00:00:00:06/None", "00:BB:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v6",
-                "interface": "h3v6-eth0",
-                "Ether": "33:33:00:00:03:fe",
-                "UDP": 40051,
-                "filter": "ip6 multicast and dst host ff08::3fe and udp dst port 40051",
-                "packet": "dst=33:33:00:00:03:fe src=00:bb:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v6",
-                    "interface": "h4v6-bond0"
-                },
-                {
-                    "host": "h8v6"
-                },
-                {
-                    "host": "h1v6"
-                }
-            ]
-        }
-    }
-]
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE201.multicastConfig b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE201.multicastConfig
deleted file mode 100644
index 218ed4d..0000000
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/CASE201.multicastConfig
+++ /dev/null
@@ -1,60 +0,0 @@
-[
-    {
-        "ipVersion": 4,
-        "sIP": "10.2.0.1",
-        "group": "224.2.0.1",
-        "sPorts": ["of:0000000000000002/9"],
-        "dHosts": ["00:AA:00:00:00:03/None", "00:AA:00:00:00:06/None", "00:AA:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v4",
-                "interface": "h3v4-eth0",
-                "Ether": "01:00:5e:02:00:01",
-                "UDP": 40051,
-                "filter": "ip multicast and dst host 224.2.0.1 and udp dst port 40051",
-                "packet": "dst=01:00:5e:02:00:01 src=00:aa:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v4",
-                    "interface": "h4v4-bond0"
-                },
-                {
-                    "host": "h8v4"
-                },
-                {
-                    "host": "h1v4"
-                }
-            ]
-        }
-    },
-    {
-        "ipVersion": 6,
-        "sIP": "1002::3fe",
-        "group": "ff08::3fe",
-        "sPorts": ["of:0000000000000002/6"],
-        "dHosts": ["00:BB:00:00:00:03/None", "00:BB:00:00:00:06/None", "00:BB:00:00:00:01/None"],
-        "scapy": {
-            "src": {
-                "host": "h3v6",
-                "interface": "h3v6-eth0",
-                "Ether": "33:33:00:00:03:fe",
-                "UDP": 40051,
-                "filter": "ip6 multicast and dst host ff08::3fe and udp dst port 40051",
-                "packet": "dst=33:33:00:00:03:fe src=00:bb:00:00:00:02"
-            },
-            "dst": [
-                {
-                    "host": "h4v6",
-                    "interface": "h4v6-bond0"
-                },
-                {
-                    "host": "h8v6"
-                },
-                {
-                    "host": "h1v6"
-                }
-            ]
-        }
-    }
-]
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/common.multicastConfig b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/common.multicastConfig
new file mode 100644
index 0000000..842d540
--- /dev/null
+++ b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/multicast/common.multicastConfig
@@ -0,0 +1,58 @@
+{
+    "ipv4": {
+        "ipVersion": 4,
+        "group": "224.2.0.1",
+        "src": [
+            {
+                "host": "h3v4",
+                "ip": "10.2.0.1",
+                "port": "of:0000000000000002/9",
+                "interface": "h3v4-eth0",
+                "Ether": "01:00:5e:02:00:01",
+                "UDP": 40051,
+                "filter": "ip host 224.2.0.1",
+                "packet": "dst=01:00:5e:02:00:01 src=00:aa:00:00:00:02"
+            }
+        ],
+        "dst": [
+            {
+                "host": "h4v4",
+                "id": "00:AA:00:00:00:03/None",
+                "interface": "h4v4-bond0",
+                "dualHomed": "True"
+            },
+            {
+                "host": "h8v4",
+                "id": "00:AA:00:00:00:06/None",
+                "dualHomed": "False"
+            },
+            {
+                "host": "h10v4",
+                "id": "00:AA:00:00:00:08/40",
+                "dualHomed": "True"
+            }
+        ]
+    },
+    "ipv6": {
+        "ipVersion": 6,
+        "group": "ff08::3fe",
+        "src": [
+            {
+                "host": "h3v6",
+                "ip": "1002::3fe",
+                "port": "of:0000000000000002/6",
+                "interface": "h3v6-eth0",
+                "Ether": "33:33:00:00:03:fe",
+                "UDP": 40051,
+                "filter": "ip6 host ff08::3fe",
+                "packet": "dst=33:33:00:00:03:fe src=00:bb:00:00:00:02"
+            }
+        ],
+        "dst": [
+            {
+                "host": "h1v6",
+                "id": "00:BB:00:00:00:01/None"
+            }
+        ]
+    }
+}
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/switchFailure/CASE201.switchFailureChart b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/switchFailure/CASE201.switchFailureChart
deleted file mode 100644
index 6614e5f..0000000
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/switchFailure/CASE201.switchFailureChart
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-    "spine101": { "switches_before_failure": 10,
-                  "links_before_failure": 48,
-                  "switches_after_failure": 9,
-                  "links_after_failure": 30 },
-    "spine102": { "switches_before_failure": 10,
-                  "links_before_failure": 48,
-                  "switches_after_failure": 9,
-                  "links_after_failure": 30 },
-    "spine103": { "switches_before_failure": 10,
-                  "links_before_failure": 48,
-                  "switches_after_failure": 9,
-                  "links_after_failure": 42 },
-    "spine104": { "switches_before_failure": 10,
-                  "links_before_failure": 48,
-                  "switches_after_failure": 9,
-                  "links_after_failure": 42 }
-}
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py b/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
index 9d901f1..8c67f37 100644
--- a/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
+++ b/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
@@ -586,11 +586,12 @@
                                  onfail="Link batch up failed" )
 
     @staticmethod
-    def restoreLink( main, end1, end2, dpid1, dpid2, port1, port2, switches,
-                     links ):
+    def restoreLink( main, end1, end2, switches, links,
+                     portUp=False, dpid1='', dpid2='', port1='', port2='' ):
         """
         Params:
             end1,end2: identify the end switches, ex.: 'leaf1', 'spine1'
+            portUp: enable portstate after restoring link
             dpid1, dpid2: dpid of the end switches respectively, ex.: 'of:0000000000000002'
             port1, port2: respective port of the end switches that connects to the link, ex.:'1'
             switches, links: number of expected switches and links after linkDown, ex.: '4', '6'
@@ -607,13 +608,10 @@
                     "Waiting %s seconds for link up to be discovered" % main.linkSleep )
             time.sleep( main.linkSleep )
 
-            for i in range( 0, main.Cluster.numCtrls ):
-                ctrl = main.Cluster.runningNodes[ i ]
-                onosIsUp = main.ONOSbench.isup( ctrl.ipAddress )
-                if onosIsUp == main.TRUE:
-                    ctrl.CLI.portstate( dpid=dpid1, port=port1, state='Enable' )
-                    ctrl.CLI.portstate( dpid=dpid2, port=port2, state='Enable' )
-            time.sleep( main.linkSleep )
+            if portUp:
+                ctrl.CLI.portstate( dpid=dpid1, port=port1, state='Enable' )
+                ctrl.CLI.portstate( dpid=dpid2, port=port2, state='Enable' )
+                time.sleep( main.linkSleep )
 
             result = main.Cluster.active( 0 ).CLI.checkStatus( numoswitch=switches,
                                                                numolink=links )
@@ -630,9 +628,11 @@
         Completely kill a switch and verify ONOS can see the proper change
         """
         main.switchSleep = float( main.params[ 'timers' ][ 'SwitchDiscovery' ] )
-        main.step( "Kill " + switch )
-        main.log.info( "Stopping" + switch )
-        main.Network.switch( SW=switch, OPTION="stop" )
+        switch = switch if isinstance( switch, list ) else [ switch ]
+        main.step( "Kill " + str( switch ) )
+        for s in switch:
+            main.log.info( "Stopping " + s )
+            main.Network.switch( SW=s, OPTION="stop" )
         # todo make this repeatable
         main.log.info( "Waiting %s seconds for switch down to be discovered" % (
             main.switchSleep ) )
@@ -654,9 +654,11 @@
         Recover a switch and verify ONOS can see the proper change
         """
         # todo make this repeatable
-        main.step( "Recovering " + switch )
-        main.log.info( "Starting" + switch )
-        main.Network.switch( SW=switch, OPTION="start" )
+        switch = switch if isinstance( switch, list ) else [ switch ]
+        main.step( "Recovering " + str( switch ) )
+        for s in switch:
+            main.log.info( "Starting " + s )
+            main.Network.switch( SW=s, OPTION="start" )
         main.log.info( "Waiting %s seconds for switch up to be discovered" % (
             main.switchSleep ) )
         time.sleep( main.switchSleep )
@@ -670,6 +672,25 @@
                                  onpass="Switch recovery successful",
                                  onfail="Failed to recover switch?" )
 
+    def portstate( main, dpid, port, state, switches, links ):
+        """
+        Disable/enable a switch port using 'portstate' and verify ONOS can see the proper link change
+        Params:
+            dpid: dpid of the switch, ex.: 'of:0000000000000002'
+            port: port of the switch to disable/enable, ex.:'1'
+            state: disable or enable
+            switches, links: number of expected switches and links after link change, ex.: '4', '6'
+        """
+        main.step( "Port %s on %s:%s" % ( state, dpid, port ) )
+        main.Cluster.active( 0 ).CLI.portstate( dpid=dpid, port=port, state=state )
+        main.log.info( "Waiting %s seconds for port %s to be discovered" % ( main.linkSleep, state ) )
+        time.sleep( main.linkSleep )
+        result = main.Cluster.active( 0 ).CLI.checkStatus( numoswitch=switches,
+                                                           numolink=links )
+        utilities.assert_equals( expect=main.TRUE, actual=result,
+                                 onpass="Port %s successful" % state,
+                                 onfail="Port %s failed" % state )
+
     @staticmethod
     def cleanup( main, copyKarafLog=True ):
         """
@@ -976,50 +997,71 @@
             main.log.debug( host.hostMac )
 
     @staticmethod
-    def verifyMulticastTraffic( main, entry, expect, skipOnFail=False ):
+    def verifyMulticastTraffic( main, routeName, expect, skipOnFail=True, maxRetry=3 ):
         """
         Verify multicast traffic using scapy
         """
-        srcEntry = entry["scapy"]["src"]
-        for dstEntry in entry["scapy"]["dst"]:
-            # Set up scapy receiver
-            receiver = getattr( main, dstEntry["host"] )
-            if "interface" in dstEntry.keys():
-                receiver.startFilter( ifaceName=dstEntry["interface"], pktFilter=srcEntry["filter"] )
-            else:
-                receiver.startFilter( pktFilter=srcEntry["filter"] )
-            # Set up scapy sender
-            main.Network.addRoute( str( srcEntry["host"] ),
-                                   str( entry["group"] ),
-                                   str( srcEntry["interface"] ),
-                                   True if entry["ipVersion"] == 6 else False )
-            sender = getattr( main, srcEntry["host"] )
-            sender.buildEther( dst=str( srcEntry["Ether"] ) )
-            if entry["ipVersion"] == 4:
-                sender.buildIP( dst=str( entry["group"] ) )
-            elif entry["ipVersion"] == 6:
-                sender.buildIPv6( dst=str( entry["group"] ) )
-            sender.buildUDP( ipVersion=entry["ipVersion"], dport=srcEntry["UDP"] )
-            # Send packet and check received packet
-            sender.sendPacket( iface=srcEntry["interface"] )
-            finished = receiver.checkFilter()
-            packet = ""
-            if finished:
-                packets = receiver.readPackets()
-                for packet in packets.splitlines():
-                    main.log.debug( packet )
-            else:
-                kill = receiver.killFilter()
-                main.log.debug( kill )
-                sender.handle.sendline( "" )
-                sender.handle.expect( sender.scapyPrompt )
-                main.log.debug( sender.handle.before )
-            packetCaptured = True if srcEntry["packet"] in packet else False
-            utilities.assert_equals( expect=expect,
-                                     actual=packetCaptured,
-                                     onpass="Pass",
-                                     onfail="Fail" )
-            if skipOnFail and packetCaptured != expect:
-                Testcaselib.saveOnosDiagnostics( main )
-                Testcaselib.cleanup( main, copyKarafLog=False )
-                main.skipCase()
+        routeData = main.multicastConfig[ routeName ]
+        srcs = main.mcastRoutes[ routeName ][ "src" ]
+        dsts = main.mcastRoutes[ routeName ][ "dst" ]
+        main.log.info( "Sending multicast traffic from {} to {}".format( [ routeData[ "src" ][ i ][ "host" ] for i in srcs ],
+                                                                         [ routeData[ "dst" ][ i ][ "host" ] for i in dsts ] ) )
+        for src in srcs:
+            srcEntry = routeData[ "src" ][ src ]
+            for dst in dsts:
+                dstEntry = routeData[ "dst" ][ dst ]
+                sender = getattr( main, srcEntry[ "host" ] )
+                receiver = getattr( main, dstEntry[ "host" ] )
+                main.Network.addRoute( str( srcEntry[ "host" ] ),
+                                       str( routeData[ "group" ] ),
+                                       str( srcEntry[ "interface" ] ),
+                                       True if routeData[ "ipVersion" ] == 6 else False )
+                # Build the packet
+                sender.buildEther( dst=str( srcEntry[ "Ether" ] ) )
+                if routeData[ "ipVersion" ] == 4:
+                    sender.buildIP( dst=str( routeData[ "group" ] ) )
+                elif routeData[ "ipVersion" ] == 6:
+                    sender.buildIPv6( dst=str( routeData[ "group" ] ) )
+                sender.buildUDP( ipVersion=routeData[ "ipVersion" ], dport=srcEntry[ "UDP" ] )
+                sIface = srcEntry[ "interface" ]
+                dIface = dstEntry[ "interface" ] if "interface" in dstEntry.keys() else None
+                pktFilter = srcEntry[ "filter" ]
+                pkt = srcEntry[ "packet" ]
+                # Send packet and check received packet
+                expectedResult = expect.pop( 0 ) if isinstance( expect, list ) else expect
+                trafficResult = utilities.retry( Testcaselib.sendMulticastTraffic,
+                                                 main.FALSE,
+                                                 args=( main, sender, receiver, pktFilter, pkt,
+                                                        sIface, dIface, expectedResult ),
+                                                 attempts=maxRetry,
+                                                 sleep=1 )
+                utilities.assert_equals( expect=main.TRUE,
+                                         actual=trafficResult,
+                                         onpass="{} to {}: Pass".format( srcEntry[ "host" ], dstEntry[ "host" ] ),
+                                         onfail="{} to {}: Fail".format( srcEntry[ "host" ], dstEntry[ "host" ] ) )
+                if skipOnFail and trafficResult != main.TRUE:
+                    Testcaselib.saveOnosDiagnostics( main )
+                    Testcaselib.cleanup( main, copyKarafLog=False )
+                    main.skipCase()
+
+    @staticmethod
+    def sendMulticastTraffic( main, sender, receiver, pktFilter, pkt, sIface=None, dIface=None, expect=True ):
+        """
+        Send multicast traffic using scapy
+        """
+        receiver.startFilter( ifaceName=dIface, pktFilter=pktFilter )
+        sender.sendPacket( iface=sIface )
+        finished = receiver.checkFilter()
+        packet = ""
+        if finished:
+            packets = receiver.readPackets()
+            for packet in packets.splitlines():
+                main.log.debug( packet )
+        else:
+            kill = receiver.killFilter()
+            main.log.debug( kill )
+            sender.handle.sendline( "" )
+            sender.handle.expect( sender.scapyPrompt )
+            main.log.debug( sender.handle.before )
+        packetCaptured = True if pkt in packet else False
+        return main.TRUE if packetCaptured == expect else main.FALSE