Blackhole-route tests in the nightly run

Change-Id: I4f490e43fa515174d995aab017cbd68697f0b5b2
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index f041871..5694fc6 100755
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -3074,22 +3074,26 @@
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanAndExit()
 
-    def addStaticRoute( self, subnet, intf):
+    def sendOnosCliCommand( self, cmd, params=[] ):
         """
-        Adds a static route to onos.
+        Handles sending an arbitrary command to the ONOS cli and parsing standard errors
         Params:
-            subnet: The subnet reaching through this route
-            intf: The interface this route is reachable through
+            cmd: The command to be sent in the onos cli
+            params: Sending the parameters within the command we send in the cli
         """
         try:
-            cmdStr = "route-add " + subnet + " " + intf
+            if not isinstance(params, list):
+              params=[params]
+            cmdStr = cmd + " " + ' '.join(params)
             handle = self.sendline( cmdStr )
             assert handle is not None, "Error in sendline"
             assert "Command not found:" not in handle, handle
+            # Check for error in cli response
+            assert "Error executing command" not in handle, handle
             return handle
         except AssertionError:
             main.log.exception( "" )
-            return None
+            return main.FALSE
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
@@ -3098,6 +3102,27 @@
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanAndExit()
 
+    def blackholeStaticRoute( self, subnet, addBlackhole=True ):
+        """
+        Manage black hole routes in onos.
+        Params:
+            subnet: The subnet to be blocked through this route
+            addBlackhole: Boolean set to declare if we are adding or removing the blackhole route
+        """
+        if addBlackhole:
+            addedBlackholeIP = self.sendOnosCliCommand('sr-blackhole add', subnet)
+        else:
+            removedBlackholeIP = self.sendOnosCliCommand('sr-blackhole remove', subnet)
+        blackHoleList = self.sendOnosCliCommand('sr-blackhole list')
+        if subnet in blackHoleList:
+            exists = True
+        else:
+            exists = False
+        if (addBlackhole and exists) or (not addBlackhole and not exists):
+            return main.TRUE
+        else:
+            return main.FALSE
+
     def checkGroupAddedCount( self, deviceId, expectedGroupCount=0, core=False, comparison=0):
         """
         Description:
diff --git a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params.tucson b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params.tucson
index 3eeea1e..827f790 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params.tucson
+++ b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params.tucson
@@ -1,5 +1,5 @@
 <PARAMS>
-    <testcases>1,3,4,6,7,9,101,104</testcases>
+    <testcases>1,3,4,6,7,9,101,104,701</testcases>
 
     <GRAPH>
         <nodeCluster>pairedleaves</nodeCluster>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.py b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.py
index 467231c..c6e97b5 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.py
@@ -1,4 +1,3 @@
-
 class SRRouting:
 
     def __init__( self ):
@@ -1662,3 +1661,165 @@
         # Bring down/up internal router-2
         verifyRouterFailure( main, "bgp2", [ "rh5v4" ], [ "rh11v6", "rh5v6" ] )
         lib.cleanup( main, copyKarafLog=False, removeHostComponent=True )
+
+    def CASE701( self, main ):
+        """
+        Add and remove a blackhole route
+        - Set up an imaginary subnet reachable via a next hop host using a static route
+        - Ping from any host to an imaginary IP in this subnet
+        - Setup a subset of the imaginary subnet that we want to blackhole (add a blackhole route)
+        - Try to Ping from the host again, but it should fail
+        - Revert the subset (remove the blackhole IP)
+        - Try to Ping again, this time it should work
+        """
+        from tests.USECASE.SegmentRouting.SRRouting.dependencies.SRRoutingTest import *
+        from tests.USECASE.SegmentRouting.dependencies.Testcaselib import Testcaselib as lib
+        main.case( "Add and remove a blackhole-route" )
+        setupTest( main, test_idx=701, onosNodes=3, ipv6=False, external=False )
+        verify( main, ipv6=False, external=False, disconnected=False )
+
+        dstIp = "50.0.1.1"
+        baseIP = "50.0.0.0"
+        blackholeIp = "50.0.0.1"
+        blackholeIpRoute = "%s/24" % blackholeIp
+        route = "%s/16" % baseIP
+        blackholeRoute = "%s/24" % baseIP
+        srcComponent = getattr( main, 'Compute2' )
+        nextHopComponent = getattr( main, 'ManagmentServer' ) # add dstIP to the params file
+        nextHopIface = nextHopComponent.interfaces[0].get( 'name' )
+        nextHopIp = nextHopComponent.getIPAddress( iface=nextHopIface )
+        srcComponentIface = srcComponent.interfaces[0].get( 'name' )
+        srcComponentIP = srcComponent.getIPAddress( iface=srcComponentIface )
+        fabricInterfaceIP = lib.getFabricIntfIp( main, srcComponentIP )
+        main.step( "Adding a static route in onos")
+        """
+        Try this on the host:
+        ip route add 50.0.0.0/16 via <fabric interface ip>
+        and this in ONOS:
+        route-add 50.0.0.0/16 via <nextHopComponent fabric ip>
+        """
+        routeResult=main.Cluster.active( 0 ).routeAdd( route, nextHopIp )
+        main.log.debug(routeResult)
+        utilities.assert_not_equals( expect=None, actual=routeResult,
+                                     onpass="Route added in onos",
+                                     onfail="Failed to add route in onos" )
+        main.log.debug( main.Cluster.active( 0 ).routes() )
+        nextHopComponent.startScapy( ifaceName=nextHopIface )
+
+        main.step( "Adding a static route in the host" )
+        routeResult=srcComponent.addRouteToHost( route, fabricInterfaceIP )
+        utilities.assert_equals( expect=main.TRUE, actual=routeResult,
+                                     onpass="Route added in the host",
+                                     onfail="Failed to add route in the host" )
+        main.log.debug( main.Compute2.getRoutes() )
+
+        main.step("Capturing ping to dstIP after adding the static routes")
+        nextHopComponent.startFilter( ifaceName=nextHopIface, sniffCount=1, pktFilter="icmp and host " + dstIp )
+        srcComponent.ping( dstIp )
+        packetFound=nextHopComponent.checkFilter()
+        if packetFound is main.FALSE:
+            main.log.debug( nextHopComponent.killFilter() )
+        utilities.assert_equals( expect=main.TRUE, actual=packetFound,
+                                    onpass="Packet has reached dstIP",
+                                    onfail="Failed to reach dstIP" )
+        main.log.debug( nextHopComponent.readPackets() )
+
+        main.step("Capturing ping to blackholeIP after adding the static routes")
+        nextHopComponent.startFilter( ifaceName=nextHopIface, sniffCount=1, pktFilter="icmp and host " + blackholeIp )
+        srcComponent.ping( blackholeIp )
+        packetFound=nextHopComponent.checkFilter()
+        if packetFound is main.FALSE:
+            main.log.debug( nextHopComponent.killFilter() )
+        utilities.assert_equals( expect=main.TRUE, actual=packetFound,
+                                    onpass="Packet has reached blackholeIP",
+                                    onfail="Failed to reach blackholeIP" )
+        main.log.debug( nextHopComponent.readPackets() )
+
+        main.step( "Adding a blackhole route")
+        blackholeRouteResult=main.Cluster.active( 0 ).blackholeStaticRoute( subnet=blackholeRoute, addBlackhole=True )
+        utilities.assert_equals( expect=main.TRUE, actual=blackholeRouteResult,
+                                     onpass="Blackhole route added",
+                                     onfail="Failed to add blackhole route" )
+
+        main.step("Capturing ping to blackholeIP after adding the blackhole route")
+        nextHopComponent.startFilter( ifaceName=nextHopIface, sniffCount=1, pktFilter="icmp and host " + blackholeIp )
+        srcComponent.ping( blackholeIp )
+        blackholePacket=nextHopComponent.checkFilter()
+        if blackholePacket is main.FALSE:
+            main.log.debug( nextHopComponent.killFilter() )
+        utilities.assert_equals( expect=main.FALSE, actual=blackholePacket,
+                                     onpass="Packet has not reached blackholeIP",
+                                     onfail="Packet has reached blackholeIP" )
+
+        main.step("Capturing ping to dstIP after adding the blackhole route")
+        nextHopComponent.startFilter( ifaceName=nextHopIface, sniffCount=1, pktFilter="icmp and host " + dstIp )
+        srcComponent.ping( dstIp )
+        packetFound=nextHopComponent.checkFilter()
+        if packetFound is main.FALSE:
+            main.log.debug( nextHopComponent.killFilter() )
+        utilities.assert_equals( expect=main.TRUE, actual=packetFound,
+                                     onpass="Packet has reached dstIP",
+                                     onfail="Failed to reach dstIP" )
+        main.log.debug( nextHopComponent.readPackets() )
+
+        main.step( "Removing the blackhole route" )
+        blackholeList = main.Cluster.active( 0 ).blackholeStaticRoute( subnet=blackholeRoute, addBlackhole=False)
+        utilities.assert_equals( expect=main.TRUE, actual=blackholeList,
+                                     onpass="Blackhole route has been removed",
+                                     onfail="Failed to remove the blackhole route" )
+
+        main.step("Capturing ping to dstIP after removing the blackhole route")
+        nextHopComponent.startFilter( ifaceName=nextHopIface, sniffCount=1, pktFilter="icmp and host " + dstIp )
+        srcComponent.ping( dstIp )
+        packetFound=nextHopComponent.checkFilter()
+        if packetFound is main.FALSE:
+            main.log.debug( nextHopComponent.killFilter() )
+        utilities.assert_equals( expect=main.TRUE, actual=packetFound,
+                                     onpass="Packet has reached dstIP",
+                                     onfail="Failed to reach dstIP" )
+
+        main.step("Capturing ping to blackholeIP after removing the blackhole route")
+        nextHopComponent.startFilter( ifaceName=nextHopIface, sniffCount=1, pktFilter="icmp and host " + blackholeIp )
+        srcComponent.ping( blackholeIp )
+        packetFound=nextHopComponent.checkFilter()
+        if packetFound is main.FALSE:
+            main.log.debug( nextHopComponent.killFilter() )
+        utilities.assert_equals( expect=main.TRUE, actual=packetFound,
+                                     onpass="Packet has reached blackholeIP",
+                                     onfail="Packet failed to reach blackholeIP" )
+        main.log.debug( nextHopComponent.checkFilter() )
+
+        main.log.debug( nextHopComponent.readPackets() )
+        main.step("Checking if the route is present in the host")
+        routeRemoved = srcComponent.deleteRoute( route, fabricInterfaceIP )
+        utilities.assert_equals( expect=main.TRUE, actual=routeRemoved,
+                                     onpass="Route is not present in the host",
+                                     onfail="Route is still present in the host" )
+
+        main.step( "Checking if the route is removed from onos" )
+        routeRemoved = main.Cluster.active( 0 ).routeRemove( route, nextHopIp )
+        utilities.assert_not_equals( expect=None, actual=routeRemoved,
+                                     onpass="Route removed from onos",
+                                     onfail="Failed to remove route from onos" )
+
+        main.step("Capturing ping to dstIP after removing the static route")
+        nextHopComponent.startFilter( ifaceName=nextHopIface, sniffCount=1, pktFilter="icmp and host " + dstIp )
+        srcComponent.ping( dstIp )
+        packetFound=nextHopComponent.checkFilter()
+        if packetFound is main.FALSE:
+            main.log.debug( nextHopComponent.killFilter() )
+        utilities.assert_equals( expect=main.FALSE, actual=packetFound,
+                                    onpass="Packet has failed to reach dstIP",
+                                    onfail="Packet has reached dstIP" )
+        main.log.debug( nextHopComponent.readPackets() )
+
+        main.step("Capturing ping to blackholeIP after removing the static route")
+        nextHopComponent.startFilter( ifaceName=nextHopIface, sniffCount=1, pktFilter="icmp and host " + blackholeIp )
+        srcComponent.ping( blackholeIp )
+        packetFound=nextHopComponent.checkFilter()
+        if packetFound is main.FALSE:
+            main.log.debug( nextHopComponent.killFilter() )
+        utilities.assert_equals( expect=main.FALSE, actual=packetFound,
+                                     onpass="Packet has failed to reach blackholeIP",
+                                     onfail="Packet reached blackholeIP" )
+        main.log.debug( nextHopComponent.checkFilter() )
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py b/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
index 5638949..45b01b7 100644
--- a/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
+++ b/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
@@ -525,7 +525,7 @@
         """
         Adds an ONOS static route with the use route-add command.
         """
-        routeResult = main.Cluster.active( 0 ).addStaticRoute(subnet, intf)
+        routeResult = main.Cluster.active( 0 ).routeAdd(subnet, intf)
 
     @staticmethod
     def checkGroupsForBuckets( main, deviceId, subnetDict, routingTable=30 ):
@@ -762,7 +762,7 @@
                                     expectedResult = ping["vlans"].get(str(result["vlan"]))
                         if expectedResult is None:
                             expectedRresult = expect
-                        if expectedResult.lower() == "true":
+                        elif expectedResult.lower() == "true":
                             expectedResult = main.TRUE
                         else:
                             expectedResult = main.FALSE