Merge "Improve Switch Lat test methods     - Add dependence functions     - improve test algorithm Change-Id: I3b9f03b2e53b3759e32cbc464c2c53a84f5a562c"
diff --git a/TestON/tests/SCPF/SCPFswitchLat/SCPFswitchLat.params b/TestON/tests/SCPF/SCPFswitchLat/SCPFswitchLat.params
index da371c3..519debc 100644
--- a/TestON/tests/SCPF/SCPFswitchLat/SCPFswitchLat.params
+++ b/TestON/tests/SCPF/SCPFswitchLat/SCPFswitchLat.params
@@ -1,5 +1,5 @@
 <PARAMS>
-    <testcases>1,2,1,2,1,2,1,2</testcases>
+    <testcases>0,1,2,1,2,1,2,1,2</testcases>
 
     <SCALE>1,3,5,7</SCALE>
     <max>7</max>
@@ -9,9 +9,15 @@
         <cellApps>drivers,metrics,openflow</cellApps>
     </ENV>
 
+    <DEPENDENCY>
+        <path>/tests/SCPF/SCPFswitchLat/dependencies/</path>
+        <topology>topo-perf-1sw.py</topology>
+        <function>switchFunc</function>
+    </DEPENDENCY>
+
     <GIT>
-        <autopull>off</autopull>
-        <checkout>master</checkout>
+        <gitPull>off</gitPull>
+        <gitBranch>master</gitBranch>
     </GIT>
 
     <CTRL>
@@ -29,17 +35,26 @@
         <ip1>OCN</ip1>
     </MN>
 
+    <TIMEOUT>
+        <timeout>60</timeout>
+    </TIMEOUT>
+
     <BENCH>
         <ip>localhost</ip>
     </BENCH>
 
     <TSHARK>
-        <ofpPortStatus>OF 1.3 146</ofpPortStatus>
-        <ofpRoleReply>OF 1.3 90 of_role_reply</ofpRoleReply>
-        <featureReply>OF 1.3 98 of_features_reply</featureReply>
-        <roleRequest>OF 1.3 90 of_role_request</roleRequest>
-        <tcpSynAck>TCP 74 openflow</tcpSynAck>
-        <finAckSequence>FIN</finAckSequence>
+        <up>
+            <TCP>TCP 74 openflow</TCP>  #1
+            <RQ>OF 1.3 90 of_role_request</RQ> #2
+            <RR>OF 1.3 90 of_role_reply</RR> #3
+            <Feature>OF 1.3 98 of_features_reply</Feature>#4
+        </up>
+
+        <down>
+            <FA>\[FIN,\ ACK\]</FA>
+            <ACK>openflow\ \[ACK\]</ACK>
+        </down>
     </TSHARK>
 
     <TEST>
@@ -58,20 +73,41 @@
         org.onlab.onos.net.topology.impl.DefaultTopologyProvider.cfg
         </topoConfigName>
 
-        #Number of times to iterate each case
-        <numIter>25</numIter>
-        <numSwitch>2</numSwitch>
         #Number of iterations to ignore initially
-        <iterIgnore>5</iterIgnore>
+        <warmUp>5</warmUp>
+
+        #Number of times to iterate each case
+        <sampleSize>20</sampleSize>
+        <device>s3</device>
+        <tsharkResultPath>
+            <up>
+                <TCP>/tmp/Tshark_TCP</TCP>
+                <RQ>/tmp/Tshark_RQ</RQ> #role request
+                <RR>/tmp/Tshark_RR</RR> #role reply OF output
+                <Feature>/tmp/Tshark_Feature</Feature>
+            </up>
+
+            <down>
+                <FA>/tmp/Tshark_FA</FA>#Fin_ack
+                <ACK>/tmp/Tshark_ACK</ACK>
+            </down>
+
+        </tsharkResultPath>
 
         <singleSwThreshold>0,1000</singleSwThreshold>
 
         <tabletFile>tablets_3node.json</tabletFile>
    </TEST>
 
-    <DB>
-        <switchEventResultPath>/tmp/switchEventResultDb</switchEventResultPath>
-    </DB>
+    <SLEEP>
+        <startup>5</startup>
+        <measure>5</measure>
+        <mininet>5</mininet>
+    </SLEEP>
+
+    <DATABASE>
+        <dbName>/tmp/switchEventResultDb</dbName>
+    </DATABASE>
 
     <JSON>
         <deviceTimestamp>topologyDeviceEventTimestamp</deviceTimestamp>
diff --git a/TestON/tests/SCPF/SCPFswitchLat/SCPFswitchLat.py b/TestON/tests/SCPF/SCPFswitchLat/SCPFswitchLat.py
index 55cef23..8cbfb61 100644
--- a/TestON/tests/SCPF/SCPFswitchLat/SCPFswitchLat.py
+++ b/TestON/tests/SCPF/SCPFswitchLat/SCPFswitchLat.py
@@ -1,863 +1,379 @@
-# CASE1 starts number of nodes specified in param file
-#
-# cameron@onlab.us
+'''
+    SCPFswitchLat
+    Test Switch add/remove latency
+    calculate package latency between switch and ONOS
+    Switch UP:
+    TCP -- Feature Reply -- Role Request -- Role Reply -- Device -- Graph
+    Siwtch Down:
+    Openflow FIN/ACK -- ACK -- Device -- Graph
+'''
 
 class SCPFswitchLat:
 
-    def __init__( self ):
+    def __init__(self):
         self.default = ''
 
-    def CASE1( self, main ):
-        import sys
-        import re
+    def CASE0( self, main ):
         import os
+        import imp
+        '''
+        - GIT
+        - BUILDING ONOS
+            Pull specific ONOS branch, then Build ONOS ono ONOS Bench.
+            This step is usually skipped. Because in a Jenkins driven automated
+            test env. We want Jenkins jobs to pull&build for flexibility to handle
+            different versions of ONOS.
+        - Construct tests variables
+        '''
+        gitPull = main.params['GIT']['gitPull']
+        gitBranch = main.params['GIT']['gitBranch']
+
+        main.case( "Pull onos branch and build onos on Teststation." )
+
+        if gitPull == 'True':
+            main.step( "Git Checkout ONOS branch: " + gitBranch )
+            stepResult = main.ONOSbench.gitCheckout( branch=gitBranch )
+            utilities.assert_equals(expect=main.TRUE,
+                                    actual=stepResult,
+                                    onpass="Successfully checkout onos branch.",
+                                    onfail="Failed to checkout onos branch. Exiting test...")
+            if not stepResult: main.exit()
+
+            main.step( "Git Pull on ONOS branch:" + gitBranch )
+            stepResult = main.ONOSbench.gitPull()
+            utilities.assert_equals(expect=main.TRUE,
+                                    actual=stepResult,
+                                    onpass="Successfully pull onos. ",
+                                    onfail="Failed to pull onos. Exiting test ...")
+            if not stepResult: main.exit()
+
+            main.step( "Building ONOS branch: " + gitBranch )
+            stepResult = main.ONOSbench.cleanInstall( skipTest=True )
+            utilities.assert_equals(expect=main.TRUE,
+                                    actual=stepResult,
+                                    onpass="Successfully build onos.",
+                                    onfail="Failed to build onos. Exiting test...")
+            if not stepResult: main.exit()
+
+        else:
+            main.log.warn( "Skipped pulling onos and Skipped building ONOS" )
+
+        main.testOnDirectory = os.path.dirname(os.getcwd())
+        main.MN1Ip = main.params['MN']['ip1']
+        main.dependencyPath = main.testOnDirectory + \
+                              main.params['DEPENDENCY']['path']
+        main.topoName = main.params['DEPENDENCY']['topology']
+        main.dependencyFunc = main.params['DEPENDENCY']['function']
+        main.cellName = main.params['ENV']['cellName']
+        main.Apps = main.params['ENV']['cellApps']
+        main.scale = (main.params['SCALE']).split(",")
+
+        main.ofPackage = main.params['TSHARK']
+
+        main.tsharkResultPath = main.params['TEST']['tsharkResultPath']
+        main.sampleSize = int(main.params['TEST']['sampleSize'])
+        main.warmUp = int(main.params['TEST']['warmUp'])
+        main.dbFileName = main.params['DATABASE']['dbName']
+        main.startUpSleep = int(main.params['SLEEP']['startup'])
+        main.measurementSleep = int( main.params['SLEEP']['measure'] )
+        main.maxScale = int( main.params['max'] )
+        main.timeout = int( main.params['TIMEOUT']['timeout'] )
+        main.MNSleep = int( main.params['SLEEP']['mininet'])
+        main.device = main.params['TEST']['device']
+ 
+        main.log.info("Create Database file " + main.dbFileName)
+        resultsDB = open(main.dbFileName, "w+")
+        resultsDB.close()
+
+        main.switchFunc = imp.load_source(main.dependencyFunc,
+                                       main.dependencyPath +
+                                       main.dependencyFunc +
+                                       ".py")
+
+    def CASE1(self, main):
+        # Clean up test environment and set up
         import time
+        main.log.info("Get ONOS cluster IP")
+        print(main.scale)
+        main.numCtrls = int(main.scale.pop(0))
+        main.ONOSip = []
+        main.maxNumBatch = 0
+        main.AllONOSip = main.ONOSbench.getOnosIps()
+        for i in range(main.numCtrls):
+            main.ONOSip.append(main.AllONOSip[i])
+        main.log.info(main.ONOSip)
+        main.CLIs = []
+        main.log.info("Creating list of ONOS cli handles")
+        for i in range(main.numCtrls):
+            main.CLIs.append(getattr(main, 'ONOS%scli' % (i + 1)))
 
-        global init
-        try:
-            if type(init) is not bool:
-                init = Fals
-        except NameError:
-            init = False
+        if not main.CLIs:
+            main.log.error("Failed to create the list of ONOS cli handles")
+            main.cleanup()
+            main.exit()
 
-        #Load values from params file
-        checkoutBranch = main.params[ 'GIT' ][ 'checkout' ]
-        gitPull = main.params[ 'GIT' ][ 'autopull' ]
-        cellName = main.params[ 'ENV' ][ 'cellName' ]
-        Apps = main.params[ 'ENV' ][ 'cellApps' ]
-        BENCHIp = main.params[ 'BENCH' ][ 'ip' ]
-        MN1Ip = main.params[ 'MN' ][ 'ip1' ]
-        main.maxNodes = int(main.params[ 'max' ])
-        cellName = main.params[ 'ENV' ][ 'cellName' ]
-        homeDir = os.path.expanduser('~')
-        topoCfgFile = main.params['TEST']['topoConfigFile']
-        topoCfgName = main.params['TEST']['topoConfigName']
-        switchEventResultPath = main.params['DB']['switchEventResultPath']
-        skipMvn = main.params ['TEST']['mci']
-        testONpath = re.sub( "(tests)$", "bin", main.testDir )  # TestON/bin
-        user = main.params[ 'CTRL' ][ 'user' ]
+        main.commit = main.ONOSbench.getVersion(report=True)
+        main.commit = main.commit.split(" ")[1]
+        main.log.info("Starting up %s node(s) ONOS cluster" % main.numCtrls)
+        main.log.info("Safety check, killing all ONOS processes" +
+                      " before initiating environment setup")
 
-        # -- INIT SECTION, ONLY RUNS ONCE -- #
-        if init == False:
-            init = True
-            global clusterCount             #number of nodes running
-            global scale
-            global commit
-            global timeToPost
-            global runNum
-            global jenkinsBuildNumber
-            global CLIs
-            CLIs = []
-            main.ONOSIp = []
+        for i in range(main.numCtrls):
+            main.ONOSbench.onosDie(main.ONOSip[i])
 
-            for i in range( 1, 8 ):
-                CLIs.append( getattr( main, 'ONOS' + str( i ) + 'cli' ) )
+        main.log.info("NODE COUNT = %s" % main.numCtrls)
+        main.ONOSbench.createCellFile(main.ONOSbench.ip_address,
+                                      main.cellName,
+                                      main.MN1Ip,
+                                      main.Apps,
+                                      main.ONOSip)
+        main.step("Apply cell to environment")
+        cellResult = main.ONOSbench.setCell(main.cellName)
+        verifyResult = main.ONOSbench.verifyCell()
+        stepResult = cellResult and verifyResult
+        utilities.assert_equals(expect=main.TRUE,
+                                actual=stepResult,
+                                onpass="Successfully applied cell to " + \
+                                       "environment",
+                                onfail="Failed to apply cell to environment ")
 
-            timeToPost = time.strftime('%Y-%m-%d %H:%M:%S')
-            runNum = time.strftime('%d%H%M%S')
-
-            try:
-                jenkinsBuildNumber = str(os.environ['BUILD_NUMBER'])
-                main.log.report( 'Jenkins build number: ' + jenkinsBuildNumber )
-            except KeyError:
-                jenkinsBuildNumber = str(0)
-                main.log.info( 'Job is not run by jenkins. ' + 'Build number set to: ' + jenkinsBuildNumber)
-
-            clusterCount = 0
-            main.ONOSIp = main.ONOSbench.getOnosIps()
-
-            scale = (main.params[ 'SCALE' ]).split(",")
-            clusterCount = int(scale[0])
-
-            #mvn clean install, for debugging set param 'skipCleanInstall' to yes to speed up test
-            if skipMvn != "off":
-                mvnResult = main.ONOSbench.cleanInstall()
-
-            #git
-            main.step( "Git checkout and pull " + checkoutBranch )
-            if gitPull == 'on':
-                checkoutResult = main.ONOSbench.gitCheckout( checkoutBranch )
-                pullResult = main.ONOSbench.gitPull()
-
-            else:
-                checkoutResult = main.TRUE
-                pullResult = main.TRUE
-                main.log.info( "Skipped git checkout and pull" )
-
-            main.step("Grabbing commit number")
-            commit = main.ONOSbench.getVersion()       ####
-            commit = (commit.split(" "))[1]
-
-            temp = testONpath.replace("bin","") + "tests/SCPF/SCPFswitchLat/dependencies/"
-            main.ONOSbench.scp( main.Mininet1,
-                                temp + "topo-perf-1sw.py",
-                                main.Mininet1.home,
-                                direction="to" )
-            #main.ONOSbench.handle.expect(":~")
-
-            main.step('Clearing previous DB log file')
-            print switchEventResultPath
-            fSwitchLog = open(switchEventResultPath, "w+")
-            fSwitchLog.write("")
-            fSwitchLog.close()
-
-        # -- END OF INIT SECTION --#
-
-        main.step("Adjusting scale")
-        clusterCount = int(scale[0])
-        scale.remove(scale[0])
-
-        #kill off all onos processes
-        main.step("Safety check, killing all ONOS processes before initiating environment setup")
-        for node in range(main.maxNodes):
-            main.ONOSbench.onosDie(main.ONOSIp[node])
-
-        #Uninstall everywhere
-        main.step( "Cleaning Enviornment..." )
-        for i in range(main.maxNodes):
-            main.log.info(" Uninstalling ONOS " + str(i) )
-            main.ONOSbench.onosUninstall( main.ONOSIp[i] )
-        main.log.info("Sleep 10 second for uninstall to settle...")
-        time.sleep(10)
-        main.ONOSbench.handle.sendline(" ")
-        main.ONOSbench.handle.expect(":~")
-
-        #construct the cell file
-        main.log.info("Creating cell file")
-        cellIp = []
-        for node in range (clusterCount):
-            cellIp.append(main.ONOSIp[node])
-
-        main.ONOSbench.createCellFile(main.ONOSbench.ip_address, cellName, MN1Ip, str(Apps), cellIp)
-
-        main.step( "Set Cell" )
-        main.ONOSbench.setCell(cellName)
-
-        main.step( "Creating ONOS package" )
+        main.step("Creating ONOS package")
         packageResult = main.ONOSbench.onosPackage()
+        stepResult = packageResult
+        utilities.assert_equals(expect=main.TRUE,
+                                actual=stepResult,
+                                onpass="Successfully created ONOS package",
+                                onfail="Failed to create ONOS package")
 
-        main.step( "verify cells" )
-        verifyCellResult = main.ONOSbench.verifyCell()
+        main.step("Uninstall ONOS package on all Nodes")
+        uninstallResult = main.TRUE
+        for i in range(int(main.numCtrls)):
+            main.log.info("Uninstalling package on ONOS Node IP: " + main.ONOSip[i])
+            u_result = main.ONOSbench.onosUninstall(main.ONOSip[i])
+            utilities.assert_equals(expect=main.TRUE, actual=u_result,
+                                    onpass="Test step PASS",
+                                    onfail="Test step FAIL")
+            uninstallResult = (uninstallResult and u_result)
 
-        main.step('Starting mininet topology ')
+        main.step("Install ONOS package on all Nodes")
+        installResult = main.TRUE
+        for i in range(int(main.numCtrls)):
+            main.log.info("Installing package on ONOS Node IP: " + main.ONOSip[i])
+            i_result = main.ONOSbench.onosInstall(node=main.ONOSip[i])
+            utilities.assert_equals(expect=main.TRUE, actual=i_result,
+                                    onpass="Test step PASS",
+                                    onfail="Test step FAIL")
+            installResult = installResult and i_result
+
+        main.step("Verify ONOS nodes UP status")
+        statusResult = main.TRUE
+        for i in range(int(main.numCtrls)):
+            main.log.info("ONOS Node " + main.ONOSip[i] + " status:")
+            onos_status = main.ONOSbench.onosStatus(node=main.ONOSip[i])
+            utilities.assert_equals(expect=main.TRUE, actual=onos_status,
+                                    onpass="Test step PASS",
+                                    onfail="Test step FAIL")
+            statusResult = (statusResult and onos_status)
+        time.sleep(2)
+        main.step("Start ONOS CLI on all nodes")
+        cliResult = main.TRUE
+        main.step(" Start ONOS cli using thread ")
+        startCliResult = main.TRUE
+        pool = []
+        main.threadID = 0
+        for i in range(int(main.numCtrls)):
+            t = main.Thread(target=main.CLIs[i].startOnosCli,
+                            threadID=main.threadID,
+                            name="startOnosCli",
+                            args=[main.ONOSip[i]],
+                            kwargs={"onosStartTimeout": main.timeout})
+            pool.append(t)
+            t.start()
+            main.threadID = main.threadID + 1
+        for t in pool:
+            t.join()
+            startCliResult = startCliResult and t.result
+        time.sleep(main.startUpSleep)
+
+        main.log.info("Configure apps")
+        main.CLIs[0].setCfg("org.onosproject.net.topology.impl.DefaultTopologyProvider",
+                            "maxEvents 1")
+        main.CLIs[0].setCfg("org.onosproject.net.topology.impl.DefaultTopologyProvider",
+                            "maxBatchMs 0")
+        main.CLIs[0].setCfg("org.onosproject.net.topology.impl.DefaultTopologyProvider",
+                            "maxIdleMs 0")
+        time.sleep(1)
+
+        main.log.info("Copy topology file to Mininet")
+        main.ONOSbench.copyMininetFile(main.topoName,
+                                       main.dependencyPath,
+                                       main.Mininet1.user_name,
+                                       main.Mininet1.ip_address)
+        main.log.info("Stop Mininet...")
+        main.Mininet1.stopNet()
+        time.sleep(main.MNSleep)
+        main.log.info("Start new mininet topology")
         main.Mininet1.startNet()
+        main.log.info("Assign switch to controller to ONOS node 1")
 
-        main.log.report( "Initializeing " + str( clusterCount ) + " node cluster." )
-        for node in range(clusterCount):
-            main.log.info("Starting ONOS " + str(node) + " at IP: " + main.ONOSIp[node])
-            main.ONOSbench.onosInstall( node=main.ONOSIp[node])
+        time.sleep(2)
 
-        for i in range(50):
-            time.sleep(15)
-            print "attempt " + str(i)
-            main.ONOSbench.handle.sendline("onos $OC1 summary")
-            main.ONOSbench.handle.expect(":~")
-            print main.ONOSbench.handle.before
-            if "nodes=" in main.ONOSbench.handle.before:
-                break
-
-        for node in range(clusterCount):
-            for i in range( 2 ):
-                isup = main.ONOSbench.isup( main.ONOSIp[node] )
-                if isup:
-                    main.log.info("ONOS " + str(node) + " is up\n")
-                    break
-            if not isup:
-                main.log.report( "ONOS " + str(node) + " didn't start!" )
-        main.log.info("Startup sequence complete")
-
-        #time.sleep(20)
-
-        main.step('Start onos cli')
-        for i in range(0,clusterCount):
-            cli1 = CLIs[i].startOnosCli(main.ONOSIp[i])
-
-        main.step( 'Configuring application parameters' )
-
-        configName = 'org.onosproject.net.topology.impl.DefaultTopologyProvider'
-        configParam = 'maxEvents 1'
-        main.ONOSbench.onosCfgSet( main.ONOSIp[0], configName, configParam )
-        configParam = 'maxBatchMs 0'
-        main.ONOSbench.onosCfgSet( main.ONOSIp[0], configName, configParam )
-        configParam = 'maxIdleMs 0'
-        main.ONOSbench.onosCfgSet( main.ONOSIp[0], configName, configParam )
-
-    def CASE2(self, main):
-        print "Cluster size: " + str(clusterCount)
-        """
-        Assign s3 to ONOSbench and measure latency
-
-        There are 4 levels of latency measurements to this test:
-        1 ) End-to-end measurement: Complete end-to-end measurement
-           from TCP ( SYN/ACK ) handshake to Graph change
-        2 ) OFP-to-graph measurement: 'ONOS processing' snippet of
-           measurement from OFP Vendor message to Graph change
-        3 ) OFP-to-device measurement: 'ONOS processing without
-           graph change' snippet of measurement from OFP vendor
-           message to Device change timestamp
-        4 ) T0-to-device measurement: Measurement that includes
-           the switch handshake to devices timestamp without
-           the graph view change. ( TCP handshake -> Device
-           change )
-        """
+    def CASE2(self,main):
         import time
-        import subprocess
         import json
-        import requests
-        import os
         import numpy
 
-        ONOSUser = main.params['CTRL']['user']
-        numIter = main.params['TEST']['numIter']
-        iterIgnore = int(main.params['TEST']['iterIgnore'])
+        resultDict = {'up' : {}, 'down' : {}}
+        for i in range(1, main.numCtrls + 1):
+            resultDict['up'][ 'node' + str(i) ] = {}
+            resultDict['up'][ 'node' + str(i) ][ 'Ave' ] = {}
+            resultDict['up'][ 'node' + str(i) ][ 'Std' ] = {}
+            resultDict['up'][ 'node' + str(i) ][ 'T_F' ] = []#TCP to Feature
+            resultDict['up'][ 'node' + str(i) ][ 'F_R' ] = []#Feature to Role
+            resultDict['up'][ 'node' + str(i) ][ 'RQ_RR' ] = []#role request to role reply
+            resultDict['up'][ 'node' + str(i) ][ 'RR_D' ] = []#role reply to Device
+            resultDict['up'][ 'node' + str(i) ][ 'D_G' ] = []#Device to Graph
+            resultDict['up'][ 'node' + str(i) ][ 'E_E' ] = []#TCP to Graph
 
-        deviceTimestampKey = main.params['JSON']['deviceTimestamp']
-        graphTimestampKey = main.params['JSON']['graphTimestamp']
-
-        debugMode = main.params['TEST']['debugMode']
-        onosLog = main.params['TEST']['onosLogFile']
-        resultPath = main.params['DB']['switchEventResultPath']
-        thresholdStr = main.params['TEST']['singleSwThreshold']
-        thresholdObj = thresholdStr.split(',')
-        thresholdMin = int(thresholdObj[0])
-        thresholdMax = int(thresholdObj[1])
-
-        # Look for 'role-request' messages,
-        # which replaces the 'vendor' messages previously seen
-        # on OVS 2.0.1
-        tsharkTcpString = main.params[ 'TSHARK' ][ 'tcpSynAck' ]
-        tsharkFeatureReply = main.params[ 'TSHARK' ][ 'featureReply' ]
-        tsharkRoleRequest = main.params[ 'TSHARK' ][ 'roleRequest' ]
-        tsharkOfString = main.params[ 'TSHARK' ][ 'ofpRoleReply' ]
-        tsharkFinAckSequence = main.params[ 'TSHARK' ][ 'finAckSequence' ]
-
-        tsharkOfOutput = '/tmp/tshark_of_topo.txt'
-        tsharkTcpOutput = '/tmp/tshark_tcp_topo.txt'
-        tsharkRoleOutput = '/tmp/tshark_role_request.txt'
-        tsharkFeatureOutput = '/tmp/tshark_feature_reply.txt'
-        tsharkFinAckOutput = '/tmp/tshark_fin_ack.txt'
-
-        # Switch connect measurement list
-        # TCP Syn/Ack -> Feature Reply latency collection for each node
-        tcpToFeatureLatNodeIter = numpy.zeros((clusterCount, int(numIter)))
-        # Feature Reply -> Role Request latency collection for each node
-        featureToRoleRequestLatNodeIter = numpy.zeros((clusterCount,
-            int(numIter)))
-        # Role Request -> Role Reply latency collection for each node
-        roleRequestToRoleReplyLatNodeIter = numpy.zeros((clusterCount,
-            int(numIter)))
-        # Role Reply -> Device Update latency collection for each node
-        roleReplyToDeviceLatNodeIter = numpy.zeros((clusterCount,
-            int(numIter)))
-        # Device Update -> Graph Update latency collection for each node
-        deviceToGraphLatNodeIter = numpy.zeros((clusterCount,
-            int(numIter)))
-        endToEndLatNodeIter = numpy.zeros((clusterCount, int(numIter)))
-
-        # Switch disconnect measurement lists
-        # Mininet Fin / Ack -> Mininet Ack
-        finAckTransactionLatNodeIter = numpy.zeros((clusterCount,
-            int(numIter)))
-        # Mininet Ack -> Device Event
-        ackToDeviceLatNodeIter = numpy.zeros((clusterCount,
-            int(numIter)))
-        # Device event -> Graph event
-        deviceToGraphDiscLatNodeIter = numpy.zeros((clusterCount,
-            int(numIter)))
-        endToEndDiscLatNodeIter = numpy.zeros((clusterCount, int(numIter)))
-
-        assertion = main.TRUE
-        localTime = time.strftime('%x %X')
-        localTime = localTime.replace('/', '')
-        localTime = localTime.replace(' ', '_')
-        localTime = localTime.replace(':', '')
-
-        if debugMode == 'on':
-            main.ONOSbench.tsharkPcap('eth0', '/tmp/single_sw_lat_pcap_' + localTime)
-            main.log.info('Debug mode is on')
-
-        main.log.report('Latency of adding one switch to controller')
-        main.log.report('First ' + str(iterIgnore) + ' iterations ignored' + ' for jvm warmup time')
-        main.log.report('Total iterations of test: ' + str(numIter))
-
-        for i in range(0, int(numIter)):
-            main.log.info('Starting tshark capture')
-            main.ONOSbench.tsharkGrep(tsharkTcpString, tsharkTcpOutput)
-            main.ONOSbench.tsharkGrep(tsharkOfString, tsharkOfOutput)
-            main.ONOSbench.tsharkGrep(tsharkRoleRequest, tsharkRoleOutput)
-            main.ONOSbench.tsharkGrep(tsharkFeatureReply, tsharkFeatureOutput)
-
-            time.sleep(10)
-
-            main.log.info('Assigning s3 to controller')
-            main.Mininet1.assignSwController(sw='s3',
-                    ip=main.ONOSIp[0])
-
-            jsonStr = []
-            for node in range (0, clusterCount):
-                metricsSwUp = CLIs[node].topologyEventsMetrics()
-                jsonStr.append(metricsSwUp)
-
-            time.sleep(10)
-
-            main.log.info('Stopping all Tshark processes')
-            main.ONOSbench.tsharkStop()
-
-            time.sleep(5)
-
-            '''
-            main.log.info('Copying over tshark files')
-            os.system('scp ' + ONOSUser + '@' + main.ONOSIp[0] +
-                    ':' + tsharkTcpOutput + ' /tmp/')
-            os.system('scp ' + ONOSUser + '@' + main.ONOSIp[0] +
-                    ':' + tsharkRoleOutput + ' /tmp/')
-            os.system('scp ' + ONOSUser + '@' + main.ONOSIp[0] +
-                    ':' + tsharkFeatureOutput + ' /tmp/')
-            os.system('scp ' + ONOSUser + '@' +
-                      main.ONOSIp[0] + ':' + tsharkOfOutput + ' /tmp/')
-            '''
-
-            # Get tcp syn / ack output
-            time.sleep(1)
-
-            tcpFile = open(tsharkTcpOutput, 'r')
-            tempText = tcpFile.readline()
-            tempText = tempText.split(' ')
-            main.log.info('Object read in from TCP capture: ' + str(tempText))
-
-            if len(tempText) > 1:
-                t0Tcp = float(tempText[1]) * 1000.0
+        for i in range(1,main.numCtrls + 1):
+            resultDict['down'][ 'node' + str(i) ] = {}
+            resultDict['down'][ 'node' + str(i) ][ 'Ave' ] = {}
+            resultDict['down'][ 'node' + str(i) ][ 'Std' ] = {}
+            resultDict['down'][ 'node' + str(i) ][ 'FA_A' ] = []#Fin_ack to ACK
+            resultDict['down'][ 'node' + str(i) ][ 'A_D' ] = []#Ack to Device
+            resultDict['down'][ 'node' + str(i) ][ 'D_G' ] = []#Device to Graph
+            resultDict['down'][ 'node' + str(i) ][ 'E_E' ] = []#fin_ack to Graph
+        for i in range(1 , main.sampleSize + main.warmUp):
+            main.log.info("************************************************************")
+            main.log.info("************************ Iteration: {} **********************" .format(str( i )) )
+            if i < main.warmUp:
+                main.switchFunc.captureOfPack( main, main.device, main.ofPackage,
+                                               "up", resultDict, True )
+                main.switchFunc.captureOfPack( main, main.device, main.ofPackage,
+                                               "down", resultDict, True )
             else:
-                main.log.error('Tshark output file for TCP' + ' returned unexpected results')
-                t0Tcp = 0
-                assertion = main.FALSE
-            tcpFile.close()
+                main.switchFunc.captureOfPack( main, main.device, main.ofPackage,
+                                               "up", resultDict, False )
+                main.switchFunc.captureOfPack (main, main.device, main.ofPackage,
+                                               "down", resultDict, False )
+        # Dictionary for result
+        maxDict  = {}
+        maxDict['down'] = {}
+        maxDict['up'] = {}
+        maxDict['down']['max'] = 0
+        maxDict['up']['max'] = 0
+        maxDict['down']['node'] = 0
+        maxDict['up']['node'] = 0
 
-            # Get Role reply output
-            ofFile = open(tsharkOfOutput, 'r')
-            lineOfp = ''
-            while True:
-                tempText = ofFile.readline()
-                if tempText != '':
-                    lineOfp = tempText
-                else:
-                    break
-            obj = lineOfp.split(' ')
-            main.log.info('Object read in from OFP capture: ' +
-                    str(lineOfp))
-            if len(obj) > 1:
-                t0Ofp = float(obj[1]) * 1000.0
-            else:
-                main.log.error('Tshark output file for OFP' +
-                        ' returned unexpected results')
-                t0Ofp = 0
-                assertion = main.FALSE
-            ofFile.close()
+        for i in range(1, main.numCtrls + 1):
+            # calculate average and std for result, and grep the max End to End data
+            EtoEtemp = numpy.average( resultDict['up'][ 'node' + str(i) ]['E_E'] )
+            resultDict['up'][ 'node' + str(i) ][ 'Ave' ][ 'E_E' ] = EtoEtemp
+            if maxDict['up']['max'] < EtoEtemp:
+                # get max End to End latency
+                maxDict['up']['max'] = EtoEtemp
+                maxDict['up']['node'] = i
+            resultDict['up']['node' + str(i)]['Ave']['T_F'] = numpy.average(resultDict['up']['node' + str(i)]['T_F'])
+            resultDict['up']['node' + str(i)]['Ave']['F_R'] = numpy.average(resultDict['up']['node' + str(i)]['F_R'])
+            resultDict['up']['node' + str(i)]['Ave']['RQ_RR'] = numpy.average(resultDict['up']['node' + str(i)]['RQ_RR'])
+            resultDict['up']['node' + str(i)]['Ave']['RR_D'] = numpy.average(resultDict['up']['node' + str(i)]['RR_D'])
+            resultDict['up']['node' + str(i)]['Ave']['D_G'] = numpy.average(resultDict['up']['node' + str(i)]['D_G'])
 
-            # Get role request output
-            roleFile = open(tsharkRoleOutput, 'r')
-            tempText = roleFile.readline()
-            tempText = tempText.split(' ')
-            if len(tempText) > 1:
-                main.log.info('Object read in from role request capture:' +
-                        str(tempText))
-                roleTimestamp = float(tempText[1]) * 1000.0
-            else:
-                main.log.error('Tshark output file for role request' +
-                        ' returned unexpected results')
-                timeRoleRequest = 0
-                assertion = main.FALSE
-            roleFile.close()
+            resultDict['up'][ 'node' + str(i) ][ 'Std' ][ 'E_E' ] = numpy.std( resultDict['up'][ 'node' + str(i) ]['E_E'] )
+            resultDict['up']['node' + str(i)]['Std']['T_F'] = numpy.std(resultDict['up']['node' + str(i)]['T_F'])
+            resultDict['up']['node' + str(i)]['Std']['F_R'] = numpy.std(resultDict['up']['node' + str(i)]['F_R'])
+            resultDict['up']['node' + str(i)]['Std']['RQ_RR'] = numpy.std(resultDict['up']['node' + str(i)]['RQ_RR'])
+            resultDict['up']['node' + str(i)]['Std']['RR_D'] = numpy.std(resultDict['up']['node' + str(i)]['RR_D'])
+            resultDict['up']['node' + str(i)]['Std']['D_G'] = numpy.std(resultDict['up']['node' + str(i)]['D_G'])
 
-            # Get feature reply output
-            featureFile = open(tsharkFeatureOutput, 'r')
-            tempText = featureFile.readline()
-            tempText = tempText.split(' ')
-            if len(tempText) > 1:
-                main.log.info('Object read in from feature reply capture: '+
-                        str(tempText))
-                if tempText[1] != ' ' and float(tempText[1]) > 1400000000.0:
-                    temp = tempText[1]
-                elif tempText[2] != ' ' and float(tempText[2]) > 1400000000.0:
-                    temp = tempText[2]
-                else:
-                    temp = 0
-                featureTimestamp = float(temp) * 1000.0
-            else:
-                main.log.error('Tshark output file for feature reply' +
-                        ' returned unexpected results')
-                timeFeatureReply = 0
-                assertion = main.FALSE
-            featureFile.close()
+            # calculate average and std for result, and grep the max End to End data
+            EtoEtemp = numpy.average( resultDict['down'][ 'node' + str(i) ]['E_E'] )
+            resultDict['down'][ 'node' + str(i) ][ 'Ave' ][ 'E_E' ] = EtoEtemp
+            if maxDict['down']['max'] < EtoEtemp:
+                # get max End to End latency
+                maxDict['down']['max'] = EtoEtemp
+                maxDict['down']['node'] = i
+            resultDict['down']['node' + str(i)]['Ave']['FA_A'] = numpy.average(resultDict['down']['node' + str(i)]['FA_A'])
+            resultDict['down']['node' + str(i)]['Ave']['A_D'] = numpy.average(resultDict['down']['node' + str(i)]['A_D'])
+            resultDict['down']['node' + str(i)]['Ave']['D_G'] = numpy.average(resultDict['down']['node' + str(i)]['D_G'])
 
-            for node in range(0, clusterCount):
-                nodeNum = node+1
-                #metricsSwUp = CLIs[node].topologyEventsMetrics
-                #jsonStr = metricsSwUp()
-                jsonObj = json.loads(jsonStr[node])
-                if jsonObj:
-                    graphTimestamp = jsonObj[graphTimestampKey]['value']
-                    deviceTimestamp = jsonObj[deviceTimestampKey]['value']
-                else:
-                    main.log.error( "Unexpected JSON object" )
-                    # If we could not obtain the JSON object,
-                    # set the timestamps to 0, which will be
-                    # excluded from the measurement later on
-                    # (realized as invalid)
-                    graphTimestamp = 0
-                    deviceTimestamp = 0
+            resultDict['down'][ 'node' + str(i) ][ 'Std' ][ 'E_E' ] = numpy.std( resultDict['down'][ 'node' + str(i) ]['E_E'] )
+            resultDict['down']['node' + str(i)]['Std']['FA_A'] = numpy.std(resultDict['down']['node' + str(i)]['FA_A'])
+            resultDict['down']['node' + str(i)]['Std']['A_D'] = numpy.std(resultDict['down']['node' + str(i)]['A_D'])
+            resultDict['down']['node' + str(i)]['Std']['D_G'] = numpy.std(resultDict['down']['node' + str(i)]['D_G'])
 
-                endToEnd = int(graphTimestamp) - int(t0Tcp)
+            main.log.report( "=====node{} Summary:=====".format( str(i) ) )
+            main.log.report( "=============Switch up=======" )
 
-                # Below are measurement breakdowns of the end-to-end
-                # measurement.
-                tcpToFeature = int(featureTimestamp) - int(t0Tcp)
-                featureToRole = int(roleTimestamp) - int(featureTimestamp)
-                roleToOfp = float(t0Ofp) - float(roleTimestamp)
-                ofpToDevice = float(deviceTimestamp) - float(t0Ofp)
-                # Timestamps gathered from ONOS are millisecond
-                # precision. They are returned as integers, thus no
-                # need to be more precise than 'int'. However,
-                # the processing seems to be mostly under 1 ms,
-                # thus this may be a problem point to handle any
-                # submillisecond output that we are unsure of.
-                # For now, this will be treated as 0 ms if less than 1 ms
-                deviceToGraph = int(graphTimestamp) - int(deviceTimestamp)
+            main.log.report(
+                            "End to End average: {}".format( str(resultDict["up"][ 'node' + str(i) ][ 'Ave' ][ 'E_E' ]) ) )
+            main.log.report(
+                            "End to End Std: {}".format( str(resultDict["up"][ 'node' + str(i) ][ 'Std' ][ 'E_E' ]) ) )
 
-                if endToEnd >= thresholdMin and\
-                   endToEnd < thresholdMax and i >= iterIgnore:
-                    endToEndLatNodeIter[node][i] = endToEnd
-                    main.log.info("ONOS "+str(nodeNum)+ " end-to-end: "+
-                            str(endToEnd) + " ms")
-                else:
-                    main.log.info("ONOS "+str(nodeNum)+ " end-to-end "+
-                            "measurement ignored due to excess in "+
-                            "threshold or premature iteration: ")
-                    main.log.info(str(endToEnd))
+            main.log.report(
+                            "TCP to Feature average: {}".format( str(resultDict["up"][ 'node' + str(i) ][ 'Ave' ][ 'T_F' ]) ) )
+            main.log.report(
+                            "TCP to Feature Std: {}".format( str(resultDict["up"][ 'node' + str(i) ][ 'Std' ][ 'T_F' ]) ) )
 
-                if tcpToFeature >= thresholdMin and\
-                   tcpToFeature < thresholdMax and i >= iterIgnore:
-                    tcpToFeatureLatNodeIter[node][i] = tcpToFeature
-                    main.log.info("ONOS "+str(nodeNum)+ " tcp-to-feature: "+
-                            str(tcpToFeature) + " ms")
-                else:
-                    main.log.info("ONOS "+str(nodeNum)+ " tcp-to-feature "+
-                            "measurement ignored due to excess in "+
-                            "threshold or premature iteration: ")
-                    main.log.info(str(tcpToFeature))
+            main.log.report(
+                            "Feature to Role average: {}".format( str(resultDict["up"][ 'node' + str(i) ][ 'Ave' ][ 'F_R' ]) ) )
+            main.log.report(
+                            "Feature to Role Std: {}".format( str(resultDict["up"][ 'node' + str(i) ][ 'Std' ][ 'F_R' ]) ) )
 
-                if featureToRole >= thresholdMin and\
-                   featureToRole < thresholdMax and i >= iterIgnore:
-                    featureToRoleRequestLatNodeIter[node][i] = featureToRole
-                    main.log.info("ONOS "+str(nodeNum)+ " feature-to-role: "+
-                            str(featureToRole) + " ms")
-                else:
-                    main.log.info("ONOS "+str(nodeNum)+ " feature-to-role "+
-                            "measurement ignored due to excess in "+
-                            "threshold or premature iteration: ")
-                    main.log.info(str(featureToRole))
+            main.log.report(
+                            "Role request to Role reply average: {}".format( str(resultDict["up"][ 'node' + str(i) ][ 'Ave' ][ 'RQ_RR' ]) ) )
+            main.log.report(
+                            "Role request to Role reply Std: {}".format( str(resultDict["up"][ 'node' + str(i) ][ 'Std' ][ 'RQ_RR' ]) ) )
 
-                if roleToOfp >= thresholdMin and\
-                   roleToOfp < thresholdMax and i >= iterIgnore:
-                    roleRequestToRoleReplyLatNodeIter[node][i] = roleToOfp
-                    main.log.info("ONOS "+str(nodeNum)+ " role-to-reply: "+
-                            str(roleToOfp) + " ms")
-                else:
-                    main.log.info("ONOS "+str(nodeNum)+ " role-to-reply "+
-                            "measurement ignored due to excess in "+
-                            "threshold or premature iteration: ")
-                    main.log.info(str(roleToOfp))
+            main.log.report(
+                            "Role reply to Device average: {}".format( str(resultDict["up"][ 'node' + str(i) ][ 'Ave' ][ 'RR_D' ]) ) )
+            main.log.report(
+                            "Role reply to Device Std: {}".format( str(resultDict["up"][ 'node' + str(i) ][ 'Std' ][ 'RR_D' ]) ) )
 
-                if ofpToDevice >= thresholdMin and\
-                   ofpToDevice < thresholdMax and i >= iterIgnore:
-                    roleReplyToDeviceLatNodeIter[node][i] = ofpToDevice
-                    main.log.info("ONOS "+str(nodeNum)+ " reply-to-device: "+
-                            str(ofpToDevice) + " ms")
-                else:
-                    main.log.info("ONOS "+str(nodeNum)+ " reply-to-device "+
-                            "measurement ignored due to excess in "+
-                            "threshold or premature iteration: ")
-                    main.log.info(str(ofpToDevice))
+            main.log.report(
+                            "Device to Graph average: {}".format( str(resultDict["up"][ 'node' + str(i) ][ 'Ave' ][ 'D_G' ]) ) )
+            main.log.report(
+                            "Device to Graph Std: {}".format( str(resultDict["up"][ 'node' + str(i) ][ 'Std' ][ 'D_G' ]) ) )
 
-                if deviceToGraph >= thresholdMin and\
-                   deviceToGraph < thresholdMax and i >= iterIgnore:
-                    deviceToGraphLatNodeIter[node][i] = deviceToGraph
-                    main.log.info("ONOS "+str(nodeNum)+ " device-to-graph: "+
-                            str(deviceToGraph) + " ms")
-                else:
-                    if deviceToGraph == 0:
-                        deviceToGraphLatNodeIter[node][i] = 0
-                        main.log.info("ONOS "+str(nodeNum) +
-                            " device-to-graph measurement "+
-                            "was set to 0 ms because of precision "+
-                            "uncertainty. ")
-                    else:
-                        main.log.info("ONOS "+str(nodeNum)+
-                            " device-to-graph "+
-                            "measurement ignored due to excess in "+
-                            "threshold or premature iteration: ")
-                        main.log.info(str(deviceToGraph))
+            main.log.report( "=============Switch down=======" )
 
-            # ********************
-            time.sleep(5)
+            main.log.report(
+                            "End to End average: {}".format( str(resultDict["down"][ 'node' + str(i) ][ 'Ave' ][ 'E_E' ]) ) )
+            main.log.report(
+                            "End to End Std: {}".format( str(resultDict["down"][ 'node' + str(i) ][ 'Std' ][ 'E_E' ]) ) )
 
-            # Get device id to remove
-            deviceIdJsonStr = main.ONOS1cli.devices()
+            main.log.report(
+                            "Fin_ACK to ACK average: {}".format( str(resultDict["down"][ 'node' + str(i) ][ 'Ave' ][ 'FA_A' ]) ) )
+            main.log.report(
+                            "Fin_ACK to ACK Std: {}".format( str(resultDict["down"][ 'node' + str(i) ][ 'Std' ][ 'FA_A' ]) ) )
 
-            main.log.info( "Device obj obtained: " + str(deviceIdJsonStr) )
-            deviceId = json.loads(deviceIdJsonStr)
+            main.log.report(
+                            "ACK to Device average: {}".format( str(resultDict["down"][ 'node' + str(i) ][ 'Ave' ][ 'A_D' ]) ) )
+            main.log.report(
+                            "ACK to Device Std: {}".format( str(resultDict["down"][ 'node' + str(i) ][ 'Std' ][ 'A_D' ]) ) )
 
-            deviceList = []
-            for device in deviceId:
-                deviceList.append(device['id'])
+            main.log.report(
+                            "Device to Graph average: {}".format( str(resultDict["down"][ 'node' + str(i) ][ 'Ave' ][ 'D_G' ]) ) )
+            main.log.report(
+                            "Device to Graph Std: {}".format( str(resultDict["down"][ 'node' + str(i) ][ 'Std' ][ 'D_G' ]) ) )
 
-            # Measure switch down metrics
-            # TCP FIN/ACK -> TCP FIN
-            # TCP FIN -> Device Event
-            # Device Event -> Graph Event
-            # Capture switch down FIN / ACK packets
+        with open(main.dbFileName, "a") as dbFile:
+            # TODO: Save STD to Database
+            # Scale number
+            temp = str(main.numCtrls)
+            temp += ",'baremetal1'"
+            # put result
+            temp += "," + str( "%.2f" % resultDict['up'][ 'node' + str(maxDict['up']['node']) ][ 'Ave' ][ 'E_E' ] )
+            temp += "," + str( "%.2f" % resultDict['up'][ 'node' + str(maxDict['up']['node']) ][ 'Ave' ][ 'T_F' ] )
+            temp += "," + str( "%.2f" % resultDict['up'][ 'node' + str(maxDict['up']['node']) ][ 'Ave' ][ 'F_R' ] )
+            temp += "," + str( "%.2f" % resultDict['up'][ 'node' + str(maxDict['up']['node']) ][ 'Ave' ][ 'RQ_RR' ] )
+            temp += "," + str( "%.2f" % resultDict['up'][ 'node' + str(maxDict['up']['node']) ][ 'Ave' ][ 'RR_D' ] )
+            temp += "," + str( "%.2f" % resultDict['up'][ 'node' + str(maxDict['up']['node']) ][ 'Ave' ][ 'D_G' ] )
 
-            # The -A 1 grep option allows us to grab 1 extra line after the
-            # last tshark output grepped originally
-            main.ONOSbench.tsharkGrep( tsharkFinAckSequence, tsharkFinAckOutput,
-                    grepOptions = '-A 1' )
-
-            time.sleep( 5 )
-
-            removeJsonList = []
-            main.step('Remove switch from controller')
-            main.Mininet1.deleteSwController('s3')
-            firstDevice = deviceList[0]
-
-            time.sleep( 5 )
-
-            # We need to get metrics before removing
-            # device from the store below.
-            for node in range(0, clusterCount):
-                metricsSwDown = CLIs[node].topologyEventsMetrics
-                jsonStr = metricsSwDown()
-                removeJsonList.append( json.loads(jsonStr) )
-
-            main.ONOSbench.tsharkStop()
-
-            main.log.info( "Removing device " +str(firstDevice)+
-                    " from ONOS" )
-
-            #if deviceId:
-            main.ONOS1cli.deviceRemove(firstDevice)
-
-            #main.log.info('Copying over tshark files')
-            #os.system('scp ' + ONOSUser + '@' + main.ONOSIp[0] + ':' + tsharkFinAckOutput + ' /tmp/')
-
-            time.sleep( 10 )
-            finAckOutputList = []
-            with open(tsharkFinAckOutput, 'r') as f:
-                tempLine = f.readlines()
-                main.log.info('Object read in from FinAck capture: ' +
-                    "\n".join(tempLine))
-
-                index = 1
-                for line in tempLine:
-                    obj = line.split(' ')
-
-                    # There are at least 3 objects in field (valid
-                    # tshark output is lengthy)
-                    if len(obj) > 2:
-                        # If first index of object is like an epoch time
-                        if obj[1] != ' ' and float(obj[1]) > 1400000000.0:
-                            temp = obj[1]
-                        elif obj[2] != ' 'and float(obj[2]) > 1400000000.0:
-                            temp = obj[2]
-                        elif obj[3] != ' 'and float(obj[3]) > 1400000000.0:
-                            temp = obj[3]
-                        else:
-                            temp = 0
-                        if index == 1:
-                            tFinAck = float(temp) * 1000.0
-                            main.log.info("DEBUG-- tFinAck: " + str(tFinAck))
-                        elif index == 3:
-                            tAck = float(temp) * 1000.0
-                            main.log.info("DEBUG-- tAck: " + str(tAck))
-                        else:
-                            tAck = 0
-                    else:
-                        main.log.error('Tshark output file for OFP' +
-                            ' returned unexpected results')
-                        tFinAck = 0
-                        tAck = 0
-                        assertion = main.FALSE
-
-                    index += 1
-                main.log.info("DEBUG-- tFinAck: " + str(tFinAck))
-                main.log.info("DEBUG-- tAck: " + str(tAck))
-
-            # with open() as f takes care of closing file
-
-            time.sleep(5)
-
-            for node in range(0, clusterCount):
-                nodeNum = node+1
-                jsonObj = removeJsonList[node]
-                if jsonObj:
-                    graphTimestamp = jsonObj[graphTimestampKey]['value']
-                    deviceTimestamp = jsonObj[deviceTimestampKey]['value']
-                    main.log.info("Graph timestamp: "+str(graphTimestamp))
-                    main.log.info("Device timestamp: "+str(deviceTimestamp))
-                else:
-                    main.log.error( "Unexpected JSON object" )
-                    # If we could not obtain the JSON object,
-                    # set the timestamps to 0, which will be
-                    # excluded from the measurement later on
-                    # (realized as invalid)
-                    graphTimestamp = 0
-                    deviceTimestamp = 0
-
-                finAckTransaction = float(tAck) - float(tFinAck)
-                ackToDevice = float(deviceTimestamp) - float(tAck)
-                deviceToGraph = float(graphTimestamp) - float(deviceTimestamp)
-                endToEndDisc = int(graphTimestamp) - int(tFinAck)
-                main.log.info("DEBUG-- endToEndDisc = graphTimestamp - tFinAck  == (" + str(graphTimestamp) + "-" + str(tFinAck) + ")") 
-
-                if endToEndDisc >= thresholdMin and\
-                   endToEndDisc < thresholdMax and i >= iterIgnore:
-                    endToEndDiscLatNodeIter[node][i] = endToEndDisc
-                    main.log.info("ONOS "+str(nodeNum) +
-                            "end-to-end disconnection: "+
-                            str(endToEndDisc) + " ms" )
-                else:
-                    main.log.info("ONOS " + str(nodeNum) +
-                            " end-to-end disconnection "+
-                            "measurement ignored due to excess in "+
-                            "threshold or premature iteration: ")
-                    main.log.info(str(endToEndDisc))
-
-                if finAckTransaction >= thresholdMin and\
-                   finAckTransaction < thresholdMax and i >= iterIgnore:
-                    finAckTransactionLatNodeIter[node][i] = finAckTransaction
-                    main.log.info("ONOS "+str(nodeNum)+
-                            " fin/ack transaction: "+
-                            str(finAckTransaction) + " ms")
-                else:
-                    main.log.info("ONOS "+str(nodeNum)+
-                            " fin/ack transaction "+
-                            "measurement ignored due to excess in "+
-                            "threshold or premature iteration: ")
-                    main.log.info(str(finAckTransaction))
-
-                if ackToDevice >= thresholdMin and\
-                   ackToDevice < thresholdMax and i >= iterIgnore:
-                    ackToDeviceLatNodeIter[node][i] = ackToDevice
-                    main.log.info("ONOS "+str(nodeNum)+
-                            " ack-to-device: "+
-                            str(ackToDevice) + " ms")
-                else:
-                    main.log.info("ONOS "+str(nodeNum)+
-                            " ack-to-device "+
-                            "measurement ignored due to excess in "+
-                            "threshold or premature iteration: ")
-                    main.log.info(str(ackToDevice))
-
-                if deviceToGraph >= thresholdMin and\
-                   deviceToGraph < thresholdMax and i >= iterIgnore:
-                    deviceToGraphDiscLatNodeIter[node][i] = deviceToGraph
-                    main.log.info("ONOS "+str(nodeNum)+
-                            " device-to-graph disconnect: "+
-                            str(deviceToGraph) + " ms")
-                else:
-                    main.log.info("ONOS "+str(nodeNum)+
-                            " device-to-graph disconnect "+
-                            "measurement ignored due to excess in "+
-                            "threshold or premature iteration: ")
-                    main.log.info(str(deviceToGraph))
-
-        endToEndAvg = 0
-        ofpToGraphAvg = 0
-        dbCmdList = []
-        for node in range(0, clusterCount):
-            # List of latency for each node
-            endToEndList = []
-            tcpToFeatureList = []
-            featureToRoleList = []
-            roleToOfpList = []
-            ofpToDeviceList = []
-            deviceToGraphList = []
-
-            finAckTransactionList = []
-            ackToDeviceList = []
-            deviceToGraphDiscList = []
-            endToEndDiscList = []
-
-            # LatNodeIter 2d arrays contain all iteration latency
-            # for each node of the current scale cluster size
-            # Switch connection measurements
-            # Set further acceptance criteria for measurements
-            # here if you would like to filter reporting results
-            for item in endToEndLatNodeIter[node]:
-                if item > 0.0:
-                    endToEndList.append(item)
-
-            for item in tcpToFeatureLatNodeIter[node]:
-                if item > 0.0:
-                    tcpToFeatureList.append(item)
-
-            for item in featureToRoleRequestLatNodeIter[node]:
-                if item > 0.0:
-                    featureToRoleList.append(item)
-
-            for item in roleRequestToRoleReplyLatNodeIter[node]:
-                if item > 0.0:
-                    roleToOfpList.append(item)
-
-            for item in roleReplyToDeviceLatNodeIter[node]:
-                if item >= 0.0:
-                    ofpToDeviceList.append(item)
-
-            for item in featureToRoleRequestLatNodeIter[node]:
-                if item > 0.0:
-                    featureToRoleList.append(item)
-
-            for item in deviceToGraphLatNodeIter[node]:
-                if item >= 0.0:
-                    deviceToGraphList.append(item)
-
-            # Switch disconnect measurements
-            for item in endToEndDiscLatNodeIter[node]:
-                if item > 0.0:
-                    endToEndDiscList.append(item)
-
-            for item in finAckTransactionLatNodeIter[node]:
-                if item > 0.0:
-                    finAckTransactionList.append(item)
-
-            for item in ackToDeviceLatNodeIter[node]:
-                if item > 0.0:
-                    ackToDeviceList.append(item)
-
-            for item in deviceToGraphDiscLatNodeIter[node]:
-                if item >= 0.0:
-                    deviceToGraphDiscList.append(item)
-
-            endToEndAvg = round(numpy.mean(endToEndList), 2)
-            endToEndStdDev = round(numpy.std(endToEndList), 2)
-            main.log.info("endToEndList: " + str(endToEndList))
-
-            tcpToFeatureAvg = round(numpy.mean(tcpToFeatureList), 2)
-            tcpToFeatureStdDev = round(numpy.std(tcpToFeatureList), 2)
-            main.log.info("tcpToFeatureList: " + str(tcpToFeatureList))
-
-            featureToRoleAvg = round(numpy.mean(featureToRoleList), 2)
-            featureToRoleStdDev = round(numpy.std(featureToRoleList), 2)
-            main.log.info("featureToRoleList: " + str(featureToRoleList)) 
-
-            roleToOfpAvg = round(numpy.mean(roleToOfpList), 2)
-            roleToOfpStdDev = round(numpy.std(roleToOfpList), 2)
-            main.log.info("roleToOfList: " + str(roleToOfpList))
-
-            ofpToDeviceAvg = round(numpy.mean(ofpToDeviceList), 2)
-            ofpToDeviceStdDev = round(numpy.std(ofpToDeviceList), 2)
-            main.log.info("ofpToDeviceList: " + str(ofpToDeviceList))
-
-            deviceToGraphAvg = round(numpy.mean(deviceToGraphList), 2)
-            deviceToGraphStdDev = round(numpy.std(deviceToGraphList), 2)
-            main.log.info("deviceToGraphList: " + str(deviceToGraphList))
-
-            endToEndDiscAvg = round(numpy.mean(endToEndDiscList), 2)
-            endToEndDiscStdDev = round(numpy.std(endToEndDiscList), 2)
-            main.log.info("endToEndDiscList: " + str(endToEndDiscList))
-
-            finAckAvg = round(numpy.mean(finAckTransactionList), 2)
-            finAckStdDev = round(numpy.std(finAckTransactionList), 2)
-            main.log.info("finAckTransactionList: " + str(finAckTransactionList))
-
-            ackToDeviceAvg = round(numpy.mean(ackToDeviceList), 2)
-            ackToDeviceStdDev = round(numpy.std(ackToDeviceList), 2)
-            main.log.info("ackToDeviceList: " + str(ackToDeviceList))
-
-            deviceToGraphDiscAvg = round(numpy.mean(deviceToGraphDiscList), 2)
-            deviceToGraphDiscStdDev = round(numpy.std(deviceToGraphDiscList), 2)
-            main.log.info("deviceToGraphDiscList: " + str(deviceToGraphDiscList))
-
-            main.log.report(' - Node ' + str(node + 1) + ' Summary - ')
-            main.log.report(' - Switch Connection Statistics - ')
-
-            main.log.report(' End-to-end Avg: ' + str(endToEndAvg) +
-                    ' ms' + ' End-to-end Std dev: ' +
-                    str(endToEndStdDev) + ' ms')
-
-            main.log.report(' Tcp-to-feature-reply Avg: ' +
-                    str(tcpToFeatureAvg) + ' ms')
-            main.log.report(' Tcp-to-feature-reply Std dev: '+
-                    str(tcpToFeatureStdDev) + ' ms')
-
-            main.log.report(' Feature-reply-to-role-request Avg: ' +
-                    str(featureToRoleAvg) + ' ms')
-            main.log.report(' Feature-reply-to-role-request Std Dev: ' +
-                    str(featureToRoleStdDev) + ' ms')
-
-            main.log.report(' Role-request-to-role-reply Avg: ' +
-                    str(roleToOfpAvg) +' ms')
-            main.log.report(' Role-request-to-role-reply Std dev: ' +
-                    str(roleToOfpStdDev) + ' ms')
-
-            main.log.report(' Role-reply-to-device Avg: ' +
-                    str(ofpToDeviceAvg) +' ms')
-            main.log.report(' Role-reply-to-device Std dev: ' +
-                    str(ofpToDeviceStdDev) + ' ms')
-
-            main.log.report(' Device-to-graph Avg: ' +
-                    str(deviceToGraphAvg) + ' ms')
-            main.log.report( 'Device-to-graph Std dev: ' +
-                    str(deviceToGraphStdDev) + ' ms')
-
-            main.log.report(' - Switch Disconnection Statistics - ')
-            main.log.report(' End-to-end switch disconnect Avg: ' +
-                    str(endToEndDiscAvg) + ' ms')
-            main.log.report(' End-to-end switch disconnect Std dev: ' +
-                    str(endToEndDiscStdDev) + ' ms')
-            main.log.report(' Fin/Ack-to-Ack Avg: ' + str(finAckAvg) + ' ms')
-            main.log.report(' Fin/Ack-to-Ack Std dev: ' +
-                    str(finAckStdDev) + ' ms')
-
-            main.log.report(' Ack-to-device Avg: ' + str(ackToDeviceAvg) +
-                    ' ms')
-            main.log.report(' Ack-to-device Std dev: ' + str(ackToDeviceStdDev) +
-                    ' ms')
-
-            main.log.report(' Device-to-graph (disconnect) Avg: ' +
-                    str(deviceToGraphDiscAvg) + ' ms')
-            main.log.report(' Device-to-graph (disconnect) Std dev: ' +
-                    str(deviceToGraphDiscStdDev) + ' ms')
-
-            # For database schema, refer to Amazon web services
-            dbCmdList.append(
-                    "'" + timeToPost + "','switch_latency_results'," +
-                    jenkinsBuildNumber + ',' + str(clusterCount) + ",'baremetal" +
-                    str(node + 1) + "'," +
-                    str(endToEndAvg) + ',' +
-                    str(tcpToFeatureAvg) + ',' +
-                    str(featureToRoleAvg) + ',' +
-                    str(roleToOfpAvg) + ',' +
-                    str(ofpToDeviceAvg) + ',' +
-                    str(deviceToGraphAvg) + ',' +
-                    str(endToEndDiscAvg) + ',' +
-                    str(finAckAvg) + ',' +
-                    str(ackToDeviceAvg) + ',' +
-                    str(deviceToGraphDiscAvg))
-
-        if debugMode == 'on':
-            main.ONOSbench.cpLogsToDir('/opt/onos/log/karaf.log',
-                    '/tmp/', copyFileName='sw_lat_karaf')
-        fResult = open(resultPath, 'a')
-        for line in dbCmdList:
-            if line:
-                fResult.write(line + '\n')
-                main.log.report(line)
-        fResult.close()
-
-        assertion = main.TRUE
-
-        utilities.assert_equals(expect=main.TRUE, actual=assertion,
-                onpass='Switch latency test successful',
-                onfail='Switch latency test failed')
-
-        main.Mininet1.stopNet()
+            temp += "," + str( "%.2f" % resultDict['down'][ 'node' + str(maxDict['down']['node']) ][ 'Ave' ][ 'E_E' ] )
+            temp += "," + str( "%.2f" % resultDict['down'][ 'node' + str(maxDict['down']['node']) ][ 'Ave' ][ 'FA_A' ] )
+            temp += "," + str( "%.2f" % resultDict['down'][ 'node' + str(maxDict['down']['node']) ][ 'Ave' ][ 'A_D' ] )
+            temp += "," + str( "%.2f" % resultDict['down'][ 'node' + str(maxDict['down']['node']) ][ 'Ave' ][ 'D_G' ] )
+            temp += "\n"
+            dbFile.write( temp )
+            dbFile.close()
diff --git a/TestON/tests/SCPF/SCPFswitchLat/dependencies/switchFunc.py b/TestON/tests/SCPF/SCPFswitchLat/dependencies/switchFunc.py
new file mode 100644
index 0000000..2f96cda
--- /dev/null
+++ b/TestON/tests/SCPF/SCPFswitchLat/dependencies/switchFunc.py
@@ -0,0 +1,245 @@
+'''
+    Wrapper function for SCPFswitchLat test
+    Assign switch and capture openflow package
+    remove switch and caputer openflow package
+    calculate latency
+'''
+
+
+import time
+import json
+def processPackage( package ):
+    '''
+    split package information to dictionary
+    Args:
+        package: Package String
+
+    Returns:
+
+    '''
+    pacakge = package.split(" ")
+    dic = {}
+    for s in pacakge:
+        try:
+            [key, value] = s.split("=")
+            dic[key] = value
+        except:
+            continue
+    return dic
+
+def findSeqBySeqAck( seq, packageList):
+    '''
+    Find specific Seq of package in packageList
+    Args:
+        seq: seq from last TCP package
+        packageList: find package in packageList
+
+    Returns:
+
+    '''
+    for l in packageList:
+        temp = processPackage(l)
+        tA = temp['Ack']
+        if int(seq) + 1 == int(tA):
+            return temp['Seq']
+
+def captureOfPack( main, deviceName, ofPack, switchStatus, resultDict, warmup ):
+    '''
+
+    Args:
+        main: TestON class
+        deviceName: device name
+        ofPack: openflow package key word
+        switchStatus: Up -- assign, down -- remove
+        resultDict: dictionary to contain result
+        warmup: warm up boolean
+
+    Returns:
+
+    '''
+    for d in ofPack[switchStatus]:
+        main.log.info("Clean up Tshark")
+        with open(main.tsharkResultPath[switchStatus][d], "w") as tshark:
+            tshark.write("")
+        main.log.info( "Starting tshark capture" )
+        main.ONOSbench.tsharkGrep(ofPack[switchStatus][d], main.tsharkResultPath[switchStatus][d])
+    if switchStatus == 'up':
+        # if up, assign switch to controller
+        time.sleep(main.measurementSleep)
+        main.log.info('Assigning {} to controller'.format(deviceName))
+        main.Mininet1.assignSwController(sw=deviceName, ip=main.ONOSip[0])
+        time.sleep(main.measurementSleep)
+    if switchStatus == 'down':
+        # if down, remove switch from topology
+        time.sleep(main.measurementSleep)
+        main.step('Remove switch from controller')
+        main.Mininet1.deleteSwController(deviceName)
+        time.sleep(10)
+    main.log.info( "Stopping all Tshark processes" )
+    main.ONOSbench.tsharkStop()
+
+    tempResultDict = {}
+    if switchStatus == 'up':
+        for d in main.tsharkResultPath['up']:
+            with open(main.tsharkResultPath[switchStatus][d], "r") as resultFile:
+                # grep tshark result timestamp
+                resultText = resultFile.readlines()
+                resultText = resultText[0]
+                main.log.info("Capture result:" + resultText)
+                resultText = resultText.strip()
+                resultText = resultText.split( " " )
+                if len(resultText) > 1:
+                    tempResultDict[d]= int( ( float(resultText[1]) * 1000 ) )
+                resultFile.close()
+    elif switchStatus == 'down':
+        # if state is down, we should capture Fin/Ack and ACK package
+        # Use seq number in FIN/ACK package to located ACK package
+        with open(main.tsharkResultPath['down']['FA']) as resultFile:
+            resultText = resultFile.readlines()
+            FinAckText = resultText.pop(0)
+            resultFile.close()
+        FinAckSeq = processPackage(FinAckText)['Seq']
+        FinAckOFseq = findSeqBySeqAck(FinAckSeq, resultText)
+
+        with open(main.tsharkResultPath['down']['ACK']) as resultFile:
+            ACKlines = resultFile.readlines()
+            resultFile.close()
+
+        for l in ACKlines:
+            temp = processPackage(l)
+            if temp['Seq'] == findSeqBySeqAck(FinAckOFseq, ACKlines):
+                AckPackage = l
+
+        FinAckText = FinAckText.strip()
+        FinAckText = FinAckText.split(" ")
+        AckPackage = AckPackage.strip()
+        AckPackage = AckPackage.split(" ")
+        tempResultDict['ACK'] = float("%.2f" % (float(AckPackage[1]) * 1000) )
+        tempResultDict['FA'] = float("%.2f" % (float(FinAckText[1]) * 1000) )
+
+    # calculate latency
+    if switchStatus == "up":
+        # up Latency
+        for d in resultDict[switchStatus]:
+            T_Ftemp = 0
+            F_Rtemp = 0
+            RQ_RRtemp = 0
+            try:
+                T_Ftemp = tempResultDict['Feature'] - tempResultDict['TCP']
+                F_Rtemp = tempResultDict['RQ'] - tempResultDict['Feature']
+                RQ_RRtemp = tempResultDict['RR'] - tempResultDict['RQ']
+            except KeyError:
+                main.log.warn("Tshark Result was incorrect!")
+                main.log.warn(tempResultDict)
+                return
+            if not warmup:
+                resultDict[switchStatus][d][ 'T_F' ].append( T_Ftemp )
+                resultDict[switchStatus][d][ 'F_R' ].append( F_Rtemp  )
+                resultDict[switchStatus][d][ 'RQ_RR' ].append( RQ_RRtemp )
+
+            main.log.info("{} TCP to Feature: {}".format(d, str( T_Ftemp ) ) )
+            main.log.info("{} Feature to Role Request: {}".format(d, str(F_Rtemp)))
+            main.log.info("{} Role Request to Role Reply: {}".format(d, str(RQ_RRtemp)))
+
+        for i in range(1, main.numCtrls + 1):
+            RR_Dtemp = 0
+            D_Gtemp = 0
+            E_Etemp = 0
+            main.log.info("================================================")
+            # get onos metrics timestamps
+            try:
+                response = json.loads(main.CLIs[i - 1].topologyEventsMetrics())
+                DeviceTime = int( response.get("topologyDeviceEventTimestamp").get("value") )
+                main.log.info("ONOS{} device Event timestamp: {}".format(i, "%.2f" % DeviceTime))
+                GraphTime = int( response.get("topologyGraphEventTimestamp").get("value") )
+                main.log.info("ONOS{} Graph Event timestamp: {}".format(i, GraphTime))
+            except TypeError:
+                main.log.warn("TypeError")
+                break
+            except ValueError:
+                main.log.warn("Error to decode Json object!")
+                break
+            try:
+                RR_Dtemp = DeviceTime - tempResultDict['RR']
+                D_Gtemp = GraphTime - DeviceTime
+                E_Etemp = GraphTime - tempResultDict['TCP']
+                main.log.info("Role reply to Device:{}".format(RR_Dtemp))
+                main.log.info("Device to Graph:{}".format(D_Gtemp))
+                main.log.info("End to End:{}".format(E_Etemp))
+                main.log.info("================================================")
+            except KeyError:
+                main.log.warn("Tshark Result was incorrect!")
+                main.log.warn(tempResultDict)
+                return
+            except TypeError:
+                main.log.warn("TypeError")
+                break
+            except ValueError:
+                main.log.warn("Error to decode Json object!")
+                break
+            if not warmup:
+                resultDict[switchStatus]['node' + str(i)][ 'RR_D' ].append( RR_Dtemp )
+                resultDict[switchStatus]['node' + str(i)][ 'D_G' ].append( D_Gtemp )
+                resultDict[switchStatus]['node' + str(i)][ 'E_E' ].append( E_Etemp )
+
+            main.log.info( "{} Role Reply to Device: {}".format( d, str(RR_Dtemp) ) )
+            main.log.info( "{} Device to Graph: {}".format( d, str(D_Gtemp) ) )
+            main.log.info( "{} End to End: {}".format( d, str(E_Etemp) ) )
+
+    if switchStatus == "down":
+        # down Latency
+        for d in resultDict[switchStatus]:
+            FA_Atemp = 0
+            try:
+                FA_Atemp = float("%.2f" % (tempResultDict['ACK'] - tempResultDict['FA']) )
+            except KeyError:
+                main.log.warn("Tshark Result was incorrect!")
+                main.log.warn(tempResultDict)
+                return
+            if not warmup:
+                resultDict[switchStatus][d][ 'FA_A' ].append( FA_Atemp )
+            main.log.info( "{} FIN/ACK TO ACK {}:".format(d , FA_Atemp) )
+        for i in range(1, main.numCtrls + 1):
+            A_Dtemp = 0
+            D_Gtemp = 0
+            E_Etemp = 0
+
+            main.log.info("================================================")
+            # get onos metrics timestamps
+            try:
+                response = json.loads(main.CLIs[i - 1].topologyEventsMetrics())
+                DeviceTime = int( response.get("topologyDeviceEventTimestamp").get("value") )
+                main.log.info("ONOS{} device Event timestamp: {}".format(i, DeviceTime))
+                GraphTime = int( response.get("topologyGraphEventTimestamp").get("value") )
+                main.log.info("ONOS{} Graph Event timestamp: {}".format(i, GraphTime))
+            except TypeError:
+                main.log.warn("TypeError")
+                break
+            except ValueError:
+                main.log.warn("Error to decode Json object!")
+                break
+            main.log.info("================================================")
+            try:
+                A_Dtemp = float("%.2f" % (DeviceTime - tempResultDict['ACK']) )
+                D_Gtemp = GraphTime - DeviceTime
+                E_Etemp = float("%.2f" % (GraphTime - tempResultDict['FA']) )
+                main.log.info("ACK to device: {}".format(A_Dtemp))
+                main.log.info("Device ot Graph: {}".format(D_Gtemp))
+                main.log.info("End to End: {}".format(E_Etemp))
+                main.log.info("================================================")
+            except KeyError:
+                main.log.warn("Tshark Result was incorrect!")
+                main.log.warn(tempResultDict)
+                return
+            except TypeError:
+                main.log.warn("TypeError")
+                break
+            except ValueError:
+                main.log.warn("Error to decode Json object!")
+                break
+            if not warmup:
+                resultDict[switchStatus]['node' + str(i)][ 'A_D' ].append( A_Dtemp )
+                resultDict[switchStatus]['node' + str(i)][ 'D_G' ].append( D_Gtemp )
+                resultDict[switchStatus]['node' + str(i)][ 'E_E' ].append( E_Etemp )
+
+