Merge "add extra print to get around a pexpect problem"
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index 07acc01..b1c55de 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -578,7 +578,7 @@
         args = utilities.parse_args( [ "SRC", "TARGET", 'WAIT' ], **pingParams )
         wait = args['WAIT']
         wait = int( wait if wait else 1 )
-        command = args[ "SRC" ] + " ping " + \
+        command = args[ "SRC" ] + " ping6 " + \
             args[ "TARGET" ] + " -c 1 -i 1 -W " + str( wait ) + " "
         try:
             main.log.info( "Sending: " + command )
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 22b966b..cce13d3 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -331,7 +331,7 @@
             main.cleanup()
             main.exit()
 
-    def sendline( self, cmdStr, debug=False ):
+    def sendline( self, cmdStr, showResponse=False, debug=False ):
         """
         Send a completely user specified string to
         the onos> prompt. Use this function if you have
@@ -388,7 +388,10 @@
                 main.log.debug( self.name + ": split output" )
                 for r in output:
                     main.log.debug( self.name + ": " + repr( r ) )
-            return output[1].strip()
+            output = output[1].strip()
+            if showResponse:
+                main.log.info( "Resonse from ONOS: {}".format( output ) )
+            return output
         except IndexError:
             main.log.exception( self.name + ": Object not as expected" )
             return None
@@ -4117,7 +4120,6 @@
                 main.log.error( response )
                 return main.FALSE
 
-            main.log.info( response )
             return main.TRUE
 
         except TypeError:
diff --git a/TestON/tests/CHOtest/README b/TestON/tests/CHOtest/README
index 4b92d14..ab402f7 100644
--- a/TestON/tests/CHOtest/README
+++ b/TestON/tests/CHOtest/README
@@ -1 +1,40 @@
-#This README file be updated soon
+CHO TEST
+
+Summary:
+        This is a long-term regression test that is aimed to run
+        for weeks at a time. It's goal is to find memory leaks or bugs that
+        otherwise cannot be easily seen with short-term tests. The following
+        is an overview of the steps that are performed in this test.
+        Steps:
+        - Discover IPv4 and IPv6 hosts
+        - Add host intents
+        - Ping all hosts
+        - Bring links down
+        - Ping all hosts
+        - Bring links back up
+        - Ping all hosts
+        - remove intents
+
+        These steps are iterated over and over again. The number of iterations can
+        be found in the params file.
+
+Topology:
+        Att topology - 25 switches and 25 hosts and its structure is designed to simulate
+                        a real world configuration,
+        Chordal topology - 25 swithces and 25 hosts and because of its chordal graph structure,
+                            it's particulary useful in testing the rerouting capability of ONOS.
+        Leaf-spine topology - 78 switches and 68 hosts and designed to simulate modern data centers.
+
+Pre-requisites:
+        To run out-of-the box this test requires 3 NODES. The cell file
+        must be passed through the startup test command, e.g.,
+
+            ./cli.py run CHOtest onoscell <cell name>.
+
+        Passwordless login must be set from TestStation "admin" root user.
+        This test relies on the topology files to start Mininet located in
+        the Dependency folder. Be sure to check that each topology file can
+        be loaded properly by Mininet by using this command:
+
+            sudo ~/<Dependency path>/<topology name>
+
diff --git a/TestON/tests/FUNCflow/README b/TestON/tests/FUNCflow/README
new file mode 100644
index 0000000..018e42d
--- /dev/null
+++ b/TestON/tests/FUNCflow/README
@@ -0,0 +1,49 @@
+FUNCflow test suite
+
+Summary:
+        This test suite consists of basic flow-rule based functionality testing.
+        The main goal of this test suite is to verify that the flow subsytem is
+        compiling flows correctly. We verify each flow by utilizing Scapy, a
+        Python library for generating and sending packets. The following is an
+        overview of the test.
+        Steps:
+            - Discover hosts
+            - add specific flow
+            - verify flow
+            - remove flow
+
+        Each repetion of the steps tests a specific selector. Here is a list
+        of the selectors that are being tested:
+        Selectors:
+            - MAC
+            - IPv4
+            - VLAN
+            - MPLS
+            - TCP
+            - UDP
+
+        We verify the selectors by sending a tailor made packet through the
+        two hosts. If the packet was recieved, then the flow was compiled
+        correctly.
+
+Topology:
+        The topology consists of one switch with four hosts connected to it.
+        Two hosts are regular IPv4 hosts, while the other two are hosts with
+        vlan interfaces to test the vlan selector.
+
+Required:
+        This test requires Mininet topology file topo-flow.py located in the
+        dependency folder. The topology consistes of VLAN hosts, so you will
+        need to install the VLAN module. You will also need to install the
+        Python module, Scapy.
+
+VLAN configuration:
+        Execute command:
+            $ sudo apt-get install vlan
+        Configuration:
+            $ sudo modprobe 8021q
+        NOTE:To make this configuration permanent
+            $ sudo su -c 'echo "8021q" >> /etc/modules'
+
+Scapy install:
+    sudo apt-get install Scapy
diff --git a/TestON/tests/FUNCintent/README b/TestON/tests/FUNCintent/README
index ce4e99f..e97d0d3 100644
--- a/TestON/tests/FUNCintent/README
+++ b/TestON/tests/FUNCintent/README
@@ -29,6 +29,10 @@
         including VLAN hosts. Therefore you need to install VLAN module to build
         the topology correctly.
 
+NOTE:
+    This test is being updated to use Scapy for host discovery and verification of flows.
+    So, Scapy will be required to run the test in the future.
+
 VLAN configuration:
         Execute command:
             $ sudo apt-get install vlan
@@ -37,3 +41,6 @@
         NOTE:To make this configuration permanent
             $ sudo su -c 'echo "8021q" >> /etc/modules'
 
+Scapy install:
+    sudo apt-get install Scapy
+
diff --git a/TestON/tests/FUNCipv6Intent/Dependency/FUNCIpv6IntentFunction.py b/TestON/tests/FUNCipv6Intent/Dependency/FUNCIpv6IntentFunction.py
index 07de625..ec1ae9c 100644
--- a/TestON/tests/FUNCipv6Intent/Dependency/FUNCIpv6IntentFunction.py
+++ b/TestON/tests/FUNCipv6Intent/Dependency/FUNCIpv6IntentFunction.py
@@ -405,12 +405,12 @@
     checkFlowsState( main )
 
     # Ping hosts
-    pingTemp = pingallHosts( main, hostNames )
+    pingTemp = main.Mininet1.ping6pair(SRC=host1, TARGET='10:1:0::5')
     pingResult = pingResult and pingTemp
     if pingTemp:
-        main.assertReturnString += 'Initial Pingall Passed\n'
+        main.assertReturnString += 'Initial Ping6 pair Passed\n'
     else:
-        main.assertReturnString += 'Initial Pingall Failed\n'
+        main.assertReturnString += 'Initial Ping6 pair Failed\n'
 
     # Test rerouting if these variables exist
     if sw1 and sw2 and expectedLink:
@@ -435,7 +435,7 @@
             main.assertReturnString += 'Link Down Topology State Failed\n'
 
         # Ping hosts
-        pingTemp = pingallHosts( main, hostNames )
+        pingTemp = ping6allHosts( main, hostNames )
         pingResult = pingResult and pingTemp
         if pingTemp:
             main.assertReturnString += 'Link Down Pingall Passed\n'
@@ -1377,10 +1377,10 @@
 
     return stepResult
 
-def pingallHosts( main, hostList ):
+def ping6allHosts( main, hostList ):
     # Ping all host in the hosts list variable
     main.log.info( "Pinging: " + str( hostList ) )
-    return main.Mininet1.pingallHosts( hostList )
+    return main.Mininet1.pingIpv6Hosts( hostList )
 
 def getHostsData( main ):
     """
diff --git a/TestON/tests/FUNCipv6Intent/FUNCipv6Intent.params b/TestON/tests/FUNCipv6Intent/FUNCipv6Intent.params
index fdded10..f70e399 100644
--- a/TestON/tests/FUNCipv6Intent/FUNCipv6Intent.params
+++ b/TestON/tests/FUNCipv6Intent/FUNCipv6Intent.params
@@ -6,7 +6,7 @@
     # 12 - Assign switch to controller
     # 14 - Stop Mininet
 
-    <testcases>1,2,11,12,14</testcases>
+    <testcases>1,2,11,12,2000,14</testcases>
 
     <SCALE>
         <size>1</size>
@@ -24,7 +24,7 @@
         <cellApps>drivers,openflow,proxyarp,mobility</cellApps>
     </ENV>
     <GIT>
-        <pull>true</pull>
+        <pull>false</pull>
         <branch>master</branch>
     </GIT>
 
@@ -36,7 +36,6 @@
         <fwd>10</fwd>
         <topoAttempts>3</topoAttempts>
     </SLEEP>
-
     <MININET>
         <switch>7</switch>
         <links>20</links>
diff --git a/TestON/tests/FUNCipv6Intent/FUNCipv6Intent.py b/TestON/tests/FUNCipv6Intent/FUNCipv6Intent.py
index 0d189e3..f3c7f1e 100644
--- a/TestON/tests/FUNCipv6Intent/FUNCipv6Intent.py
+++ b/TestON/tests/FUNCipv6Intent/FUNCipv6Intent.py
@@ -236,6 +236,14 @@
                                  onpass="Successfully start ONOS cli",
                                  onfail="Failed to start ONOS cli" )
 
+        main.step( "setup the ipv6NeighbourDiscovery" )
+        cfgResult1 = main.CLIs[0].setCfg( "org.onosproject.proxyarp.ProxyArp", "ipv6NeighborDiscovery", "true" )
+        cfgResult2 = main.CLIs[0].setCfg( "org.onosproject.provider.host.impl.HostLocationProvider", "ipv6NeighborDiscovery", "true" )
+        cfgResult = cfgResult1 and cfgResult2
+        utilities.assert_equals( expect=main.TRUE, actual=cfgResult,
+                                onpass="ipv6NeighborDiscovery cfg is set to true",
+                                onfail="Failed to cfg set ipv6NeighborDiscovery" )
+
         # Remove the first element in main.scale list
         main.scale.remove( main.scale[ 0 ] )
 
@@ -291,7 +299,7 @@
 
         assignResult = main.Mininet1.assignSwController( sw=switchList,
                                                          ip=tempONOSip,
-                                                         port='6653' )
+                                                         port='6633' )
         if not assignResult:
             main.cleanup()
             main.exit()
@@ -331,3 +339,256 @@
         if not topoResult:
             main.cleanup()
             main.exit()
+
+    def CASE2000( self, main ):
+        """
+            add point intents between 2 hosts:
+                - Get device ids | ports
+                - Add point intents
+                - Check intents
+                - Verify flows
+                - Ping hosts
+                - Reroute
+                    - Link down
+                    - Verify flows
+                    - Check topology
+                    - Ping hosts
+                    - Link up
+                    - Verify flows
+                    - Check topology
+                    - Ping hosts
+                - Remove intents
+        """
+        import time
+        import json
+        import re
+
+        # Assert variables - These variable's name|format must be followed
+        # if you want to use the wrapper function
+        assert main, "There is no main"
+        assert main.CLIs, "There is no main.CLIs"
+        assert main.Mininet1, "Mininet handle should be named Mininet1"
+        assert main.numSwitch, "Placed the total number of switch topology in \
+                                main.numSwitch"
+
+        main.testName = "Point Intents"
+        main.case( main.testName + " Test - " + str( main.numCtrls ) +
+                   " NODE(S) - OF " + main.OFProtocol )
+        main.caseExplanation = "This test case will test point to point" +\
+                               " intents using " + str( main.numCtrls ) +\
+                               " node(s) cluster;\n" +\
+                               "Different type of hosts will be tested in " +\
+                               "each step such as IPV4, Dual stack, VLAN etc" +\
+                               ";\nThe test will use OF " + main.OFProtocol +\
+                               " OVS running in Mininet"
+
+        # No option point intents
+        main.step( "NOOPTION: Add point intents between h1 and h9, ipv6 hosts" )
+        main.assertReturnString = "Assertion Result for NOOPTION point intent\n"
+        stepResult = main.TRUE
+        stepResult = main.intentFunction.pointIntent(
+                                       main,
+                                       name="NOOPTION",
+                                       host1="h1",
+                                       host2="h9",
+                                       deviceId1="of:0000000000000005/1",
+                                       deviceId2="of:0000000000000006/1")
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass=main.assertReturnString,
+                                 onfail=main.assertReturnString )
+
+        stepResult = main.TRUE
+        main.step( "IPV6: Add point intents between h1 and h9" )
+        main.assertReturnString = "Assertion Result for IPV6 point intent\n"
+        stepResult = main.intentFunction.pointIntent(
+                                       main,
+                                       name="IPV6",
+                                       host1="h1",
+                                       host2="h9",
+                                       deviceId1="of:0000000000000005/1",
+                                       deviceId2="of:0000000000000006/1",
+                                       port1="",
+                                       port2="",
+                                       ethType="IPV6",
+                                       mac1="00:00:00:00:00:01",
+                                       mac2="00:00:00:00:00:09",
+                                       bandwidth="",
+                                       lambdaAlloc=False,
+                                       ipProto="",
+                                       ip1="",
+                                       ip2="",
+                                       tcp1="",
+                                       tcp2="",
+                                       expectedLink=18 )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass=main.assertReturnString,
+                                 onfail=main.assertReturnString )
+
+        main.step( "IPV6_2: Add point intents between h1 and h9" )
+        main.assertReturnString = "Assertion Result for IPV6 no mac address point intents\n"
+        stepResult = main.intentFunction.pointIntent(
+                                       main,
+                                       name="IPV6_2",
+                                       host1="h1",
+                                       host2="h9",
+                                       deviceId1="of:0000000000000005/1",
+                                       deviceId2="of:0000000000000006/1",
+                                       ipProto="",
+                                       ip1="",
+                                       ip2="",
+                                       tcp1="",
+                                       tcp2="",
+                                       expectedLink=18 )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass=main.assertReturnString,
+                                 onfail=main.assertReturnString )
+        """
+        main.step( "SDNIP-ICMP: Add point intents between h1 and h9" )
+        main.assertReturnString = "Assertion Result for SDNIP-ICMP IPV4 using TCP point intents\n"
+        mac1 = main.hostsData[ 'h1' ][ 'mac' ]
+        mac2 = main.hostsData[ 'h9' ][ 'mac' ]
+        try:
+            ip1 = str( main.hostsData[ 'h1' ][ 'ipAddresses' ][ 0 ] ) + "/24"
+            ip2 = str( main.hostsData[ 'h9' ][ 'ipAddresses' ][ 0 ] ) + "/24"
+        except KeyError:
+            main.log.debug( "Key Error getting IP addresses of h1 | h9 in" +
+                            "main.hostsData" )
+            ip1 = main.Mininet1.getIPAddress( 'h1')
+            ip2 = main.Mininet1.getIPAddress( 'h9')
+
+        ipProto = main.params[ 'SDNIP' ][ 'icmpProto' ]
+        # Uneccessary, not including this in the selectors
+        tcp1 = main.params[ 'SDNIP' ][ 'srcPort' ]
+        tcp2 = main.params[ 'SDNIP' ][ 'dstPort' ]
+
+        stepResult = main.intentFunction.pointIntent(
+                                           main,
+                                           name="SDNIP-ICMP",
+                                           host1="h1",
+                                           host2="h9",
+                                           deviceId1="of:0000000000000005/1",
+                                           deviceId2="of:0000000000000006/1",
+                                           mac1=mac1,
+                                           mac2=mac2,
+                                           ethType="IPV6",
+                                           ipProto=ipProto,
+                                           ip1=ip1,
+                                           ip2=ip2 )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass=main.assertReturnString,
+                                 onfail=main.assertReturnString )
+
+        main.step( "SDNIP-TCP: Add point intents between h1 and h9" )
+        main.assertReturnString = "Assertion Result for SDNIP-TCP IPV4 using ICMP point intents\n"
+        mac1 = main.hostsData[ 'h1' ][ 'mac' ]
+        mac2 = main.hostsData[ 'h9' ][ 'mac' ]
+        ip1 = str( main.hostsData[ 'h1' ][ 'ipAddresses' ][ 0 ] ) + "/32"
+        ip2 = str( main.hostsData[ 'h9' ][ 'ipAddresses' ][ 0 ] ) + "/32"
+        ipProto = main.params[ 'SDNIP' ][ 'tcpProto' ]
+        tcp1 = main.params[ 'SDNIP' ][ 'srcPort' ]
+        tcp2 = main.params[ 'SDNIP' ][ 'dstPort' ]
+
+        stepResult = main.intentFunction.pointIntentTcp(
+                                           main,
+                                           name="SDNIP-TCP",
+                                           host1="h1",
+                                           host2="h9",
+                                           deviceId1="of:0000000000000005/1",
+                                           deviceId2="of:0000000000000006/1",
+                                           mac1=mac1,
+                                           mac2=mac2,
+                                           ethType="IPV4",
+                                           ipProto=ipProto,
+                                           ip1=ip1,
+                                           ip2=ip2,
+                                           tcp1=tcp1,
+                                           tcp2=tcp2 )
+
+        utilities.assert_equals( expect=main.TRUE,
+                             actual=stepResult,
+                                 onpass=main.assertReturnString,
+                                 onfail=main.assertReturnString )
+
+        main.step( "DUALSTACK1: Add point intents between h3 and h11" )
+        main.assertReturnString = "Assertion Result for Dualstack1 IPV4 with mac address point intents\n"
+        stepResult = main.intentFunction.pointIntent(
+                                       main,
+                                       name="DUALSTACK1",
+                                       host1="h3",
+                                       host2="h11",
+                                       deviceId1="of:0000000000000005",
+                                       deviceId2="of:0000000000000006",
+                                       port1="3",
+                                       port2="3",
+                                       ethType="IPV4",
+                                       mac1="00:00:00:00:00:03",
+                                       mac2="00:00:00:00:00:0B",
+                                       bandwidth="",
+                                       lambdaAlloc=False,
+                                       ipProto="",
+                                       ip1="",
+                                       ip2="",
+                                       tcp1="",
+                                       tcp2="",
+                                       sw1="s5",
+                                       sw2="s2",
+                                       expectedLink=18 )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass=main.assertReturnString,
+                                 onfail=main.assertReturnString )
+
+        main.step( "VLAN: Add point intents between h5 and h21" )
+        main.assertReturnString = "Assertion Result for VLAN IPV4 with mac address point intents\n"
+        stepResult = main.intentFunction.pointIntent(
+                                       main,
+                                       name="VLAN",
+                                       host1="h5",
+                                       host2="h21",
+                                       deviceId1="of:0000000000000005/5",
+                                       deviceId2="of:0000000000000007/5",
+                                       port1="",
+                                       port2="",
+                                       ethType="IPV4",
+                                       mac1="00:00:00:00:00:05",
+                                       mac2="00:00:00:00:00:15",
+                                       bandwidth="",
+                                       lambdaAlloc=False,
+                                       ipProto="",
+                                       ip1="",
+                                       ip2="",
+                                       tcp1="",
+                                       tcp2="",
+                                       sw1="s5",
+                                       sw2="s2",
+                                       expectedLink=18 )
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass=main.assertReturnString,
+                                 onfail=main.assertReturnString )
+
+        main.step( "1HOP: Add point intents between h1 and h3" )
+        main.assertReturnString = "Assertion Result for 1HOP IPV4 with no mac address point intents\n"
+        stepResult = main.intentFunction.hostIntent( main,
+                                              name='1HOP',
+                                              host1='h1',
+                                              host2='h9',
+                                              host1Id='00:00:00:00:00:01/-1',
+                                              host2Id='00:00:00:00:00:09/-1')
+
+        utilities.assert_equals( expect=main.TRUE,
+                                 actual=stepResult,
+                                 onpass=main.assertReturnString,
+                                 onfail=main.assertReturnString )
+        """
+        main.intentFunction.report( main )
diff --git a/TestON/tests/FUNCipv6Intent/README b/TestON/tests/FUNCipv6Intent/README
new file mode 100644
index 0000000..3a2dd91
--- /dev/null
+++ b/TestON/tests/FUNCipv6Intent/README
@@ -0,0 +1,39 @@
+Summary:
+        This test suite consist of basic intent IPv6 functionality testing.
+        The following is an overview of how point-to-point intents are being tested.
+        Steps:
+            - Discover IPv6 hosts with ICMP6 ping
+            - Add point intents
+            - Check intents
+            - Verify flows
+            - ICMP6 ping of all hosts
+            - Reroute
+                - Link down
+                - Verify flows
+                - Check topology
+                - Ping hosts
+                - Link up
+                - Verify flows
+                - Check topology
+                - Ping hosts
+            - Verify intents with VLAN-id
+            - Remove intents
+        This test suite includes testing of different types of intents such as
+        host, point, single-to-multi and multi-to-single ( More intent types to
+        add later ). The same steps above is being performed to other type of
+        intents.
+
+Required:
+        This test requires Mininet topology file newFuncIntent.py that is in the
+        Dependency folder. You should run the topology file to check for any
+        missing packages. The mininet topology file has different type of hosts
+        including VLAN hosts. Therefore you need to install VLAN module to build
+        the topology correctly.
+
+VLAN configuration:
+        Execute command:
+            $ sudo apt-get install vlan
+        Configuration:
+            $ sudo modprobe 8021q
+        NOTE:To make this configuration permanent
+            $ sudo su -c 'echo "8021q" >> /etc/modules'
diff --git a/TestON/tests/FUNCoptical/README b/TestON/tests/FUNCoptical/README
new file mode 100644
index 0000000..48a4f5f
--- /dev/null
+++ b/TestON/tests/FUNCoptical/README
@@ -0,0 +1,11 @@
+Summary:
+        This test suite consist of basic optical functionality testing.
+        It bings up Link-OE topology to simulate optical switches.
+        The following is an overview of the basic functionality that is
+        performed in this test.
+        Steps:
+            - Discover hosts
+            - Compare Mininet topology
+            - Add and test point intents
+            - Add and test host intents
+ 
diff --git a/TestON/tests/FUNCovsdbtest/README b/TestON/tests/FUNCovsdbtest/README
new file mode 100644
index 0000000..e73cc26
--- /dev/null
+++ b/TestON/tests/FUNCovsdbtest/README
@@ -0,0 +1,2 @@
+TODO:
+    Brief summary of the test and test cases. 
diff --git a/TestON/tests/HAclusterRestart/README b/TestON/tests/HAclusterRestart/README
new file mode 100644
index 0000000..033598c
--- /dev/null
+++ b/TestON/tests/HAclusterRestart/README
@@ -0,0 +1 @@
+Summary: Fill me in please!
diff --git a/TestON/tests/HAsingleInstanceRestart/README b/TestON/tests/HAsingleInstanceRestart/README
new file mode 100644
index 0000000..033598c
--- /dev/null
+++ b/TestON/tests/HAsingleInstanceRestart/README
@@ -0,0 +1 @@
+Summary: Fill me in please!
diff --git a/TestON/tests/SAMPstartTemplate/README b/TestON/tests/SAMPstartTemplate/README
new file mode 100644
index 0000000..359943e
--- /dev/null
+++ b/TestON/tests/SAMPstartTemplate/README
@@ -0,0 +1,5 @@
+Summary:
+        This is a Sample test suite that demonstrates starting up ONOS
+        and scalling to multiple instances. It also has extra
+        functionalilty that allows the tester to bypass the ONOS
+        package and install case (case 2) to save time.
diff --git a/TestON/tests/SCPFflowTp1g/README b/TestON/tests/SCPFflowTp1g/README
index 613bd13..e43e6ea 100644
--- a/TestON/tests/SCPFflowTp1g/README
+++ b/TestON/tests/SCPFflowTp1g/README
@@ -1,29 +1,31 @@
 FLOW THROUGHPUT
 
-Summary: This is a performance test suite to test the flow throughput 
-    capabilities of ONOS with various controller cluster sizes. 
+Summary:
+        This is a performance test suite to test the flow throughput
+        capabilities of ONOS with various controller cluster sizes. This
+        This test uses the null-provider to simulate a network topology
+        and tests the throughput via a python script called flow-tester.py.
 
-Pre-requisites: To run out-of-the box this test requires 7 NODES. 
-    OC1->OC7 must be set before initiating the test. Passwordless login 
-    must be set from TestStation "admin" root user. 
+Pre-requisites: To run out-of-the box this test requires 7 NODES.
+    OC1->OC7 must be set before initiating the test. Passwordless login
+    must be set from TestStation "admin" root user.
 
-***If you wish to run this test with less than 7 nodes the following 
+***If you wish to run this test with less than 7 nodes the following
     alterations must be made:
 
 NOTE: Only scale sizes 1,3,5 and 7 will be functional
 
---In the .params, remove any values in the comma separated list in the 
-    <scale> tag that are above your desired cluster size. 
+Modifying .params file:
+-- Remove any values in the comma separated list in the
+    <scale> tag that are above your desired cluster size.
 
---In the .params file remove one instance of “1,2” from the <testcases> 
-    tag for each value you removed from <scale> (case 1 and 2 are each 
+-- Remove one instance of “1,2” from the <testcases>
+    tag for each value you removed from <scale> (case 1 and 2 are each
     called once for each scale value)
 
---In the .params file, change the value in the <max> tag to your 
-    desired scale size (1,3, or 5)
+-- Change the value in the <max> tag to your desired scale size (1,3, or 5)
 
---In the .topo file, change the <ONOSbench/COMPONENTS/nodes> tag to your 
-    desired scale size 
+Modifying .topo file:
+-- Change the <ONOSbench/COMPONENTS/nodes> tag to your desired scale size
 
---Also in the .topo file, you will need to remove all unneeded <ONOS X 
-    cli> tags and their contents 
+-- Remove all unneeded <ONOS#cli> tags and their contents
diff --git a/TestON/tests/SCPFintentEventTp/README b/TestON/tests/SCPFintentEventTp/README
index 8de1428..980c748 100644
--- a/TestON/tests/SCPFintentEventTp/README
+++ b/TestON/tests/SCPFintentEventTp/README
@@ -1,29 +1,28 @@
 INTENT EVENT THROUGHPUT
 
-Summary: This is a performance test suite to test the intent 
-    throughput capabilities of ONOS with various controller cluster sizes. 
+Summary: This is a performance test suite to test the intent
+    throughput capabilities of ONOS with various controller cluster sizes.
 
-Pre-requisites: To run out-of-the box this test requires 7 NODES. OC1->OC7 
-    must be set before initiating the test. Passwordless login must be set 
-    from TestStation "admin" root user. 
+Pre-requisites: To run out-of-the box this test requires 7 NODES. OC1->OC7
+    must be set before initiating the test. Passwordless login must be set
+    from TestStation "admin" root user.
 
-***If you wish to run this test with less than 7 nodes the following 
-    alterations must be made: 
+***If you wish to run this test with less than 7 nodes the following
+    alterations must be made:
 
 NOTE: Only scale sizes 1,3,5 and 7 will be functional
 
---In the .params, remove any values in the comma separated list in the 
-    <scale> tag that are above your desired cluster size. 
+Modifying .params file:
+-- Remove any values in the comma separated list in the
+    <scale> tag that are above your desired cluster size.
 
---In the .params file remove one instance of “1,2” from the <testcases> 
-    tag for each value you removed from <scale> (case 1 and 2 are each 
+-- Remove one instance of “1,2” from the <testcases>
+    tag for each value you removed from <scale> (case 1 and 2 are each
     called once for each scale value)
 
---In the .params file, change the value in the <max> tag to your desired 
-    scale size (1,3, or 5)
+-- Change the value in the <max> tag to your desired scale size (1,3, or 5)
 
---In the .topo file, change the <ONOSbench/COMPONENTS/nodes> tag to your 
-    desired scale size 
+Modifying .topo file:
+-- Change the <ONOSbench/COMPONENTS/nodes> tag to your desired scale size
 
---Also in the .topo file, you will need to remove all unneeded <ONOS X cli> 
-    tags and their contents 
+-- Remove all unneeded <ONOS#cli> tags and their contents
diff --git a/TestON/tests/SCPFintentInstallWithdrawLat/README b/TestON/tests/SCPFintentInstallWithdrawLat/README
index 864739b..0dc53cd 100644
--- a/TestON/tests/SCPFintentInstallWithdrawLat/README
+++ b/TestON/tests/SCPFintentInstallWithdrawLat/README
@@ -1,31 +1,30 @@
-INTENT INSTALL/WITHDRAW LATENCY 
+INTENT INSTALL/WITHDRAW LATENCY
 
-Summary: This is a performance test designed to benchmark the 
-    latency of installing intents and withdrawing intents. (intent 
-    install and intent withdraw are separate operations with 
-    independent time data) 
+Summary: This is a performance test designed to benchmark the
+    latency of installing intents and withdrawing intents. (intent
+    install and intent withdraw are separate operations with
+    independent time data)
 
-Pre-requisites: To run out-of-the box this test requires 7 NODES. 
-    OC1->OC7 must be set before initiating the test. Passwordless 
-    login must be set from TestStation "admin" root user. 
+Pre-requisites: To run out-of-the box this test requires 7 NODES.
+    OC1->OC7 must be set before initiating the test. Passwordless
+    login must be set from TestStation "admin" root user.
 
-***If you wish to run this test with less than 7 nodes the 
-    following alterations must be made: 
+***If you wish to run this test with less than 7 nodes the
+    following alterations must be made:
 
 NOTE: Only scale sizes 1,3,5 and 7 will be functional
 
---In the .params, remove any values in the comma separated list 
-    in the <scale> tag that are above your desired cluster size. 
+Modifying .params file:
+-- Remove any values in the comma separated list in the <scale>
+    tag that are above your desired cluster size.
 
---In the .params file remove one instance of “1,2” from the 
-    <testcases> tag for each value you removed from <scale> (case 
-    1 and 2 are each called once for each scale value)
+-- Remove one instance of “1,2” from the <testcases> tag for each
+    value you removed from <scale> (case 1 and 2 are each called
+    once for each scale value)
 
---In the .params file, change the value in the <max> tag to your 
-    desired scale size (1,3, or 5)
+-- Change the value in the <max> tag to your desired scale size (1,3,5)
 
---In the .topo file, change the <ONOSbench/COMPONENTS/nodes> tag 
-    to your desired scale size 
+Modifying .topo file:
+-- Change the <ONOSbench/COMPONENTS/nodes> tag to your desired scale size
 
---Also in the .topo file, you will need to remove all unneeded 
-    <ONOS X cli> tags and their contents 
+-- Remove all unneeded <ONOS#cli> tags and their contents
diff --git a/TestON/tests/SCPFintentRerouteLat/README b/TestON/tests/SCPFintentRerouteLat/README
index 6ad9cce..af912f1 100644
--- a/TestON/tests/SCPFintentRerouteLat/README
+++ b/TestON/tests/SCPFintentRerouteLat/README
@@ -1,29 +1,29 @@
-INTENT REROUTE LATENCY 
+INTENT REROUTE LATENCY
 
-Summary: This is a performance test designed to benchmark the 
-    intent reroute speed of ONOS at various controller cluster sizes. 
+Summary: This is a performance test designed to benchmark the
+    intent reroute speed of ONOS at various controller cluster sizes.
 
-Pre-requisites: To run out-of-the box this test requires 7 NODES. 
-    OC1->OC7 must be set before initiating the test. Passwordless login 
-    must be set from TestStation "admin" root user. 
+Pre-requisites: To run out-of-the box this test requires 7 NODES.
+    OC1->OC7 must be set before initiating the test. Passwordless login
+    must be set from TestStation "admin" root user.
 
-***If you wish to run this test with less than 7 nodes the 
+***If you wish to run this test with less than 7 nodes the
     following alterations must be made:
 
 NOTE: Only scale sizes 1,3,5 and 7 will be functional
 
---In the .params, remove any values in the comma separated list in 
-    the <scale> tag that are above your desired cluster size. 
+Modifying .params file:
+-- Remove any values in the comma separated list in
+    the <scale> tag that are above your desired cluster size.
 
---In the .params file remove one instance of “1,2” from the 
-    <testcases> tag for each value you removed from <scale> (case 
-    1 and 2 are each called once for each scale value)
+-- Remove one instance of “1,2” from the <testcases> tag for
+    each value you removed from <scale> (case1 and 2 are each
+    called once for each scale value)
 
---In the .params file, change the value in the <max> tag to your 
-    desired scale size (1,3, or 5)
+-- Change the value in the <max> tag to your desired scale size (1,3,5)
 
---In the .topo file, change the <ONOSbench/COMPONENTS/nodes> tag to 
-    your desired scale size 
+Modifying .topo file:
+-- Change the <ONOSbench/COMPONENTS/nodes> tag to
+    your desired scale size
 
---Also in the .topo file, you will need to remove all unneeded 
-    <ONOS X cli> tags and their contents 
+-- Remove all unneeded <ONOS#cli> tags and their contents
diff --git a/TestON/tests/SCPFmaxIntents/README b/TestON/tests/SCPFmaxIntents/README
new file mode 100644
index 0000000..cb53df8
--- /dev/null
+++ b/TestON/tests/SCPFmaxIntents/README
@@ -0,0 +1,6 @@
+Summary:
+        This is a performance test suit, designed to test the upper limits
+        of onos and ovsdb with respect to installing intents and rerouting flows.
+NOTE:
+        This test is largely based on the hardware used to run onos and mininet.
+        Therefore, results will very test station to test station.
diff --git a/TestON/tests/SCPFscaleTopo/README b/TestON/tests/SCPFscaleTopo/README
new file mode 100644
index 0000000..16df150
--- /dev/null
+++ b/TestON/tests/SCPFscaleTopo/README
@@ -0,0 +1,8 @@
+Summary:
+        This is a performance test suite that is designed to test
+        large topologies. It also contains a failure case that brings
+        down an onos controller to see if the neighboring controllers
+        pick up the rest of the devices.
+NOTE:
+        This test does not scale onos controllers. The number of
+        controllers is fixed at 3.
diff --git a/TestON/tests/SCPFswitchLat/README b/TestON/tests/SCPFswitchLat/README
new file mode 100644
index 0000000..b86ca6f
--- /dev/null
+++ b/TestON/tests/SCPFswitchLat/README
@@ -0,0 +1,31 @@
+SWITCH LATENCY
+
+Summary: This is a performance test suite to measure the time it takes ONOS
+        to recognize a switch going up and down.
+
+Pre-requisites: To run out-of-the box this test requires 7 NODES.
+    OC1->OC7 must be set before initiating the test. Passwordless login
+    must be set from TestStation "admin" root user. The 7 NODES must have
+    their clocks synced to TestStation via ptpd and be accurate to the
+    millisecond. You will also need the Wireshark disector to see openflow packets.
+
+*** If you wish to run this test with less than 7 nodes the following
+    alterations must be made:
+
+NOTE: Only scale sizes 1,3,5 and 7 will be functional
+
+Modifying .params file:
+-- Remove any values in the comma separated list in the
+    <scale> tag that are above your desired cluster size.
+
+-- Remove one instance of “1,2” from the <testcases> tag for each
+    value you removed from <scale> (case 1 and 2 are each called once
+    for each scale value)
+
+-- Change the value in the <max> tag to your desired scale size (1,3,5)
+
+Modifying .topo file:
+-- Change the <ONOSbench/COMPONENTS/nodes> tag to your
+    desired scale size
+
+-- Remove all unneeded <ONOS#cli> tags and their contents
diff --git a/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/Functions.py b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/Functions.py
new file mode 100644
index 0000000..8d4007a
--- /dev/null
+++ b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/Functions.py
@@ -0,0 +1,178 @@
+
+def checkRouteNum( main, routeNumExpected, ONOScli = "ONOScli1" ):
+    main.step( "Check routes installed" )
+    main.log.info( "Route number expected:" )
+    main.log.info( routeNumExpected )
+    main.log.info( "Route number from ONOS CLI:" )
+
+    if ONOScli == "ONOScli1":
+        routeNumActual = main.ONOScli1.ipv4RouteNumber()
+    else:
+        routeNumActual = main.ONOScli2.ipv4RouteNumber()
+
+    main.log.info( routeNumActual )
+    utilities.assertEquals( \
+        expect = routeNumExpected, actual = routeNumActual,
+        onpass = "Route number is correct!",
+        onfail = "Route number is wrong!" )
+
+def checkM2SintentNum( main, intentNumExpected, ONOScli = "ONOScli1" ):
+    main.step( "Check M2S intents installed" )
+    main.log.info( "Intent number expected:" )
+    main.log.info( intentNumExpected )
+    main.log.info( "Intent number from ONOS CLI:" )
+    if ONOScli == "ONOScli1":
+        jsonResult = main.ONOScli1.intents( jsonFormat = True, summary = True,
+                                            TYPE = "multiPointToSinglePoint" )
+    else:
+        jsonResult = main.ONOScli2.intents( jsonFormat = True, summary = True,
+                                            TYPE = "multiPointToSinglePoint" )
+    intentNumActual = jsonResult['installed']
+    main.log.info( intentNumActual )
+    utilities.assertEquals( \
+        expect = intentNumExpected, actual = intentNumActual,
+        onpass = "M2S intent number is correct!",
+        onfail = "M2S intent number is wrong!" )
+
+def checkP2PintentNum( main, intentNumExpected, ONOScli = "ONOScli1" ):
+    main.step( "Check P2P intents installed" )
+    main.log.info( "Intent number expected:" )
+    main.log.info( intentNumExpected )
+    main.log.info( "Intent number from ONOS CLI:" )
+    if ONOScli == "ONOScli1":
+        jsonResult = main.ONOScli1.intents( jsonFormat = True, summary = True,
+                                            TYPE = "pointToPoint" )
+    else:
+        jsonResult = main.ONOScli2.intents( jsonFormat = True, summary = True,
+                                            TYPE = "pointToPoint" )
+    intentNumActual = jsonResult['installed']
+    main.log.info( intentNumActual )
+    utilities.assertEquals( \
+        expect = intentNumExpected, actual = intentNumActual,
+        onpass = "P2P intent number is correct!",
+        onfail = "P2P intent number is wrong!" )
+
+def checkFlowNum( main, switch, flowNumExpected ):
+    main.step( "Check flow entry number in " + switch )
+    main.log.info( "Flow number expected:" )
+    main.log.info( flowNumExpected )
+    main.log.info( "Flow number actual:" )
+    flowNumActual = main.Mininet.getSwitchFlowCount( switch )
+    main.log.info( flowNumActual )
+    utilities.assertEquals( \
+        expect = flowNumExpected, actual = flowNumActual,
+        onpass = "Flow number in " + switch + " is correct!",
+        onfail = "Flow number in " + switch + " is wrong!" )
+
+
+def pingSpeakerToPeer( main, speakers = ["speaker1"],
+                       peers = ["peer64514", "peer64515", "peer64516"],
+                       expectAllSuccess = True ):
+    """
+    Carry out ping test between each BGP speaker and peer pair
+    Optional argument:
+        * speakers - BGP speakers
+        * peers - BGP peers
+        * expectAllSuccess - boolean indicating if you expect all results
+        succeed if True, otherwise expect all results fail if False
+    """
+    if len( speakers ) == 0:
+        main.log.error( "Parameter speakers can not be empty." )
+        main.cleanup()
+        main.exit()
+    if len( peers ) == 0:
+        main.log.error( "Parameter speakers can not be empty." )
+        main.cleanup()
+        main.exit()
+
+    if expectAllSuccess:
+        main.step( "BGP speakers ping peers, expect all tests to succeed" )
+    else:
+        main.step( "BGP speakers ping peers, expect all tests to fail" )
+
+    result = True
+    if expectAllSuccess:
+        for speaker in speakers:
+            for peer in peers:
+                tmpResult = main.Mininet.pingHost( src = speaker,
+                                                   target = peer )
+                result = result and ( tmpResult == main.TRUE )
+    else:
+        for speaker in speakers:
+            for peer in peers:
+                tmpResult = main.Mininet.pingHost( src = speaker,
+                                                   target = peer )
+
+    utilities.assert_equals( expect = True, actual = result,
+                             onpass = "Ping test results are expected",
+                             onfail = "Ping test results are Not expected" )
+
+    if result == False:
+        main.cleanup()
+        main.exit()
+
+
+def pingHostToHost( main, hosts = ["host64514", "host64515", "host64516"],
+                expectAllSuccess = True ):
+    """
+    Carry out ping test between each BGP host pair
+    Optional argument:
+        * hosts - hosts behind BGP peer routers
+        * expectAllSuccess - boolean indicating if you expect all results
+        succeed if True, otherwise expect all results fail if False
+    """
+    main.step( "Check ping between each host pair" )
+    if len( hosts ) == 0:
+        main.log.error( "Parameter hosts can not be empty." )
+        main.cleanup()
+        main.exit()
+
+    result = True
+    if expectAllSuccess:
+        for srcHost in hosts:
+            for targetHost in hosts:
+                if srcHost != targetHost:
+                    tmpResult = main.Mininet.pingHost( src = srcHost,
+                                                       target = targetHost )
+                    result = result and ( tmpResult == main.TRUE )
+    else:
+        for srcHost in hosts:
+            for targetHost in hosts:
+                if srcHost != targetHost:
+                    tmpResult = main.Mininet.pingHost( src = srcHost,
+                                                       target = targetHost )
+                    result = result and ( tmpResult == main.FALSE )
+
+    utilities.assert_equals( expect = True, actual = result,
+                             onpass = "Ping test results are expected",
+                             onfail = "Ping test results are Not expected" )
+
+    '''
+    if result == False:
+        main.cleanup()
+        main.exit()
+    '''
+
+
+def setupTunnel( main, srcIp, srcPort, dstIp, dstPort ):
+    """
+    Create a tunnel from Mininet host to host outside Mininet
+    """
+    main.step( "Set up tunnel from Mininet node " +
+               str( srcIp ) + ":" + str( srcPort ) + " to ONOS node "
+               + str(dstIp) + ":" + str(dstPort) )
+    forwarding = '%s:%s:%s:%s' % ( srcIp, srcPort, dstIp, dstPort )
+    command = 'ssh -nNT -o "PasswordAuthentication no" \
+        -o "StrictHostKeyChecking no" -l sdn -L %s %s & ' % ( forwarding, dstIp )
+
+
+    tunnelResult = main.TRUE
+    tunnelResult = main.Mininet.node( "root", command )
+    utilities.assert_equals( expect = True,
+                             actual = ( "PasswordAuthentication" in tunnelResult ),
+                             onpass = "Created tunnel succeeded",
+                             onfail = "Create tunnel failed" )
+    if ( "PasswordAuthentication" not in tunnelResult ) :
+        main.cleanup()
+        main.exit()
+
diff --git a/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/USECASE_SdnipI2MN_Cluster.py b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/USECASE_SdnipI2MN_Cluster.py
new file mode 100644
index 0000000..d034371
--- /dev/null
+++ b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/USECASE_SdnipI2MN_Cluster.py
@@ -0,0 +1,422 @@
+#!/usr/bin/python
+
+"""
+Set up the SDN-IP topology as same as it on Internet2
+"""
+
+"""
+AS 64513, (SDN AS)
+AS 64514, reachable by 10.0.4.1, 10.0.14.1
+AS 64515, reachable by 10.0.5.1, 10.0.15.1
+AS 64516, reachable by 10.0.6.1, 10.0.16.1
+"""
+
+from mininet.net import Mininet
+from mininet.node import Controller, RemoteController
+from mininet.log import setLogLevel, info
+from mininet.cli import CLI
+from mininet.topo import Topo
+from mininet.util import quietRun
+from mininet.moduledeps import pathCheck
+
+import os.path
+import time
+from subprocess import Popen, STDOUT, PIPE
+
+QUAGGA_DIR = '/usr/lib/quagga'
+QUAGGA_RUN_DIR = '/usr/local/var/run/quagga'
+QUAGGA_CONFIG_DIR = '~/OnosSystemTest/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/'
+numSw = 39
+
+# net = Mininet( controller = RemoteController )
+
+class SDNTopo( Topo ):
+    "SDN Topology"
+
+    def __init__( self, *args, **kwargs ):
+
+        Topo.__init__( self, *args, **kwargs )
+
+        # BGP peer hosts
+        peer64514 = self.addHost( 'peer64514' )
+        peer64515 = self.addHost( 'peer64515' )
+        peer64516 = self.addHost( 'peer64516' )
+
+        '''
+        sw1 = self.addSwitch( 'SEAT', dpid = '00000000000000a1' )
+        sw2 = self.addSwitch( 'PORT', dpid = '00000000000000a2' )
+        sw3 = self.addSwitch( 'SUNN', dpid = '00000000000000a3' )
+        sw4 = self.addSwitch( 'RENO', dpid = '00000000000000a4' )
+        sw5 = self.addSwitch( 'LOSA', dpid = '00000000000000a5' )
+        sw6 = self.addSwitch( 'MISS', dpid = '00000000000000a6' )
+        sw7 = self.addSwitch( 'LASV', dpid = '00000000000000a7' )
+        sw8 = self.addSwitch( 'SALT', dpid = '00000000000000a8' )
+        sw9 = self.addSwitch( 'PHOE', dpid = '00000000000000a9' )
+        sw10 = self.addSwitch( 'TUCS', dpid = '0000000000000a10' )
+        sw11 = self.addSwitch( 'DENV', dpid = '0000000000000a11' )
+        sw12 = self.addSwitch( 'ELPA', dpid = '0000000000000a12' )
+        sw13 = self.addSwitch( 'MINN', dpid = '0000000000000a13' )
+        sw14 = self.addSwitch( 'KANS', dpid = '0000000000000a14' )
+        sw15 = self.addSwitch( 'TULS', dpid = '0000000000000a15' )
+        sw16 = self.addSwitch( 'DALL', dpid = '0000000000000a16' )
+        sw17 = self.addSwitch( 'HOUH', dpid = '0000000000000a17' )
+        sw18 = self.addSwitch( 'COLU', dpid = '0000000000000a18' )
+        sw19 = self.addSwitch( 'JCSN', dpid = '0000000000000a19' )
+        sw20 = self.addSwitch( 'BATO', dpid = '0000000000000a20' )
+        sw21 = self.addSwitch( 'EQCH', dpid = '0000000000000a21' )
+        sw22 = self.addSwitch( 'STAR', dpid = '0000000000000a22' )
+        sw23 = self.addSwitch( 'CHIC', dpid = '0000000000000a23' )
+        sw24 = self.addSwitch( 'INDI', dpid = '0000000000000a24' )
+        sw25 = self.addSwitch( 'CINC', dpid = '0000000000000a25' )
+        sw26 = self.addSwitch( 'LOUI', dpid = '0000000000000a26' )
+        sw27 = self.addSwitch( 'ATLA', dpid = '0000000000000a27' )
+        sw28 = self.addSwitch( 'JACK', dpid = '0000000000000a28' )
+        sw29 = self.addSwitch( 'CLEV', dpid = '0000000000000a29' )
+        sw30 = self.addSwitch( 'PITT', dpid = '0000000000000a30' )
+        sw31 = self.addSwitch( 'ASHB', dpid = '0000000000000a31' )
+        sw32 = self.addSwitch( 'WASH', dpid = '0000000000000a32' )
+        sw33 = self.addSwitch( 'RALE', dpid = '0000000000000a33' )
+        sw34 = self.addSwitch( 'CHAR', dpid = '0000000000000a34' )
+        sw35 = self.addSwitch( 'ALBA', dpid = '0000000000000a35' )
+        sw36 = self.addSwitch( 'BOST', dpid = '0000000000000a36' )
+        sw37 = self.addSwitch( 'HART', dpid = '0000000000000a37' )
+        sw38 = self.addSwitch( 'NEWY', dpid = '0000000000000a38' )
+        sw39 = self.addSwitch( 'PHIL', dpid = '0000000000000a39' )
+        '''
+        sw1 = self.addSwitch( 'sw1', dpid = '00000000000000a1' )
+        sw2 = self.addSwitch( 'sw2', dpid = '00000000000000a2' )
+        sw3 = self.addSwitch( 'sw3', dpid = '00000000000000a3' )
+        sw4 = self.addSwitch( 'sw4', dpid = '00000000000000a4' )
+        sw5 = self.addSwitch( 'sw5', dpid = '00000000000000a5' )
+        sw6 = self.addSwitch( 'sw6', dpid = '00000000000000a6' )
+        sw7 = self.addSwitch( 'sw7', dpid = '00000000000000a7' )
+        sw8 = self.addSwitch( 'sw8', dpid = '00000000000000a8' )
+        sw9 = self.addSwitch( 'sw9', dpid = '00000000000000a9' )
+        sw10 = self.addSwitch( 'sw10', dpid = '0000000000000a10' )
+        sw11 = self.addSwitch( 'sw11', dpid = '0000000000000a11' )
+        sw12 = self.addSwitch( 'sw12', dpid = '0000000000000a12' )
+        sw13 = self.addSwitch( 'sw13', dpid = '0000000000000a13' )
+        sw14 = self.addSwitch( 'sw14', dpid = '0000000000000a14' )
+        sw15 = self.addSwitch( 'sw15', dpid = '0000000000000a15' )
+        sw16 = self.addSwitch( 'sw16', dpid = '0000000000000a16' )
+        sw17 = self.addSwitch( 'sw17', dpid = '0000000000000a17' )
+        sw18 = self.addSwitch( 'sw18', dpid = '0000000000000a18' )
+        sw19 = self.addSwitch( 'sw19', dpid = '0000000000000a19' )
+        sw20 = self.addSwitch( 'sw20', dpid = '0000000000000a20' )
+        sw21 = self.addSwitch( 'sw21', dpid = '0000000000000a21' )
+        sw22 = self.addSwitch( 'sw22', dpid = '0000000000000a22' )
+        sw23 = self.addSwitch( 'sw23', dpid = '0000000000000a23' )
+        sw24 = self.addSwitch( 'sw24', dpid = '0000000000000a24' )
+        sw25 = self.addSwitch( 'sw25', dpid = '0000000000000a25' )
+        sw26 = self.addSwitch( 'sw26', dpid = '0000000000000a26' )
+        sw27 = self.addSwitch( 'sw27', dpid = '0000000000000a27' )
+        sw28 = self.addSwitch( 'sw28', dpid = '0000000000000a28' )
+        sw29 = self.addSwitch( 'sw29', dpid = '0000000000000a29' )
+        sw30 = self.addSwitch( 'sw30', dpid = '0000000000000a30' )
+        sw31 = self.addSwitch( 'sw31', dpid = '0000000000000a31' )
+        sw32 = self.addSwitch( 'sw32', dpid = '0000000000000a32' )
+        sw33 = self.addSwitch( 'sw33', dpid = '0000000000000a33' )
+        sw34 = self.addSwitch( 'sw34', dpid = '0000000000000a34' )
+        sw35 = self.addSwitch( 'sw35', dpid = '0000000000000a35' )
+        sw36 = self.addSwitch( 'sw36', dpid = '0000000000000a36' )
+        sw37 = self.addSwitch( 'sw37', dpid = '0000000000000a37' )
+        sw38 = self.addSwitch( 'sw38', dpid = '0000000000000a38' )
+        sw39 = self.addSwitch( 'sw39', dpid = '0000000000000a39' )
+
+
+        # Add a layer2 switch for control plane connectivity
+        # This switch isn't part of the SDN topology
+        # We'll use the ovs-controller to turn this into a learning switch
+        swCtl100 = self.addSwitch( 'swCtl100', dpid = '0000000000000100' )
+
+
+        # BGP speaker hosts
+        speaker1 = self.addHost( 'speaker1' )
+        speaker2 = self.addHost( 'speaker2' )
+
+        root = self.addHost( 'root', inNamespace = False , ip = '0' )
+
+        # hosts behind each AS
+        host64514 = self.addHost( 'host64514' )
+        host64515 = self.addHost( 'host64515' )
+        host64516 = self.addHost( 'host64516' )
+
+        self.addLink( 'speaker1', sw24 )
+        self.addLink( 'speaker2', sw24 )
+
+        # connect all switches
+        self.addLink( sw1, sw2 )
+        self.addLink( sw1, sw6 )
+        self.addLink( sw1, sw8 )
+        self.addLink( sw2, sw3 )
+        self.addLink( sw3, sw4 )
+        self.addLink( sw3, sw5 )
+        self.addLink( sw4, sw8 )
+        self.addLink( sw5, sw7 )
+        self.addLink( sw5, sw9 )
+        self.addLink( sw6, sw13 )
+        self.addLink( sw7, sw8 )
+        self.addLink( sw8, sw11 )
+        self.addLink( sw9, sw10 )
+        self.addLink( sw10, sw12 )
+        self.addLink( sw11, sw12 )
+        self.addLink( sw11, sw14 )
+        self.addLink( sw12, sw17 )
+        self.addLink( sw13, sw14 )
+        self.addLink( sw13, sw21 )
+        self.addLink( sw14, sw15 )
+        self.addLink( sw14, sw18 )
+        self.addLink( sw14, sw23 )
+        self.addLink( sw15, sw16 )
+        self.addLink( sw16, sw17 )
+        self.addLink( sw17, sw19 )
+        self.addLink( sw17, sw20 )
+        self.addLink( sw18, sw23 )
+        self.addLink( sw19, sw27 )
+        self.addLink( sw20, sw28 )
+        self.addLink( sw21, sw22 )
+        self.addLink( sw21, sw29 )
+        self.addLink( sw22, sw23 )
+        self.addLink( sw23, sw24 )
+        self.addLink( sw23, sw31 )
+        self.addLink( sw24, sw25 )
+        self.addLink( sw25, sw26 )
+        self.addLink( sw26, sw27 )
+        self.addLink( sw27, sw28 )
+        self.addLink( sw27, sw34 )
+        self.addLink( sw29, sw30 )
+        self.addLink( sw29, sw35 )
+        self.addLink( sw30, sw31 )
+        self.addLink( sw31, sw32 )
+        self.addLink( sw32, sw33 )
+        self.addLink( sw32, sw39 )
+        self.addLink( sw33, sw34 )
+        self.addLink( sw35, sw36 )
+        self.addLink( sw36, sw37 )
+        self.addLink( sw37, sw38 )
+        self.addLink( sw38, sw39 )
+
+        # connection between switches and peers
+        self.addLink( peer64514, sw32 )
+        self.addLink( peer64515, sw8 )
+        self.addLink( peer64516, sw28 )
+
+        # connection between BGP peer and hosts behind the BGP peer
+        self.addLink( peer64514, host64514 )
+        self.addLink( peer64515, host64515 )
+        self.addLink( peer64516, host64516 )
+
+        # Internal Connection To Hosts
+        self.addLink( swCtl100, peer64514 )
+        self.addLink( swCtl100, peer64515 )
+        self.addLink( swCtl100, peer64516 )
+        self.addLink( swCtl100, speaker1 )
+        self.addLink( swCtl100, speaker2 )
+
+
+        # add host64514 to control plane for ping test
+        self.addLink( swCtl100, host64514 )
+        self.addLink( swCtl100, root )
+        self.addLink( swCtl100, root )
+        self.addLink( swCtl100, root )
+
+
+def startsshd( host ):
+    "Start sshd on host"
+    info( '*** Starting sshd\n' )
+    name, intf, ip = host.name, host.defaultIntf(), host.IP()
+    banner = '/tmp/%s.banner' % name
+    host.cmd( 'echo "Welcome to %s at %s" >  %s' % ( name, ip, banner ) )
+    host.cmd( '/usr/sbin/sshd -o "Banner %s"' % banner, '-o "UseDNS no"' )
+    info( '***', host.name, 'is running sshd on', intf, 'at', ip, '\n' )
+
+def startsshds ( hosts ):
+    for h in hosts:
+        startsshd( h )
+
+def stopsshd():
+    "Stop *all* sshd processes with a custom banner"
+    info( '*** Shutting down stale sshd/Banner processes ',
+          quietRun( "pkill -9 -f Banner" ), '\n' )
+
+def startquagga( host, num, config_file ):
+    info( '*** Starting Quagga on %s\n' % host )
+    host.cmd( "cd %s" % QUAGGA_CONFIG_DIR )
+    zebra_cmd = \
+    '%s/zebra -d -f  ./zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid'\
+     % ( QUAGGA_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num )
+    quagga_cmd = '%s/bgpd -d -f %s -z %s/zserv%s.api -i %s/bgpd%s.pid' \
+    % ( QUAGGA_DIR, config_file, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num )
+
+    print zebra_cmd
+    print quagga_cmd
+
+    host.cmd( zebra_cmd )
+    host.cmd( quagga_cmd )
+
+'''
+def startQuaggaFromTeston( host, num, config_file ):
+    global net
+    h = net.get( str( host ) )
+    startquagga( h, num, config_file )
+'''
+
+def startquaggahost5( host, num ):
+    info( '*** Starting Quagga on %s\n' % host )
+    zebra_cmd = \
+    '%s/zebra -d -f  ./zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid' \
+    % ( QUAGGA_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num )
+    quagga_cmd = \
+    '%s/bgpd -d -f ./as4quaggas/quagga%s.conf -z %s/zserv%s.api -i %s/bgpd%s.pid'\
+     % ( QUAGGA_DIR, num, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num )
+
+    host.cmd( zebra_cmd )
+    host.cmd( quagga_cmd )
+
+
+def stopquagga():
+    quietRun( 'sudo pkill -9 -f bgpd' )
+    quietRun( 'sudo pkill -9 -f zebra' )
+
+def sdn1net():
+    topo = SDNTopo()
+    info( '*** Creating network\n' )
+
+    # global net
+    net = Mininet( topo = topo, controller = RemoteController )
+
+
+    speaker1, speaker2, peer64514, peer64515, peer64516 = \
+    net.get( 'speaker1', 'speaker2' ,
+             'peer64514', 'peer64515', 'peer64516' )
+
+    # Adding addresses to speakers' interface connected to sw24
+    # for BGP peering
+    speaker1.setMAC( '00:00:00:00:00:01', 'speaker1-eth0' )
+    speaker1.cmd( 'ip addr add 10.0.4.101/24 dev speaker1-eth0' )
+    speaker1.cmd( 'ip addr add 10.0.5.101/24 dev speaker1-eth0' )
+    speaker1.cmd( 'ip addr add 10.0.6.101/24 dev speaker1-eth0' )
+
+    speaker1.defaultIntf().setIP( '10.0.4.101/24' )
+    speaker1.defaultIntf().setMAC( '00:00:00:00:00:01' )
+
+    speaker2.setMAC( '00:00:00:00:00:02', 'speaker2-eth0' )
+    speaker2.cmd( 'ip addr add 10.0.14.101/24 dev speaker2-eth0' )
+    speaker2.cmd( 'ip addr add 10.0.15.101/24 dev speaker2-eth0' )
+    speaker2.cmd( 'ip addr add 10.0.16.101/24 dev speaker2-eth0' )
+
+    speaker2.defaultIntf().setIP( '10.0.14.101/24' )
+    speaker2.defaultIntf().setMAC( '00:00:00:00:00:02' )
+
+    # Net has to be start after adding the above link
+    net.start()
+
+    # setup configuration on the interface connected to switch
+    peer64514.cmd( "ifconfig  peer64514-eth0 10.0.4.1 up" )
+    peer64514.cmd( "ip addr add 10.0.14.1/24 dev peer64514-eth0" )
+    peer64514.setMAC( '00:00:00:00:00:04', 'peer64514-eth0' )
+    peer64515.cmd( "ifconfig  peer64515-eth0 10.0.5.1 up" )
+    peer64515.cmd( "ip addr add 10.0.15.1/24 dev peer64515-eth0" )
+    peer64515.setMAC( '00:00:00:00:00:05', 'peer64515-eth0' )
+    peer64516.cmd( "ifconfig  peer64516-eth0 10.0.6.1 up" )
+    peer64516.cmd( "ip addr add 10.0.16.1/24 dev peer64516-eth0" )
+    peer64516.setMAC( '00:00:00:00:00:06', 'peer64516-eth0' )
+
+    # setup configuration on the interface connected to hosts
+    peer64514.setIP( "4.0.0.254", 8, "peer64514-eth1" )
+    peer64514.setMAC( '00:00:00:00:00:44', 'peer64514-eth1' )
+    peer64515.setIP( "5.0.0.254", 8, "peer64515-eth1" )
+    peer64515.setMAC( '00:00:00:00:00:55', 'peer64515-eth1' )
+    peer64516.setIP( "6.0.0.254", 8, "peer64516-eth1" )
+    peer64516.setMAC( '00:00:00:00:00:66', 'peer64516-eth1' )
+
+    # enable forwarding on BGP peer hosts
+    peer64514.cmd( 'sysctl net.ipv4.conf.all.forwarding=1' )
+    peer64515.cmd( 'sysctl net.ipv4.conf.all.forwarding=1' )
+    peer64516.cmd( 'sysctl net.ipv4.conf.all.forwarding=1' )
+
+    # config interface for control plane connectivity
+    peer64514.setIP( "192.168.0.4", 24, "peer64514-eth2" )
+    peer64515.setIP( "192.168.0.5", 24, "peer64515-eth2" )
+    peer64516.setIP( "192.168.0.6", 24, "peer64516-eth2" )
+
+    # Setup hosts in each non-SDN AS
+    host64514, host64515, host64516 = \
+    net.get( 'host64514', 'host64515', 'host64516' )
+    host64514.cmd( 'ifconfig host64514-eth0 4.0.0.1 up' )
+    host64514.cmd( 'ip route add default via 4.0.0.254' )
+    host64514.setIP( '192.168.0.44', 24, 'host64514-eth1' )  # for control plane
+    host64515.cmd( 'ifconfig host64515-eth0 5.0.0.1 up' )
+    host64515.cmd( 'ip route add default via 5.0.0.254' )
+    host64516.cmd( 'ifconfig host64516-eth0 6.0.0.1 up' )
+    host64516.cmd( 'ip route add default via 6.0.0.254' )
+
+
+    # set up swCtl100 as a learning
+    swCtl100 = net.get( 'swCtl100' )
+    swCtl100.cmd( 'ovs-vsctl set-controller swCtl100 none' )
+    swCtl100.cmd( 'ovs-vsctl set-fail-mode swCtl100 standalone' )
+
+    # connect all switches to controller
+    '''
+    onos1IP = "10.128.4.52"
+    onos2IP = "10.128.4.53"
+    onos3IP = "10.128.4.54"
+    for i in range ( 1, numSw + 1 ):
+        swX = net.get( 'sw%s' % ( i ) )
+        swX.cmd( 'ovs-vsctl set-controller sw%s tcp:%s:6653 tcp:%s:6653 tcp:%s:6653' % ( i, onos1IP, onos2IP, onos3IP) )
+    '''
+
+    # Start Quagga on border routers
+    startquagga( peer64514, 64514, 'quagga64514.conf' )
+    startquagga( peer64515, 64515, 'quagga64515.conf' )
+    startquagga( peer64516, 64516, 'quagga64516.conf' )
+
+    # start Quagga in SDN network
+    startquagga( speaker1, 64513, 'quagga-sdn.conf' )
+    startquagga( speaker2, 64512, 'quagga-sdn-speaker2.conf' )
+
+
+    root = net.get( 'root' )
+    root.intf( 'root-eth0' ).setIP( '1.1.1.2/24' )
+    root.cmd( 'ip addr add 192.168.0.100/24 dev root-eth0' )
+
+    root.intf( 'root-eth1' ).setIP( '1.1.1.4/24' )
+    root.cmd( 'ip addr add 192.168.0.101/24 dev root-eth1' )
+
+    root.intf( 'root-eth2' ).setIP( '1.1.1.6/24' )
+    root.cmd( 'ip addr add 192.168.0.102/24 dev root-eth2' )
+
+    speaker1.intf( 'speaker1-eth1' ).setIP( '1.1.1.1/24' )
+    speaker2.intf( 'speaker2-eth1' ).setIP( '1.1.1.3/24' )
+
+
+    stopsshd()
+
+    hosts = [ peer64514, peer64515, peer64516, host64514];
+    startsshds( hosts )
+
+
+    '''
+    forwarding1 = '%s:2000:%s:2000' % ( '1.1.1.2', onos1IP )
+    root.cmd( 'ssh -nNT -o "PasswordAuthentication no" \
+    -o "StrictHostKeyChecking no" -l sdn -L %s %s & ' % ( forwarding1, onos1IP ) )
+
+    forwarding2 = '%s:2000:%s:2000' % ( '1.1.1.4', onos2IP )
+    root.cmd( 'ssh -nNT -o "PasswordAuthentication no" \
+    -o "StrictHostKeyChecking no" -l sdn -L %s %s & ' % ( forwarding2, onos2IP ) )
+
+    forwarding3 = '%s:2000:%s:2000' % ( '1.1.1.6', onos3IP )
+    root.cmd( 'ssh -nNT -o "PasswordAuthentication no" \
+    -o "StrictHostKeyChecking no" -l sdn -L %s %s & ' % ( forwarding3, onos3IP ) )
+    '''
+    CLI( net )
+
+    stopsshd()
+    stopquagga()
+    net.stop()
+
+
+if __name__ == '__main__':
+    setLogLevel( 'debug' )
+    sdn1net()
diff --git a/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/fsfw.xml b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/fsfw.xml
new file mode 100644
index 0000000..4700483
--- /dev/null
+++ b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/fsfw.xml
@@ -0,0 +1,445 @@
+<flowspace_firewall>
+    <switch name="sw1" dpid="00000000000000a1" flush_rules_on_connect="false" />
+    <switch name="sw2" dpid="00000000000000a2" flush_rules_on_connect="false" />
+    <switch name="sw3" dpid="00000000000000a3" flush_rules_on_connect="false" />
+    <switch name="sw4" dpid="00000000000000a4" flush_rules_on_connect="false" />
+    <switch name="sw5" dpid="00000000000000a5" flush_rules_on_connect="false" />
+    <switch name="sw6" dpid="00000000000000a6" flush_rules_on_connect="false" />
+    <switch name="sw7" dpid="00000000000000a7" flush_rules_on_connect="false" />
+    <switch name="sw8" dpid="00000000000000a8" flush_rules_on_connect="false" />
+    <switch name="sw9" dpid="00000000000000a9" flush_rules_on_connect="false" />
+    <switch name="sw10" dpid="0000000000000a10" flush_rules_on_connect="false" />
+    <switch name="sw11" dpid="0000000000000a11" flush_rules_on_connect="false" />
+    <switch name="sw12" dpid="0000000000000a12" flush_rules_on_connect="false" />
+    <switch name="sw13" dpid="0000000000000a13" flush_rules_on_connect="false" />
+    <switch name="sw14" dpid="0000000000000a14" flush_rules_on_connect="false" />
+    <switch name="sw15" dpid="0000000000000a15" flush_rules_on_connect="false" />
+    <switch name="sw16" dpid="0000000000000a16" flush_rules_on_connect="false" />
+    <switch name="sw17" dpid="0000000000000a17" flush_rules_on_connect="false" />
+    <switch name="sw18" dpid="0000000000000a18" flush_rules_on_connect="false" />
+    <switch name="sw19" dpid="0000000000000a19" flush_rules_on_connect="false" />
+    <switch name="sw20" dpid="0000000000000a20" flush_rules_on_connect="false" />
+    <switch name="sw21" dpid="0000000000000a21" flush_rules_on_connect="false" />
+    <switch name="sw22" dpid="0000000000000a22" flush_rules_on_connect="false" />
+    <switch name="sw23" dpid="0000000000000a23" flush_rules_on_connect="false" />
+    <switch name="sw24" dpid="0000000000000a24" flush_rules_on_connect="false" />
+    <switch name="sw25" dpid="0000000000000a25" flush_rules_on_connect="false" />
+    <switch name="sw26" dpid="0000000000000a26" flush_rules_on_connect="false" />
+    <switch name="sw27" dpid="0000000000000a27" flush_rules_on_connect="false" />
+    <switch name="sw28" dpid="0000000000000a28" flush_rules_on_connect="false" />
+    <switch name="sw29" dpid="0000000000000a29" flush_rules_on_connect="false" />
+    <switch name="sw30" dpid="0000000000000a30" flush_rules_on_connect="false" />
+    <switch name="sw31" dpid="0000000000000a31" flush_rules_on_connect="false" />
+    <switch name="sw32" dpid="0000000000000a32" flush_rules_on_connect="false" />
+    <switch name="sw33" dpid="0000000000000a33" flush_rules_on_connect="false" />
+    <switch name="sw34" dpid="0000000000000a34" flush_rules_on_connect="false" />
+    <switch name="sw35" dpid="0000000000000a35" flush_rules_on_connect="false" />
+    <switch name="sw36" dpid="0000000000000a36" flush_rules_on_connect="false" />
+    <switch name="sw37" dpid="0000000000000a37" flush_rules_on_connect="false" />
+    <switch name="sw38" dpid="0000000000000a38" flush_rules_on_connect="false" />
+    <switch name="sw39" dpid="0000000000000a39" flush_rules_on_connect="false" />
+
+    <slice name="P10-ONOS-demo1">
+        <switch name="sw1" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw1-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw1-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw1-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw2" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw2-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw2-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw3" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw3-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw3-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw3-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw4" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw4-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw4-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw5" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw5-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw5-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw5-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw6" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw6-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw6-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw7" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw7-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw7-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw8" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw8-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw8-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw8-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw8-eth4">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw8-eth5">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw9" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw9-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw9-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw10" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw10-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw10-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw11" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw11-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw11-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw11-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw12" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw12-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw12-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw12-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <controller ip_address="10.128.20.11" ssl="false" port="6633"/>
+    </slice>
+    <slice name="P10-ONOS-demo2">
+        <switch name="sw13" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw13-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw13-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw13-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw14" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw14-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw14-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw14-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw14-eth4">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw14-eth5">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw15" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw15-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw15-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw16" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw16-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw16-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw17" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw17-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw17-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw17-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw17-eth4">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw18" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw18-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw18-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw19" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw19-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw19-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw20" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw20-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw20-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw21" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw21-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw21-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw21-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw22" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw22-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw22-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw23" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw23-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw23-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw23-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw23-eth4">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw23-eth5">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw24" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw24-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw24-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw24-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw24-eth4">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw25" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw25-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw25-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw26" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw26-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw26-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw27" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw27-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw27-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw27-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw27-eth4">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw28" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw28-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw28-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw28-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <controller ip_address="10.128.20.12" ssl="false" port="6633"/>
+    </slice>
+    <slice name="P10-ONOS-demo3">
+        <switch name="sw29" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw29-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw29-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw29-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw30" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw30-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw30-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw31" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw31-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw31-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw31-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw32" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw32-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw32-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw32-eth3">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw32-eth4">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw33" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw33-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw33-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw34" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw34-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw34-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw35" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw35-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw35-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw36" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw36-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw36-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw37" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw37-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw37-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw38" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw38-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw38-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <switch name="sw39" max_flows="200" flow_rate="400" packet_in_rate="100" flush_rules_on_connect="false" tag_management="true">
+            <port name="sw39-eth1">
+                 <range start="2511" end="2511"/>
+            </port>
+            <port name="sw39-eth2">
+                 <range start="2511" end="2511"/>
+            </port>
+        </switch>
+        <controller ip_address="10.128.20.13" ssl="false" port="6633"/>
+    </slice>
+
+</flowspace_firewall>
\ No newline at end of file
diff --git a/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/quagga-sdn-speaker2.conf b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/quagga-sdn-speaker2.conf
new file mode 100644
index 0000000..256e7e8
--- /dev/null
+++ b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/quagga-sdn-speaker2.conf
@@ -0,0 +1,49 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+!
+router bgp 64513
+  bgp router-id 10.0.14.101
+  timers bgp 1 3
+  !timers bgp 3 9
+  neighbor 10.0.14.1 remote-as 64514
+  neighbor 10.0.14.1 ebgp-multihop
+  neighbor 10.0.14.1 timers connect 5
+  neighbor 10.0.15.1 remote-as 64515
+  neighbor 10.0.15.1 ebgp-multihop
+  neighbor 10.0.15.1 timers connect 5
+  neighbor 10.0.16.1 remote-as 64516
+  neighbor 10.0.16.1 ebgp-multihop
+  neighbor 10.0.16.1 timers connect 5
+
+  neighbor 1.1.1.2 remote-as 64513
+  neighbor 1.1.1.2 port 2000
+  neighbor 1.1.1.2 timers connect 5
+
+  neighbor 1.1.1.4 remote-as 64513
+  neighbor 1.1.1.4 port 2000
+  neighbor 1.1.1.4 timers connect 5
+
+  neighbor 1.1.1.6 remote-as 64513
+  neighbor 1.1.1.6 port 2000
+  neighbor 1.1.1.6 timers connect 5
+
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/quagga-sdn.conf b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/quagga-sdn.conf
new file mode 100644
index 0000000..3d2a455
--- /dev/null
+++ b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/quagga-sdn.conf
@@ -0,0 +1,49 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+!
+router bgp 64513
+  bgp router-id 10.0.4.101
+  timers bgp 1 3
+  !timers bgp 3 9
+  neighbor 10.0.4.1 remote-as 64514
+  neighbor 10.0.4.1 ebgp-multihop
+  neighbor 10.0.4.1 timers connect 5
+  neighbor 10.0.5.1 remote-as 64515
+  neighbor 10.0.5.1 ebgp-multihop
+  neighbor 10.0.5.1 timers connect 5
+  neighbor 10.0.6.1 remote-as 64516
+  neighbor 10.0.6.1 ebgp-multihop
+  neighbor 10.0.6.1 timers connect 5
+
+  neighbor 1.1.1.2 remote-as 64513
+  neighbor 1.1.1.2 port 2000
+  neighbor 1.1.1.2 timers connect 5
+
+  neighbor 1.1.1.4 remote-as 64513
+  neighbor 1.1.1.4 port 2000
+  neighbor 1.1.1.4 timers connect 5
+
+  neighbor 1.1.1.6 remote-as 64513
+  neighbor 1.1.1.6 port 2000
+  neighbor 1.1.1.6 timers connect 5
+
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/quagga64514.conf b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/quagga64514.conf
new file mode 100644
index 0000000..cc056dd
--- /dev/null
+++ b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/quagga64514.conf
@@ -0,0 +1,29 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64514
+  bgp router-id 10.0.4.1
+!  timers bgp 1 3
+ neighbor 10.0.4.101 remote-as 64513
+ neighbor 10.0.14.101 remote-as 64513
+ network 4.0.0.0/24
+
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
\ No newline at end of file
diff --git a/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/quagga64515.conf b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/quagga64515.conf
new file mode 100644
index 0000000..7b45d57
--- /dev/null
+++ b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/quagga64515.conf
@@ -0,0 +1,29 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64515
+  bgp router-id 10.0.5.1
+!  timers bgp 1 3
+ neighbor 10.0.5.101 remote-as 64513
+ neighbor 10.0.15.101 remote-as 64513
+ network 5.0.0.0/24
+
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/quagga64516.conf b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/quagga64516.conf
new file mode 100644
index 0000000..20c104e
--- /dev/null
+++ b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/quagga64516.conf
@@ -0,0 +1,32 @@
+! -*- bgp -*-
+!
+! BGPd sample configuratin file
+!
+! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
+!
+hostname bgpd
+password hello
+!enable password please-set-at-here
+!
+!bgp mulitple-instance
+!
+router bgp 64516
+  bgp router-id 10.0.6.1
+!  timers bgp 1 3
+ neighbor 10.0.6.101 remote-as 64513
+ neighbor 10.0.16.101 remote-as 64513
+ network 6.0.0.0/24
+
+! neighbor 10.0.0.2 route-map set-nexthop out
+! neighbor 10.0.0.2 ebgp-multihop
+! neighbor 10.0.0.2 next-hop-self
+!
+! access-list all permit any
+!
+!route-map set-nexthop permit 10
+! match ip address all
+! set ip next-hop 10.0.0.1
+!
+!log file /usr/local/var/log/quagga/bgpd.log
+!
+log stdout
diff --git a/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/zebra.conf b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/zebra.conf
new file mode 100644
index 0000000..517db94
--- /dev/null
+++ b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/Dependency/zebra.conf
@@ -0,0 +1,26 @@
+! -*- zebra -*-
+!
+! zebra sample configuration file
+!
+! $Id: zebra.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $
+!
+hostname zebra
+password hello
+enable password 0fw0rk
+log stdout
+!
+! Interfaces description.
+!
+!interface lo
+! description test of desc.
+!
+!interface sit0
+! multicast
+
+!
+! Static default route sample.
+!
+!ip route 0.0.0.0/0 203.181.89.241
+!
+
+!log file /usr/local/var/log/quagga/zebra.log
diff --git a/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/USECASE_SdnipFunctionCluster_fsfw.params b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/USECASE_SdnipFunctionCluster_fsfw.params
new file mode 100644
index 0000000..097361d
--- /dev/null
+++ b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/USECASE_SdnipFunctionCluster_fsfw.params
@@ -0,0 +1,51 @@
+<PARAMS>
+
+    <testcases>101, 100, 200, 102, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12</testcases>
+    #Environment variables
+    <ENV>
+        <cellName>sdnip_multiple_instance_VM</cellName>
+    </ENV>
+
+    <CTRL>
+        <numCtrl>1</numCtrl>
+        <ip1>OC1</ip1>
+        <ip2>OC2</ip2>
+        <ip3>OC3</ip3>
+        <port1>6653</port1>
+    </CTRL>
+
+    <GIT>
+        <branch1>master</branch1>
+        <branch2>onos-1.3</branch2>
+    </GIT>
+
+    <JSON>
+        <prefix>prefix</prefix>
+        <nextHop>nextHop</nextHop>
+    </JSON>
+
+    <DEPENDENCY>
+        <path>/USECASE_SdnipFunctionCluster_fsfw/Dependency/</path>
+        <topology>USECASE_SdnipI2MN_Cluster.py</topology>
+        <wrapper1>Functions</wrapper1>
+        <wrapper2>USECASE_SdnipI2MN_Cluster_fsfw</wrapper2>
+    </DEPENDENCY>
+
+    <config>
+        <peerNum> 3 </peerNum>
+        <switchNum> 39 </switchNum>
+        <peer64514> 10.0.14.1</peer64514>
+        <peer64515> 10.0.15.1</peer64515>
+        <peer64516> 10.0.16.1</peer64516>
+    </config>
+
+    <timers>
+        <SdnIpSetup>10</SdnIpSetup>
+        <TopoDiscovery>10</TopoDiscovery>
+        <PingTestWithRoutes>20</PingTestWithRoutes>
+        <PingTestWithoutRoutes>100</PingTestWithoutRoutes>
+        <RouteDelivery>30</RouteDelivery>
+        <PathAvailable>20</PathAvailable>
+    </timers>
+
+</PARAMS>
diff --git a/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/USECASE_SdnipFunctionCluster_fsfw.py b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/USECASE_SdnipFunctionCluster_fsfw.py
new file mode 100644
index 0000000..7b95479
--- /dev/null
+++ b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/USECASE_SdnipFunctionCluster_fsfw.py
@@ -0,0 +1,837 @@
+# Testing the functionality of SDN-IP with single ONOS instance
+class USECASE_SdnipFunctionCluster_fsfw:
+
+    def __init__( self ):
+        self.default = ''
+        global branchName
+
+    def CASE100( self, main ):
+        """
+            Start mininet
+        """
+        import imp
+        main.log.case( "Setup the Mininet testbed" )
+        main.dependencyPath = main.testDir + \
+                              main.params[ 'DEPENDENCY' ][ 'path' ]
+        main.topology = main.params[ 'DEPENDENCY' ][ 'topology' ]
+
+        main.step( "Starting Mininet Topology" )
+        topology = main.dependencyPath + main.topology
+        topoResult = main.Mininet.startNet( topoFile = topology )
+        utilities.assert_equals( expect = main.TRUE,
+                                 actual = topoResult,
+                                 onpass = "Successfully loaded topology",
+                                 onfail = "Failed to load topology" )
+        # Exit if topology did not load properly
+        if not topoResult:
+            main.cleanup()
+            main.exit()
+        main.step( "Connect switches to controllers" )
+
+        # connect all switches to controllers
+        swResult = main.TRUE
+        for i in range ( 1, int( main.params['config']['switchNum'] ) + 1 ):
+            sw = "sw%s" % ( i )
+            swResult = swResult and main.Mininet.assignSwController( sw,
+                                                 [ONOS1Ip, ONOS2Ip, ONOS3Ip] )
+
+        utilities.assert_equals( expect = main.TRUE,
+                             actual = swResult,
+                             onpass = "Successfully connect all switches to ONOS",
+                             onfail = "Failed to connect all switches to ONOS" )
+        if not swResult:
+            main.cleanup()
+            main.exit()
+
+
+    def CASE101( self, main ):
+        """
+           Package ONOS and install it
+           Startup sequence:
+           cell <name>
+           onos-verify-cell
+           onos-package
+           onos-install -f
+           onos-wait-for-start
+        """
+        import json
+        import time
+        import os
+        from operator import eq
+
+        main.case( "Setting up ONOS environment" )
+
+        cellName = main.params[ 'ENV' ][ 'cellName' ]
+        global ONOS1Ip
+        global ONOS2Ip
+        global ONOS3Ip
+        ONOS1Ip = os.getenv( main.params[ 'CTRL' ][ 'ip1' ] )
+        ONOS2Ip = os.getenv( main.params[ 'CTRL' ][ 'ip2' ] )
+        ONOS3Ip = os.getenv( main.params[ 'CTRL' ][ 'ip3' ] )
+
+        global peer64514
+        global peer64515
+        global peer64516
+        peer64514 = main.params['config']['peer64514']
+        peer64515 = main.params['config']['peer64515']
+        peer64516 = main.params['config']['peer64516']
+
+        main.step( "Applying cell variable to environment" )
+        cellResult = main.ONOSbench.setCell( cellName )
+        utilities.assert_equals( expect = main.TRUE,
+                                 actual = cellResult,
+                                 onpass = "Set cell succeeded",
+                                 onfail = "Set cell failed" )
+
+        verifyResult = main.ONOSbench.verifyCell()
+        utilities.assert_equals( expect = main.TRUE,
+                                 actual = verifyResult,
+                                 onpass = "Verify cell succeeded",
+                                 onfail = "Verify cell failed" )
+
+        branchName = main.ONOSbench.getBranchName()
+        main.log.report( "ONOS is on branch: " + branchName )
+
+        main.log.step( "Uninstalling ONOS" )
+        uninstallResult = main.ONOSbench.onosUninstall( ONOS1Ip ) \
+                          and main.ONOSbench.onosUninstall( ONOS2Ip ) \
+                          and main.ONOSbench.onosUninstall( ONOS3Ip )
+        utilities.assert_equals( expect = main.TRUE,
+                                 actual = uninstallResult,
+                                 onpass = "Uninstall ONOS from nodes succeeded",
+                                 onfail = "Uninstall ONOS form nodes failed" )
+
+        main.ONOSbench.getVersion( report = True )
+
+        main.step( "Creating ONOS package" )
+        packageResult = main.ONOSbench.onosPackage( opTimeout = 500 )
+        utilities.assert_equals( expect = main.TRUE,
+                                 actual = packageResult,
+                                 onpass = "Package ONOS succeeded",
+                                 onfail = "Package ONOS failed" )
+
+        main.step( "Installing ONOS package" )
+        onos1InstallResult = main.ONOSbench.onosInstall( options = "-f",
+                                                         node = ONOS1Ip )
+        onos2InstallResult = main.ONOSbench.onosInstall( options = "-f",
+                                                         node = ONOS2Ip )
+        onos3InstallResult = main.ONOSbench.onosInstall( options = "-f",
+                                                         node = ONOS3Ip )
+        onosInstallResult = onos1InstallResult and onos2InstallResult \
+                            and onos3InstallResult
+        utilities.assert_equals( expect = main.TRUE,
+                                 actual = onosInstallResult,
+                                 onpass = "Install ONOS to nodes succeeded",
+                                 onfail = "Install ONOS to nodes failed" )
+
+        main.step( "Checking if ONOS is up yet" )
+        onos1UpResult = main.ONOSbench.isup( ONOS1Ip, timeout = 420 )
+        onos2UpResult = main.ONOSbench.isup( ONOS2Ip, timeout = 420 )
+        onos3UpResult = main.ONOSbench.isup( ONOS3Ip, timeout = 420 )
+        onosUpResult = onos1UpResult and onos2UpResult and onos3UpResult
+        utilities.assert_equals( expect = main.TRUE,
+                                 actual = onos1UpResult and onosUpResult,
+                                 onpass = "ONOS nodes are up",
+                                 onfail = "ONOS nodes are NOT up" )
+
+        main.step( "Checking if ONOS CLI is ready" )
+        cliResult1 = main.ONOScli1.startOnosCli( ONOS1Ip,
+                commandlineTimeout = 100, onosStartTimeout = 600 )
+        cliResult2 = main.ONOScli2.startOnosCli( ONOS2Ip,
+                commandlineTimeout = 100, onosStartTimeout = 600 )
+        cliResult = cliResult1 and cliResult2
+        utilities.assert_equals( expect = main.TRUE,
+                                 actual = cliResult,
+                                 onpass = "ONOS CLI (on node1) is ready",
+                                 onfail = "ONOS CLI (on node1) ready" )
+
+        caseResult = ( cellResult and verifyResult and
+                       packageResult and
+                       onosInstallResult and onosUpResult and cliResult )
+
+        utilities.assert_equals( expect = main.TRUE, actual = caseResult,
+                                 onpass = "ONOS startup successful",
+                                 onfail = "ONOS startup NOT successful" )
+
+        if caseResult == main.FALSE:
+            main.log.error( "ONOS startup failed!" )
+            main.cleanup()
+            main.exit()
+
+
+    def CASE200( self, main ):
+        main.case( "Activate sdn-ip application" )
+        main.log.info( "waiting link discovery......" )
+        time.sleep( int ( main.params['timers']['TopoDiscovery'] ) )
+
+        main.log.info( "Get links in the network" )
+        summaryResult = main.ONOScli1.summary()
+        linkNum = json.loads( summaryResult )[ "links" ]
+        listResult = main.ONOScli1.links( jsonFormat = False )
+        main.log.info( listResult )
+
+        if linkNum < 100:
+            main.log.error( "Link number is wrong!" )
+            main.cleanup()
+            main.exit()
+
+        main.step( "Activate sdn-ip application" )
+        activeSDNIPresult = main.ONOScli1.activateApp( "org.onosproject.sdnip" )
+        utilities.assert_equals( expect = main.TRUE,
+                                 actual = activeSDNIPresult,
+                                 onpass = "Activate SDN-IP succeeded",
+                                 onfail = "Activate SDN-IP failed" )
+        if not activeSDNIPresult:
+            main.cleanup()
+            main.exit()
+
+
+    def CASE102( self, main ):
+        '''
+        This test case is to load the methods from other Python files, and create
+        tunnels from mininet host to onos nodes.
+        '''
+        import time
+        main.case( "Load methods from other Python file and create tunnels" )
+        # load the methods from other file
+        wrapperFile1 = main.params[ 'DEPENDENCY' ][ 'wrapper1' ]
+        main.Functions = imp.load_source( wrapperFile1,
+                                          main.dependencyPath +
+                                          wrapperFile1 +
+                                          ".py" )
+        # Create tunnels
+        main.Functions.setupTunnel( main, '1.1.1.2', 2000, ONOS1Ip, 2000 )
+        main.Functions.setupTunnel( main, '1.1.1.4', 2000, ONOS2Ip, 2000 )
+        main.Functions.setupTunnel( main, '1.1.1.6', 2000, ONOS3Ip, 2000 )
+
+        main.log.info( "Wait SDN-IP to finish installing connectivity intents \
+        and the BGP paths in data plane are ready..." )
+        time.sleep( int( main.params[ 'timers' ][ 'SdnIpSetup' ] ) )
+
+        main.log.info( "Wait Quagga to finish delivery all routes to each \
+        other and to sdn-ip, plus finish installing all intents..." )
+        time.sleep( int( main.params[ 'timers' ][ 'RouteDelivery' ] ) )
+        # TODO
+        # time.sleep( int( main.params[ 'timers' ][ 'PathAvailable' ] ) )
+
+        '''
+        # TODO: use for together with wrapperFile1
+        wrapperFile2 = main.params[ 'DEPENDENCY' ][ 'wrapper2' ]
+        main.USECASE_SdnipI2MN_Cluster = imp.load_source( wrapperFile2,
+                                                         main.dependencyPath +
+                                                         wrapperFile2 +
+                                                         ".py" )
+        '''
+
+
+    def CASE1( self, main ):
+        '''
+        ping test from 3 bgp peers to BGP speaker
+        '''
+
+        main.case( "Ping tests between BGP peers and speakers" )
+        main.Functions.pingSpeakerToPeer( main, speakers = ["speaker1"],
+                       peers = ["peer64514", "peer64515", "peer64516"],
+                       expectAllSuccess = True )
+        main.Functions.pingSpeakerToPeer( main, speakers = ["speaker2"],
+                       peers = [peer64514, peer64515, peer64516],
+                       expectAllSuccess = True )
+
+
+    def CASE2( self, main ):
+        '''
+        point-to-point intents test for each BGP peer and BGP speaker pair
+        '''
+        main.case( "Check point-to-point intents" )
+        main.log.info( "There are %s BGP peers in total "
+                       % main.params[ 'config' ][ 'peerNum' ] )
+        main.step( "Check P2P intents number from ONOS CLI" )
+
+        getIntentsResult = main.ONOScli1.intents( jsonFormat = True )
+        bgpIntentsActualNum = \
+            main.QuaggaCliSpeaker1.extractActualBgpIntentNum( getIntentsResult )
+        bgpIntentsExpectedNum = int( main.params[ 'config' ][ 'peerNum' ] ) * 6 * 2
+        main.log.info( "bgpIntentsExpected num is:" )
+        main.log.info( bgpIntentsExpectedNum )
+        main.log.info( "bgpIntentsActual num is:" )
+        main.log.info( bgpIntentsActualNum )
+        utilities.assertEquals( \
+            expect = True,
+            actual = eq( bgpIntentsExpectedNum, bgpIntentsActualNum ),
+            onpass = "PointToPointIntent Intent Num is correct!",
+            onfail = "PointToPointIntent Intent Num is wrong!" )
+
+
+    def CASE3( self, main ):
+        '''
+        routes and intents check to all BGP peers
+        '''
+        main.case( "Check routes and M2S intents to all BGP peers" )
+
+        allRoutesExpected = []
+        allRoutesExpected.append( "4.0.0.0/24" + "/" + "10.0.4.1" )
+        allRoutesExpected.append( "5.0.0.0/24" + "/" + "10.0.5.1" )
+        allRoutesExpected.append( "6.0.0.0/24" + "/" + "10.0.6.1" )
+
+        getRoutesResult = main.ONOScli1.routes( jsonFormat = True )
+        allRoutesActual = \
+            main.QuaggaCliSpeaker1.extractActualRoutesMaster( getRoutesResult )
+        allRoutesStrExpected = str( sorted( allRoutesExpected ) )
+        allRoutesStrActual = str( allRoutesActual ).replace( 'u', "" )
+
+        main.step( "Check routes installed" )
+        main.log.info( "Routes expected:" )
+        main.log.info( allRoutesStrExpected )
+        main.log.info( "Routes get from ONOS CLI:" )
+        main.log.info( allRoutesStrActual )
+        utilities.assertEquals( \
+            expect = allRoutesStrExpected, actual = allRoutesStrActual,
+            onpass = "Routes are correct!",
+            onfail = "Routes are wrong!" )
+
+        main.step( "Check M2S intents installed" )
+        getIntentsResult = main.ONOScli1.intents( jsonFormat = True )
+        routeIntentsActualNum = \
+            main.QuaggaCliSpeaker1.extractActualRouteIntentNum( getIntentsResult )
+        routeIntentsExpectedNum = 3
+
+        main.log.info( "MultiPointToSinglePoint Intent Num expected is:" )
+        main.log.info( routeIntentsExpectedNum )
+        main.log.info( "MultiPointToSinglePoint Intent NUM Actual is:" )
+        main.log.info( routeIntentsActualNum )
+        utilities.assertEquals( \
+            expect = True,
+            actual = eq( routeIntentsExpectedNum, routeIntentsActualNum ),
+            onpass = "MultiPointToSinglePoint Intent Num is correct!",
+            onfail = "MultiPointToSinglePoint Intent Num is wrong!" )
+
+        main.step( "Check whether all flow status are ADDED" )
+        utilities.assertEquals( \
+            expect = main.TRUE,
+            actual = main.ONOScli1.checkFlowsState( isPENDING_ADD = False ),
+            onpass = "Flow status is correct!",
+            onfail = "Flow status is wrong!" )
+
+
+    def CASE4( self, main ):
+        '''
+        Ping test in data plane for each route
+        '''
+        main.case( "Ping test for each route, all hosts behind BGP peers" )
+        main.Functions.pingHostToHost( main,
+                        hosts = ["host64514", "host64515", "host64516"],
+                        expectAllSuccess = True )
+
+
+    def CASE5( self, main ):
+        '''
+        Cut links to peers one by one, check routes/intents
+        '''
+        import time
+        main.case( "Bring down links and check routes/intents" )
+        main.step( "Bring down the link between sw32 and peer64514" )
+        linkResult1 = main.Mininet.link( END1 = "sw32", END2 = "peer64514",
+                                         OPTION = "down" )
+        utilities.assertEquals( expect = main.TRUE,
+                                actual = linkResult1,
+                                onpass = "Bring down link succeeded!",
+                                onfail = "Bring down link failed!" )
+
+        if linkResult1 == main.TRUE:
+            time.sleep( int( main.params[ 'timers' ][ 'RouteDelivery' ] ) )
+            main.Functions.checkRouteNum( main, 2 )
+            main.Functions.checkM2SintentNum( main, 2 )
+        else:
+            main.log.error( "Bring down link failed!" )
+            main.cleanup()
+            main.exit()
+
+        main.step( "Bring down the link between sw8 and peer64515" )
+        linkResult2 = main.Mininet.link( END1 = "sw8", END2 = "peer64515",
+                                         OPTION = "down" )
+        utilities.assertEquals( expect = main.TRUE,
+                                actual = linkResult2,
+                                onpass = "Bring down link succeeded!",
+                                onfail = "Bring down link failed!" )
+        if linkResult2 == main.TRUE:
+            time.sleep( int( main.params[ 'timers' ][ 'RouteDelivery' ] ) )
+            main.Functions.checkRouteNum( main, 1 )
+            main.Functions.checkM2SintentNum( main, 1 )
+        else:
+            main.log.error( "Bring down link failed!" )
+            main.cleanup()
+            main.exit()
+
+        main.step( "Bring down the link between sw28 and peer64516" )
+        linkResult3 = main.Mininet.link( END1 = "sw28", END2 = "peer64516",
+                                         OPTION = "down" )
+        utilities.assertEquals( expect = main.TRUE,
+                                actual = linkResult3,
+                                onpass = "Bring down link succeeded!",
+                                onfail = "Bring down link failed!" )
+        if linkResult3 == main.TRUE:
+            time.sleep( int( main.params[ 'timers' ][ 'RouteDelivery' ] ) )
+            main.Functions.checkRouteNum( main, 0 )
+            main.Functions.checkM2SintentNum( main, 0 )
+        else:
+            main.log.error( "Bring down link failed!" )
+            main.cleanup()
+            main.exit()
+
+        main.step( "Check whether all flow status are ADDED" )
+        utilities.assertEquals( \
+            expect = main.TRUE,
+            actual = main.ONOScli1.checkFlowsState( isPENDING_ADD = False ),
+            onpass = "Flow status is correct!",
+            onfail = "Flow status is wrong!" )
+
+        # Ping test
+        main.Functions.pingSpeakerToPeer( main, speakers = ["speaker1"],
+                       peers = ["peer64514", "peer64515", "peer64516"],
+                       expectAllSuccess = False )
+        main.Functions.pingHostToHost( main,
+                        hosts = ["host64514", "host64515", "host64516"],
+                        expectAllSuccess = False )
+
+
+    def CASE6( self, main ):
+        '''
+        Recover links to peers one by one, check routes/intents
+        '''
+        import time
+        main.case( "Bring up links and check routes/intents" )
+        main.step( "Bring up the link between sw32 and peer64514" )
+        linkResult1 = main.Mininet.link( END1 = "sw32", END2 = "peer64514",
+                                         OPTION = "up" )
+        utilities.assertEquals( expect = main.TRUE,
+                                actual = linkResult1,
+                                onpass = "Bring up link succeeded!",
+                                onfail = "Bring up link failed!" )
+        if linkResult1 == main.TRUE:
+            time.sleep( int( main.params[ 'timers' ][ 'RouteDelivery' ] ) )
+            main.Functions.checkRouteNum( main, 1 )
+            main.Functions.checkM2SintentNum( main, 1 )
+        else:
+            main.log.error( "Bring up link failed!" )
+            main.cleanup()
+            main.exit()
+
+        main.step( "Bring up the link between sw8 and peer64515" )
+        linkResult2 = main.Mininet.link( END1 = "sw8", END2 = "peer64515",
+                                         OPTION = "up" )
+        utilities.assertEquals( expect = main.TRUE,
+                                actual = linkResult2,
+                                onpass = "Bring up link succeeded!",
+                                onfail = "Bring up link failed!" )
+        if linkResult2 == main.TRUE:
+            time.sleep( int( main.params[ 'timers' ][ 'RouteDelivery' ] ) )
+            main.Functions.checkRouteNum( main, 2 )
+            main.Functions.checkM2SintentNum( main, 2 )
+        else:
+            main.log.error( "Bring up link failed!" )
+            main.cleanup()
+            main.exit()
+
+        main.step( "Bring up the link between sw28 and peer64516" )
+        linkResult3 = main.Mininet.link( END1 = "sw28", END2 = "peer64516",
+                                         OPTION = "up" )
+        utilities.assertEquals( expect = main.TRUE,
+                                actual = linkResult3,
+                                onpass = "Bring up link succeeded!",
+                                onfail = "Bring up link failed!" )
+        if linkResult3 == main.TRUE:
+            time.sleep( int( main.params[ 'timers' ][ 'RouteDelivery' ] ) )
+            main.Functions.checkRouteNum( main, 3 )
+            main.Functions.checkM2SintentNum( main, 3 )
+        else:
+            main.log.error( "Bring up link failed!" )
+            main.cleanup()
+            main.exit()
+
+        main.step( "Check whether all flow status are ADDED" )
+        utilities.assertEquals( \
+            expect = main.TRUE,
+            actual = main.ONOScli1.checkFlowsState( isPENDING_ADD = False ),
+            onpass = "Flow status is correct!",
+            onfail = "Flow status is wrong!" )
+
+        # Ping test
+        main.Functions.pingSpeakerToPeer( main, speakers = ["speaker1"],
+                       peers = ["peer64514", "peer64515", "peer64516"],
+                       expectAllSuccess = True )
+        main.Functions.pingHostToHost( main,
+                        hosts = ["host64514", "host64515", "host64516"],
+                        expectAllSuccess = True )
+
+
+    def CASE7( self, main ):
+        '''
+        Shut down a edge switch, check P-2-P and M-2-S intents, ping test
+        '''
+        import time
+        main.case( "Stop edge sw32,check P-2-P and M-2-S intents, ping test" )
+        main.step( "Stop sw32" )
+        result = main.Mininet.switch( SW = "sw32", OPTION = "stop" )
+        utilities.assertEquals( expect = main.TRUE, actual = result,
+                                onpass = "Stopping switch succeeded!",
+                                onfail = "Stopping switch failed!" )
+
+        if result == main.TRUE:
+            time.sleep( int( main.params[ 'timers' ][ 'RouteDelivery' ] ) )
+            main.Functions.checkRouteNum( main, 2 )
+            main.Functions.checkM2SintentNum( main, 2 )
+            main.Functions.checkP2PintentNum( main, 12 * 2 )
+        else:
+            main.log.error( "Stopping switch failed!" )
+            main.cleanup()
+            main.exit()
+
+        main.step( "Check ping between hosts behind BGP peers" )
+        result1 = main.Mininet.pingHost( src = "host64514", target = "host64515" )
+        result2 = main.Mininet.pingHost( src = "host64515", target = "host64516" )
+        result3 = main.Mininet.pingHost( src = "host64514", target = "host64516" )
+
+        pingResult1 = ( result1 == main.FALSE ) and ( result2 == main.TRUE ) \
+                      and ( result3 == main.FALSE )
+        utilities.assert_equals( expect = True, actual = pingResult1,
+                                 onpass = "Ping test result is correct",
+                                 onfail = "Ping test result is wrong" )
+
+        if pingResult1 == False:
+            main.cleanup()
+            main.exit()
+
+        main.step( "Check ping between BGP peers and speaker1" )
+        result4 = main.Mininet.pingHost( src = "speaker1", target = "peer64514" )
+        result5 = main.Mininet.pingHost( src = "speaker1", target = "peer64515" )
+        result6 = main.Mininet.pingHost( src = "speaker1", target = "peer64516" )
+
+        pingResult2 = ( result4 == main.FALSE ) and ( result5 == main.TRUE ) \
+                      and ( result6 == main.TRUE )
+        utilities.assert_equals( expect = True, actual = pingResult2,
+                                 onpass = "Speaker1 ping peers successful",
+                                 onfail = "Speaker1 ping peers NOT successful" )
+
+        if pingResult2 == False:
+            main.cleanup()
+            main.exit()
+
+        main.step( "Check ping between BGP peers and speaker2" )
+        # TODO
+        result7 = main.Mininet.pingHost( src = "speaker2", target = peer64514 )
+        result8 = main.Mininet.pingHost( src = "speaker2", target = peer64515 )
+        result9 = main.Mininet.pingHost( src = "speaker2", target = peer64516 )
+
+        pingResult3 = ( result7 == main.FALSE ) and ( result8 == main.TRUE ) \
+                                                and ( result9 == main.TRUE )
+        utilities.assert_equals( expect = True, actual = pingResult2,
+                                 onpass = "Speaker2 ping peers successful",
+                                 onfail = "Speaker2 ping peers NOT successful" )
+
+        if pingResult3 == False:
+            main.cleanup()
+            main.exit()
+
+        main.step( "Check whether all flow status are ADDED" )
+        utilities.assertEquals( \
+            expect = main.TRUE,
+            actual = main.ONOScli1.checkFlowsState( isPENDING_ADD = False ),
+            onpass = "Flow status is correct!",
+            onfail = "Flow status is wrong!" )
+
+
+    def CASE8( self, main ):
+        '''
+        Bring up the edge switch (sw32) which was shut down in CASE7,
+        check P-2-P and M-2-S intents, ping test
+        '''
+        import time
+        main.case( "Start the edge sw32, check P-2-P and M-2-S intents, ping test" )
+        main.step( "Start sw32" )
+        result1 = main.Mininet.switch( SW = "sw32", OPTION = "start" )
+        utilities.assertEquals( \
+            expect = main.TRUE,
+            actual = result1,
+            onpass = "Starting switch succeeded!",
+            onfail = "Starting switch failed!" )
+
+        result2 = main.Mininet.assignSwController( "sw32", ONOS1Ip )
+        utilities.assertEquals( \
+            expect = main.TRUE,
+            actual = result2,
+            onpass = "Connect switch to ONOS succeeded!",
+            onfail = "Connect switch to ONOS failed!" )
+
+        if result1 and result2:
+            time.sleep( int( main.params[ 'timers' ][ 'RouteDelivery' ] ) )
+            main.Functions.checkRouteNum( main, 3 )
+            main.Functions.checkM2SintentNum( main, 3 )
+            main.Functions.checkP2PintentNum( main, 18 * 2 )
+        else:
+            main.log.error( "Starting switch failed!" )
+            main.cleanup()
+            main.exit()
+
+        main.step( "Check whether all flow status are ADDED" )
+        utilities.assertEquals( \
+            expect = main.TRUE,
+            actual = main.ONOScli1.checkFlowsState( isPENDING_ADD = False ),
+            onpass = "Flow status is correct!",
+            onfail = "Flow status is wrong!" )
+
+        # Ping test
+        main.Functions.pingSpeakerToPeer( main, speakers = ["speaker1"],
+                       peers = ["peer64514", "peer64515", "peer64516"],
+                       expectAllSuccess = True )
+        main.Functions.pingSpeakerToPeer( main, speakers = ["speaker2"],
+                       peers = [peer64514, peer64515, peer64516],
+                       expectAllSuccess = True )
+        main.Functions.pingHostToHost( main,
+                        hosts = ["host64514", "host64515", "host64516"],
+                        expectAllSuccess = True )
+
+
+    def CASE9( self, main ):
+        '''
+        Bring down a switch in best path, check:
+        route number, P2P intent number, M2S intent number, ping test
+        '''
+        main.case( "Stop sw11 located in best path, \
+        check route number, P2P intent number, M2S intent number, ping test" )
+
+        main.log.info( "Check the flow number correctness before stopping sw11" )
+        main.Functions.checkFlowNum( main, "sw11", 19 )
+        main.Functions.checkFlowNum( main, "sw1", 3 )
+        main.Functions.checkFlowNum( main, "sw7", 3 )
+        main.log.info( main.Mininet.checkFlows( "sw11" ) )
+        main.log.info( main.Mininet.checkFlows( "sw1" ) )
+        main.log.info( main.Mininet.checkFlows( "sw7" ) )
+
+        main.step( "Stop sw11" )
+        result = main.Mininet.switch( SW = "sw11", OPTION = "stop" )
+        utilities.assertEquals( expect = main.TRUE, actual = result,
+                                onpass = "Stopping switch succeeded!",
+                                onfail = "Stopping switch failed!" )
+        if result:
+            time.sleep( int( main.params[ 'timers' ][ 'RouteDelivery' ] ) )
+            time.sleep( int( main.params[ 'timers' ][ 'RouteDelivery' ] ) )
+            main.Functions.checkRouteNum( main, 3 )
+            main.Functions.checkM2SintentNum( main, 3 )
+            main.Functions.checkP2PintentNum( main, 18 * 2 )
+        else:
+            main.log.error( "Stopping switch failed!" )
+            main.cleanup()
+            main.exit()
+
+        main.step( "Check whether all flow status are ADDED" )
+        utilities.assertEquals( \
+            expect = main.TRUE,
+            actual = main.ONOScli1.checkFlowsState( isPENDING_ADD = False ),
+            onpass = "Flow status is correct!",
+            onfail = "Flow status is wrong!" )
+        # Ping test
+        main.Functions.pingSpeakerToPeer( main, speakers = ["speaker1"],
+                       peers = ["peer64514", "peer64515", "peer64516"],
+                       expectAllSuccess = True )
+        main.Functions.pingSpeakerToPeer( main, speakers = ["speaker2"],
+                       peers = [peer64514, peer64515, peer64516],
+                       expectAllSuccess = True )
+        main.Functions.pingHostToHost( main,
+                        hosts = ["host64514", "host64515", "host64516"],
+                        expectAllSuccess = True )
+
+
+    def CASE10( self, main ):
+        '''
+        Bring up the switch which was stopped in CASE9, check:
+        route number, P2P intent number, M2S intent number, ping test
+        '''
+        main.case( "Start sw11 which was stopped in CASE9, \
+        check route number, P2P intent number, M2S intent number, ping test" )
+
+        main.log.info( "Check the flow status before starting sw11" )
+        main.Functions.checkFlowNum( main, "sw1", 17 )
+        main.Functions.checkFlowNum( main, "sw7", 5 )
+        main.log.info( main.Mininet.checkFlows( "sw1" ) )
+        main.log.info( main.Mininet.checkFlows( "sw7" ) )
+
+        main.step( "Start sw11" )
+        result1 = main.Mininet.switch( SW = "sw11", OPTION = "start" )
+        utilities.assertEquals( expect = main.TRUE, actual = result1,
+                                onpass = "Starting switch succeeded!",
+                                onfail = "Starting switch failed!" )
+        result2 = main.Mininet.assignSwController( "sw11", ONOS1Ip )
+        utilities.assertEquals( expect = main.TRUE, actual = result2,
+                                onpass = "Connect switch to ONOS succeeded!",
+                                onfail = "Connect switch to ONOS failed!" )
+        if result1 and result2:
+            time.sleep( int( main.params[ 'timers' ][ 'RouteDelivery' ] ) )
+            main.Functions.checkRouteNum( main, 3 )
+            main.Functions.checkM2SintentNum( main, 3 )
+            main.Functions.checkP2PintentNum( main, 18 * 2 )
+
+            main.log.debug( main.Mininet.checkFlows( "sw11" ) )
+            main.log.debug( main.Mininet.checkFlows( "sw1" ) )
+            main.log.debug( main.Mininet.checkFlows( "sw7" ) )
+        else:
+            main.log.error( "Starting switch failed!" )
+            main.cleanup()
+            main.exit()
+
+        main.step( "Check whether all flow status are ADDED" )
+        utilities.assertEquals( \
+            expect = main.TRUE,
+            actual = main.ONOScli1.checkFlowsState( isPENDING_ADD = False ),
+            onpass = "Flow status is correct!",
+            onfail = "Flow status is wrong!" )
+        # Ping test
+        main.Functions.pingSpeakerToPeer( main, speakers = ["speaker1"],
+                       peers = ["peer64514", "peer64515", "peer64516"],
+                       expectAllSuccess = True )
+        main.Functions.pingSpeakerToPeer( main, speakers = ["speaker2"],
+                       peers = [peer64514, peer64515, peer64516],
+                       expectAllSuccess = True )
+        main.Functions.pingHostToHost( main,
+                        hosts = ["host64514", "host64515", "host64516"],
+                        expectAllSuccess = True )
+
+
+    def CASE11(self, main):
+        import time
+        main.case( "Kill speaker1, check:\
+        route number, P2P intent number, M2S intent number, ping test" )
+        main.log.info( "Check network status before killing speaker1" )
+        main.Functions.checkRouteNum( main, 3 )
+        main.Functions.checkM2SintentNum( main, 3 )
+        main.Functions.checkP2PintentNum( main, 18 * 2 )
+        main.step( "Check whether all flow status are ADDED" )
+        utilities.assertEquals( \
+            expect = main.TRUE,
+            actual = main.ONOScli1.checkFlowsState( isPENDING_ADD = False ),
+            onpass = "Flow status is correct!",
+            onfail = "Flow status is wrong!" )
+
+        main.Functions.pingSpeakerToPeer( main, speakers = ["speaker1"],
+                       peers = ["peer64514", "peer64515", "peer64516"],
+                       expectAllSuccess = True )
+        main.Functions.pingSpeakerToPeer( main, speakers = ["speaker2"],
+                       peers = [peer64514, peer64515, peer64516],
+                       expectAllSuccess = True )
+        main.Functions.pingHostToHost( main,
+                        hosts = ["host64514", "host64515", "host64516"],
+                        expectAllSuccess = True )
+
+        main.step( "Kill speaker1" )
+        command1 = "ps -e | grep bgp -c"
+        result1 = main.Mininet.node( "root", command1 )
+
+        # The total BGP daemon number in this test environment is 5.
+        if "5" in result1:
+            main.log.debug( "Before kill speaker1, 5 BGP daemons - correct" )
+        else:
+            main.log.warn( "Before kill speaker1, number of BGP daemons is wrong" )
+            main.log.info( result1 )
+
+        command2 = "sudo kill -9 `ps -ef | grep quagga-sdn.conf | grep -v grep | awk '{print $2}'`"
+        result2 = main.Mininet.node( "root", command2 )
+
+        result3 = main.Mininet.node( "root", command1 )
+
+        utilities.assert_equals( expect = True,
+                                 actual = ( "4" in result3 ),
+                                 onpass = "Kill speaker1 succeeded",
+                                 onfail = "Kill speaker1 failed" )
+        if ( "4" not in result3 ) :
+            main.log.info( result3 )
+            main.cleanup()
+            main.exit()
+
+        time.sleep( int( main.params[ 'timers' ][ 'RouteDelivery' ] ) )
+        main.Functions.checkRouteNum( main, 3 )
+        main.Functions.checkM2SintentNum( main, 3 )
+        main.Functions.checkP2PintentNum( main, 18 * 2 )
+
+        main.step( "Check whether all flow status are ADDED" )
+        utilities.assertEquals( \
+            expect = main.TRUE,
+            actual = main.ONOScli1.checkFlowsState( isPENDING_ADD = False ),
+            onpass = "Flow status is correct!",
+            onfail = "Flow status is wrong!" )
+
+        '''
+        main.Functions.pingSpeakerToPeer( main, speakers = ["speaker1"],
+                       peers = ["peer64514", "peer64515", "peer64516"],
+                       expectAllSuccess = False )
+        '''
+        main.Functions.pingSpeakerToPeer( main, speakers = ["speaker2"],
+                       peers = [peer64514, peer64515, peer64516],
+                       expectAllSuccess = True )
+        main.Functions.pingHostToHost( main,
+                        hosts = ["host64514", "host64515", "host64516"],
+                        expectAllSuccess = True )
+
+
+    def CASE12( self, main ):
+        import time
+        import json
+        main.case( "Bring down leader ONOS node, check: \
+        route number, P2P intent number, M2S intent number, ping test" )
+        main.step( "Find out ONOS leader node" )
+        result = main.ONOScli1.leaders()
+        jsonResult = json.loads( result )
+        leaderIP = ""
+        for entry in jsonResult:
+            if entry["topic"] == "org.onosproject.sdnip":
+                leaderIP = entry["leader"]
+                main.log.info( "leaderIP is: " )
+                main.log.info( leaderIP )
+
+        main.step( "Uninstall ONOS/SDN-IP leader node" )
+        if leaderIP == ONOS1Ip:
+            uninstallResult = main.ONOSbench.onosStop( ONOS1Ip )
+        elif leaderIP == ONOS2Ip:
+            uninstallResult = main.ONOSbench.onosStop( ONOS2Ip )
+        else:
+            uninstallResult = main.ONOSbench.onosStop( ONOS3Ip )
+
+        utilities.assert_equals( expect = main.TRUE,
+                                 actual = uninstallResult,
+                                 onpass = "Uninstall ONOS leader succeeded",
+                                 onfail = "Uninstall ONOS leader failed" )
+        if uninstallResult != main.TRUE:
+            main.cleanup()
+            main.exit()
+        time.sleep( int( main.params[ 'timers' ][ 'RouteDelivery' ] ) )
+
+        if leaderIP == ONOS1Ip:
+            main.Functions.checkRouteNum( main, 3, ONOScli = "ONOScli2" )
+            main.Functions.checkM2SintentNum( main, 3, ONOScli = "ONOScli2" )
+            main.Functions.checkP2PintentNum( main, 18 * 2, ONOScli = "ONOScli2" )
+
+            main.step( "Check whether all flow status are ADDED" )
+            utilities.assertEquals( \
+                expect = main.TRUE,
+                actual = main.ONOScli2.checkFlowsState( isPENDING_ADD = False ),
+                onpass = "Flow status is correct!",
+                onfail = "Flow status is wrong!" )
+        else:
+            main.Functions.checkRouteNum( main, 3 )
+            main.Functions.checkM2SintentNum( main, 3 )
+            main.Functions.checkP2PintentNum( main, 18 * 2 )
+
+            main.step( "Check whether all flow status are ADDED" )
+            utilities.assertEquals( \
+                expect = main.TRUE,
+                actual = main.ONOScli1.checkFlowsState( isPENDING_ADD = False ),
+                onpass = "Flow status is correct!",
+                onfail = "Flow status is wrong!" )
+
+        main.Functions.pingSpeakerToPeer( main, speakers = ["speaker1"],
+                       peers = ["peer64514", "peer64515", "peer64516"],
+                       expectAllSuccess = True )
+        main.Functions.pingSpeakerToPeer( main, speakers = ["speaker2"],
+                       peers = [peer64514, peer64515, peer64516],
+                       expectAllSuccess = True )
+        main.Functions.pingHostToHost( main,
+                        hosts = ["host64514", "host64515", "host64516"],
+                        expectAllSuccess = True )
diff --git a/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/USECASE_SdnipFunctionCluster_fsfw.topo b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/USECASE_SdnipFunctionCluster_fsfw.topo
new file mode 100644
index 0000000..f3c9b5f
--- /dev/null
+++ b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/USECASE_SdnipFunctionCluster_fsfw.topo
@@ -0,0 +1,52 @@
+<TOPOLOGY>
+    <COMPONENT>
+
+        <ONOSbench>
+            <host>127.0.0.1</host>
+            <user>admin</user>
+            <password></password>
+            <type>OnosDriver</type>
+            <connect_order>1</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOSbench>
+
+        <ONOScli1>
+            <host>127.0.0.1</host>
+            <user>admin</user>
+            <password></password>
+            <type>OnosCliDriver</type>
+            <connect_order>2</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli1>
+        <ONOScli2>
+            <host>127.0.0.1</host>
+            <user>admin</user>
+            <password></password>
+            <type>OnosCliDriver</type>
+            <connect_order>3</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </ONOScli2>
+
+        <QuaggaCliSpeaker1>
+            <host>127.0.0.1</host>
+            <user>admin</user>
+            <password></password>
+            <type>QuaggaCliDriver</type>
+            <connect_order>4</connect_order>
+            <COMPONENTS> </COMPONENTS>
+        </QuaggaCliSpeaker1>
+
+        <Mininet>
+            <host>OCN</host>
+            <user>admin</user>
+            <password></password>
+            <type>MininetCliDriver</type>
+            <connect_order>5</connect_order>
+            <COMPONENTS>
+                <home>~/Mininet/mininet/custom/</home>
+            </COMPONENTS>
+        </Mininet>
+
+    </COMPONENT>
+</TOPOLOGY>
+
diff --git a/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/__init__.py b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/__init__.py
diff --git a/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/network-cfg.json b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/network-cfg.json
new file mode 100644
index 0000000..602a72f
--- /dev/null
+++ b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/network-cfg.json
@@ -0,0 +1,66 @@
+{
+    "ports" : {
+        "of:00000000000000a8/5" : {
+            "interfaces" : [
+                {
+                    "ips"  : [ "10.0.5.101/24" ],
+                    "mac"  : "00:00:00:00:00:01"
+                },
+                {
+                    "ips"  : [ "10.0.15.101/24" ],
+                    "mac"  : "00:00:00:00:00:02"
+                }
+            ]
+        },
+        "of:0000000000000a32/4" : {
+            "interfaces" : [
+                {
+                    "ips"  : [ "10.0.4.101/24" ],
+                    "mac"  : "00:00:00:00:00:01"
+                },
+                {
+                    "ips"  : [ "10.0.14.101/24" ],
+                    "mac"  : "00:00:00:00:00:02"
+                }
+            ]
+        },
+        "of:0000000000000a28/3" : {
+            "interfaces" : [
+                {
+                    "ips"  : [ "10.0.6.101/24" ],
+                    "mac"  : "00:00:00:00:00:01"
+                },
+                {
+                    "ips"  : [ "10.0.16.101/24" ],
+                    "mac"  : "00:00:00:00:00:02"
+                }
+            ]
+        }
+    },
+    "apps" : {
+        "org.onosproject.router" : {
+            "bgp" : {
+                "bgpSpeakers" : [
+                    {
+                        "name" : "speaker1",
+                        "connectPoint" : "of:0000000000000a24/1",
+                        "peers" : [
+                            "10.0.4.1",
+                            "10.0.5.1",
+                            "10.0.6.1"
+                        ]
+                    },
+                    {
+                        "name" : "speaker2",
+                        "connectPoint" : "of:0000000000000a24/2",
+                        "peers" : [
+                            "10.0.14.1",
+                            "10.0.15.1",
+                            "10.0.16.1"
+                        ]
+                    }
+                ]
+            }
+        }
+    }
+}
diff --git a/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/sdnip_multiple_instance_VM b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/sdnip_multiple_instance_VM
new file mode 100644
index 0000000..070e366
--- /dev/null
+++ b/TestON/tests/USECASE_SdnipFunctionCluster_fsfw/sdnip_multiple_instance_VM
@@ -0,0 +1,16 @@
+export ONOS_CELL="sdnip_single_instance"
+
+export ONOS_INSTALL_DIR="/opt/onos"
+export ONOS_NIC=10.128.20.*
+export OC1="10.128.20.11"
+export OC2="10.128.20.12"
+export OC3="10.128.20.13"
+export OCN="10.128.10.12"
+export OCI="${OC1}"
+export ONOS_USER="sdn"                  # ONOS user on remote system
+export ONOS_PWD="rocks"
+
+#export ONOS_APPS="drivers,openflow,config,proxyarp"
+export ONOS_APPS="drivers,openflow,proxyarp"
+
+
diff --git a/TestON/tests/USECASE_SdnipFunction_fsfw/USECASE_SdnipFunction_fsfw.params b/TestON/tests/USECASE_SdnipFunction_fsfw/USECASE_SdnipFunction_fsfw.params
index 18bfde6..fca86aa 100644
--- a/TestON/tests/USECASE_SdnipFunction_fsfw/USECASE_SdnipFunction_fsfw.params
+++ b/TestON/tests/USECASE_SdnipFunction_fsfw/USECASE_SdnipFunction_fsfw.params
@@ -10,6 +10,9 @@
     <CTRL>
         <numCtrl>1</numCtrl>
         <ip1>OC1</ip1>
+        <ipN>OCN</ipN>
+        <fsfwIp>10.128.10.12</fsfwIp>
+        <fsfwPort>6633</fsfwPort>
         <port1>6653</port1>
     </CTRL>
 
diff --git a/TestON/tests/USECASE_SdnipFunction_fsfw/USECASE_SdnipFunction_fsfw.py b/TestON/tests/USECASE_SdnipFunction_fsfw/USECASE_SdnipFunction_fsfw.py
index 4636bcc..68571c7 100644
--- a/TestON/tests/USECASE_SdnipFunction_fsfw/USECASE_SdnipFunction_fsfw.py
+++ b/TestON/tests/USECASE_SdnipFunction_fsfw/USECASE_SdnipFunction_fsfw.py
@@ -32,11 +32,19 @@
 
         global ONOS1Ip
         ONOS1Ip = os.getenv( main.params[ 'CTRL' ][ 'ip1' ] )
+        global fsfwIp
+        # TDOO: there is some setup sequence issue, will fix it later
+        # fsfwIp = os.getenv( main.params[ 'CTRL' ][ 'ipN' ] )
+        fsfwIp = main.params[ 'CTRL' ][ 'fsfwIp' ]
+        global fsfwPort
+        fsfwPort = main.params[ 'CTRL' ][ 'fsfwPort' ]
+
         # connect all switches to controller
         swResult = main.TRUE
         for i in range ( 1, int( main.params['config']['switchNum'] ) + 1 ):
             sw = "sw%s" % ( i )
-            swResult = swResult and main.Mininet.assignSwController( sw, ONOS1Ip )
+            swResult = swResult and main.Mininet.assignSwController( sw, fsfwIp,
+                                                                     port = fsfwPort )
             # swResult = swResult and main.Mininet.assignSwController( sw, ONOS1Ip, port = "6633" )
         utilities.assert_equals( expect = main.TRUE,
                              actual = swResult,
@@ -532,7 +540,7 @@
             onpass = "Starting switch succeeded!",
             onfail = "Starting switch failed!" )
 
-        result2 = main.Mininet.assignSwController( "sw32", ONOS1Ip )
+        result2 = main.Mininet.assignSwController( "sw32", fsfwIp )
         utilities.assertEquals( \
             expect = main.TRUE,
             actual = result2,
@@ -631,7 +639,7 @@
         utilities.assertEquals( expect = main.TRUE, actual = result1,
                                 onpass = "Starting switch succeeded!",
                                 onfail = "Starting switch failed!" )
-        result2 = main.Mininet.assignSwController( "sw11", ONOS1Ip )
+        result2 = main.Mininet.assignSwController( "sw11", fsfwIp )
         utilities.assertEquals( expect = main.TRUE, actual = result2,
                                 onpass = "Connect switch to ONOS succeeded!",
                                 onfail = "Connect switch to ONOS failed!" )