Merge pull request #29 from pingping-lin/ONOS-Next

add checking intents function for SDN-IP
diff --git a/TestON/dependencies/Jenkins_getresult_andrew.py b/TestON/dependencies/Jenkins_getresult_andrew.py
new file mode 100755
index 0000000..0e7ef8d
--- /dev/null
+++ b/TestON/dependencies/Jenkins_getresult_andrew.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python
+
+import sys
+import os
+import re
+import datetime
+import time
+import argparse
+
+parser = argparse.ArgumentParser()
+parser.add_argument("-n", "--name", help="Comma Separated string of test names. Ex: --name='test1, test2, test3'")
+args = parser.parse_args()
+
+#Pass in test names as a comma separated string argument. 
+#Example: ./Jenkins_getresult.py "Test1,Test2,Test3,Test4"
+name_list = args.name.split(",")
+result_list = map(lambda x: x.strip(), name_list)
+
+#NOTE: testnames list should be in order in which it is run
+testnames = result_list
+output = ''
+testdate = datetime.datetime.now()
+
+output +="<p>**************************************</p>"
+output +=testdate.strftime('Jenkins test result for %H:%M on %b %d, %Y. %Z')
+
+#TestON reporting
+for test in testnames:
+    name = os.popen("ls /home/admin/ONLabTest/TestON/logs/ -rt | grep %s | tail -1" % test).read().split()[0]
+    path = "/home/admin/ONLabTest/TestON/logs/" + name + "/"
+    output +="<p></p>"
+    #output +="   Date: %s, %s %s" % (name.split("_")[2], name.split("_")[1], name.split("_")[3]) + "<br>*******************<br>"
+    #Open the latest log folder 
+    output += "<h2>Test "+str(test)+"</h2><p>************************************</p>"
+
+    f = open(path + name + ".rpt")
+
+    #Parse through each line of logs and look for specific strings to output to wiki.
+    #NOTE: with current implementation, you must specify which output to output to wiki by using
+    #main.log.report("") since it is looking for the [REPORT] tag in the logs
+    for line in f:
+        if re.search("Result summary for Testcase", line):
+            output += "<h3>"+str(line)+"</h3>"
+            #output += "<br>"
+        if re.search("\[REPORT\]", line): 
+            line_split = line.split("] ")
+            #line string is split by bracket, and first two items (log tags) in list are omitted from output
+            #join is used to convert list to string
+            line_str = ''.join(line_split[2:])
+            output += "<p>"
+            output += line_str
+            output += "</p>"
+        if re.search("Result:", line):
+            output += "<p>"
+            output += line
+            output += "</p>"
+    f.close()
+
+    #*********************
+    #include any other phrase specific to case you would like to include in wiki here
+    if test == "IntentPerf":
+        output += "URL to Historical Performance results data: <a href='http://10.128.5.54/perf.html'>Perf Graph</a>"
+    #*********************
+print output
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index 9191b89..c888e23 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -153,26 +153,33 @@
         if self.handle :
             main.log.info(self.name+": Checking reachabilty to the hosts using pingall")
             try:
-                response = self.execute(cmd="pingall",prompt="mininet>",timeout=120)
-                print "response: " + str(response)
-            except pexpect.EOF:  
+                response = self.execute(cmd="pingall",prompt="mininet>",timeout=300)
+            except pexpect.EOF:
                 main.log.error(self.name + ": EOF exception found")
                 main.log.error(self.name + ":     " + self.handle.before)
-                #main.cleanup()
-                #main.exit()
-            pattern = 'Results\:\s0\%\sdropped\s'
-            #FIXME:Pending Mininet Pull Request #408
-            #pattern = 'Results\:\s0\.00\%\sdropped\s'
-            #if utilities.assert_matches(expect=pattern,actual=response,onpass="All hosts are reaching",onfail="Unable to reach all the hosts"):
+                main.cleanup()
+                main.exit()
+            except pexpect.TIMEOUT:
+                #We may not want to kill the test if pexpect times out
+                main.log.error(self.name + ": TIMEOUT exception found")
+                main.log.error(self.name + ":     " + str(self.handle.before) )
+            #NOTE: mininet's pingall rounds, so we will check the number of passed and number of failed
+            pattern = "Results\:\s0\%\sdropped\s\((?P<passed>[\d]+)/(?P=passed)"
             if re.search(pattern,response):
                 main.log.info(self.name+": All hosts are reachable")
                 return main.TRUE
             else:
                 main.log.error(self.name+": Unable to reach all the hosts")
+                main.log.info("Pingall ouput: " + str(response))
+                #NOTE: Send ctrl-c to make sure pingall is done
+                self.handle.send("\x03")
+                self.handle.expect("Interrupt")
+                self.handle.expect("mininet>")
                 return main.FALSE
         else :
             main.log.error(self.name+": Connection failed to the host") 
-            return main.FALSE
+            main.cleanup()
+            main.exit()
 
     def fpingHost(self,**pingParams):
         ''' 
@@ -735,9 +742,10 @@
             self.handle.expect("mininet>")
             self.handle.sendline("sh sudo tcpdump -n -i "+ intf + " " + port + " -w " + filename.strip() + "  &")
             self.handle.sendline("")
-            self.handle.sendline("")
             i=self.handle.expect(['No\ssuch\device','listening\son',pexpect.TIMEOUT,"mininet>"],timeout=10)
             main.log.warn(self.handle.before + self.handle.after)
+            self.handle.sendline("")
+            self.handle.expect("mininet>")
             if i == 0:
                 main.log.error(self.name + ": tcpdump - No such device exists. tcpdump attempted on: " + intf)
                 return main.FALSE
@@ -769,7 +777,7 @@
         "pkills tcpdump"
         try:
             self.handle.sendline("sh sudo pkill tcpdump")
-            self.handle.sendline("")
+            self.handle.expect("mininet>")
             self.handle.sendline("")
             self.handle.expect("mininet>")
         except pexpect.EOF:
@@ -857,7 +865,7 @@
         #FIXME: this does not look for extra ports in ONOS, only checks that ONOS has what is in MN
         import json
         from numpy import uint64
-        port_results = main.TRUE
+        ports_results = main.TRUE
         output = {"switches":[]}
         for switch in topo.graph.switches: #iterate through the MN topology and pull out switches and and port info
             ports = []
@@ -882,9 +890,12 @@
         for mn_switch in output['switches']:
             mn_ports = []
             onos_ports = []
+            switch_result = main.TRUE
             for port in mn_switch['ports']:
                 if port['enabled'] == True:
                     mn_ports.append(port['of_port'])
+                #else: #DEBUG only 
+                #    main.log.warn("Port %s on switch %s is down" % ( str(port['of_port']) , str(mn_switch['name'])) )
             for onos_switch in ports_json:
                 #print "Iterating through a new switch as seen by ONOS"
                 #print onos_switch
@@ -894,37 +905,57 @@
                             if port['isEnabled']:
                                 #print "Iterating through available ports on the switch"
                                 #print port
-                                onos_ports.append(int(port['port'])) 
+                                if port['port'] == 'local':
+                                    #onos_ports.append('local')
+                                    onos_ports.append(long(uint64(-2)))
+                                else:
+                                    onos_ports.append(int(port['port']))
+                                    '''
+                                else: #This is likely a new reserved port implemented
+                                    main.log.error("unkown port '" + str(port['port']) )
+                                    '''
+                           #else: #DEBUG
+                           #    main.log.warn("Port %s on switch %s is down" % ( str(port['port']) , str(onos_switch['device']['id'])) )
+                        break
             mn_ports.sort(key=float)
             onos_ports.sort(key=float)
             #print "\nPorts for Switch %s:" % (switch['name'])
             #print "\tmn_ports[] = ", mn_ports
             #print "\tonos_ports[] = ", onos_ports
-            
-            #NOTE:For OF1.3, the OFP_local port number is 0xfffffffe or 4294967294 instead of 0xfffe or 65534 in OF1.0,
-            #   ONOS topology sees the correct port number, however MN topology as read from line 151 of
-            #   https://github.com/ucb-sts/sts/blob/topology_refactoring2/sts/entities/teston_entities.py 
-            #   is 0xfffe which doesn't work correctly with OF1.3 switches.
-            
-            #NOTE: ONOS is abstracting port numbers to 64bit unsigned number(long). So we will be converting the 
-            #   OF reserved ports to these numbers
-
+            mn_ports_log = mn_ports
+            onos_ports_log = onos_ports
+            mn_ports = [x for x in mn_ports]
+            onos_ports = [x for x in onos_ports]
 
             #TODO: handle other reserved port numbers besides LOCAL
-            for mn_port,onos_port in zip(mn_ports,onos_ports):
-                #print "mn == onos port?"
-                #print mn_port, onos_port
-                if mn_port == onos_port or (mn_port == 65534 and onos_port == long(uint64(-2))):
-                    continue
+            #NOTE: List of Reserved Ports
+            #   Local port: -2 in unsigned int in Openflow, the size depends on
+            #       openflow version( 1.0 is 16 bit, 1.3 is 32 bit), ONOS shows
+            #       'local', we store as long(uint64(-2))
+            for mn_port in mn_ports_log:
+                if mn_port in onos_ports:
                     #don't set results to true here as this is just one of many checks and it might override a failure
-                else:  #the ports of this switch don't match
-                    port_results = main.FALSE
-                    break
-            if port_results == main.FALSE:
-                main.log.report("The list of ports for switch %s(%s) does not match:" % (mn_switch['name'], mn_switch['dpid']) )
-                main.log.report("mn_ports[] = " +  str(mn_ports))
-                main.log.report("onos_ports[] = " + str(onos_ports))
-        return port_results
+                    mn_ports.remove(mn_port)
+                    onos_ports.remove(mn_port)
+                #NOTE: OVS reports this as down since there is no link
+                #      So ignoring these for now
+                #TODO: Come up with a better way of handling these
+                if 65534 in mn_ports:
+                    mn_ports.remove(65534)
+                if long(uint64(-2)) in onos_ports:
+                    onos_ports.remove( long(uint64(-2))  )
+            if len(mn_ports):  #the ports of this switch don't match
+                switch_result = main.FALSE
+                main.log.warn("Ports in MN but not ONOS: " + str(mn_ports) )
+            if len(onos_ports):  #the ports of this switch don't match
+                switch_result = main.FALSE
+                main.log.warn("Ports in ONOS but not MN: " + str(onos_ports) )
+            if switch_result == main.FALSE:
+                main.log.report("The list of active ports for switch %s(%s) does not match:" % (mn_switch['name'], mn_switch['dpid']) )
+                main.log.warn("mn_ports[]  =  " + str(mn_ports_log))
+                main.log.warn("onos_ports[] = " + str(onos_ports_log))
+            ports_results = ports_results and switch_result
+        return ports_results
 
 
 
@@ -1007,7 +1038,7 @@
                     if int(onos_port1) == int(port1) and int(onos_port2) == int(port2):
                         first_dir = main.TRUE
                     else:
-                        main.log.report('The port numbers do not match for ' +str(link) +\
+                        main.log.warn('The port numbers do not match for ' +str(link) +\
                                 ' between ONOS and MN. When cheking ONOS for link '+\
                                 '%s/%s -> %s/%s' % (node1, port1, node2, port2)+\
                                 ' ONOS has the values %s/%s -> %s/%s' %\
@@ -1018,7 +1049,7 @@
                     if ( int(onos_port1) == int(port2) and int(onos_port2) == int(port1) ):
                         second_dir = main.TRUE
                     else:
-                        main.log.report('The port numbers do not match for ' +str(link) +\
+                        main.log.warn('The port numbers do not match for ' +str(link) +\
                                 ' between ONOS and MN. When cheking ONOS for link '+\
                                 '%s/%s -> %s/%s' % (node2, port2, node1, port1)+\
                                 ' ONOS has the values %s/%s -> %s/%s' %\
@@ -1065,18 +1096,23 @@
         '''
         #TODO: Add error checking. currently the mininet command has no output
         main.log.info("Updateing MN port information")
-        self.handle.sendline("")
-        self.handle.expect("mininet>")
-        
-        self.handle.sendline("update")
-        self.handle.expect("mininet>")
+        try:
+            self.handle.sendline("")
+            self.handle.expect("mininet>")
 
-        self.handle.sendline("")
-        self.handle.expect("mininet>")
+            self.handle.sendline("update")
+            self.handle.expect("update")
+            self.handle.expect("mininet>")
 
-        return main.TRUE 
+            self.handle.sendline("")
+            self.handle.expect("mininet>")
 
-        
+            return main.TRUE
+        except pexpect.EOF:
+            main.log.error(self.name + ": EOF exception found")
+            main.log.error(self.name + ":     " + self.handle.before)
+            main.cleanup()
+            main.exit()
 
 if __name__ != "__main__":
     import sys
diff --git a/TestON/drivers/common/cli/emulator/remotemininetdriver.py b/TestON/drivers/common/cli/emulator/remotemininetdriver.py
index bb03c07..5d2a7a3 100644
--- a/TestON/drivers/common/cli/emulator/remotemininetdriver.py
+++ b/TestON/drivers/common/cli/emulator/remotemininetdriver.py
@@ -92,7 +92,8 @@
         elif re.search("found multiple mininet",outputs):
             return main.ERROR
         else:
-            print outputs
+            main.log.error("Error, unexpected output in the ping file")
+            main.log.warn( outputs )
             return main.TRUE
 
 
@@ -155,6 +156,11 @@
         main.log.info( "Transferring ping files to TestStation" )
         command = "scp /tmp/ping.* "+ str(testONUser) + "@" + str(testONIP) + ":/tmp/" 
         self.execute(cmd=command,prompt="100%",timeout=20)
+        #Make sure the output is cleared
+        self.handle.sendline("")
+        self.handle.expect("\$")
+        self.handle.sendline("")
+        self.handle.expect("\$")
         self.handle.sendline("")
         self.handle.expect("\$")
         return main.TRUE
@@ -553,7 +559,7 @@
         response = ''
         #print "Disconnecting Mininet"
         if self.handle:
-            self.handle.sendline("exit") 
+            self.handle.sendline("exit")
             self.handle.expect("exit")
             self.handle.expect("(.*)")
             response = self.handle.before
@@ -561,13 +567,15 @@
         else :
             main.log.error("Connection failed to the host")
             response = main.FALSE
-        return response  
+        return response
 
     def get_flowTable(self, protoVersion, sw):
+        #TODO document usage
+        #FIXME: clean up print statements and such
         self.handle.sendline("cd")
-        #self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
-        print "cd expect status: " 
-        print self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
+        self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
+        #print "cd expect status: "
+        #print self.handle.expect(["\$",pexpect.EOF,pexpect.TIMEOUT])
         #TODO: Write seperate versions of the function for this, possibly a string that tells it which switch is in use?
         #For 1.0 version of OVS
         #command = "sudo ovs-ofctl dump-flows " + sw + " | awk '{OFS=\",\" ; print $1 $6 $7 }' |sort -n -k1"
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 282200d..feca717 100644
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -195,10 +195,18 @@
                 #If failed, send ctrl+c to process and try again
                 main.log.info("Starting CLI failed. Retrying...")
                 self.handle.sendline("\x03")
+                i = self.handle.expect(["onos>",pexpect.TIMEOUT],
+                        timeout=30)
+                #Send ctrl+d to exit the onos> prompt that was
+                #not successful
+                self.handle.sendline("\x04")
+                self.handle.expect("\$")
                 self.handle.sendline("onos -w "+str(ONOS_ip))
                 i = self.handle.expect(["onos>",pexpect.TIMEOUT],
                         timeout=30)
                 if i == 0:
+                    main.log.info(str(ONOS_ip)+" CLI Started "+
+                        "successfully after retry attempt")
                     return main.TRUE
                 else:
                     main.log.error("Connection to CLI "+\
@@ -981,8 +989,8 @@
             main.cleanup()
             main.exit()
 
-    def add_point_intent(self, ingress_device, port_ingress,
-            egress_device, port_egress, ethType="", ethSrc="",
+    def add_point_intent(self, ingress_device, egress_device,
+            port_ingress="", port_egress="", ethType="", ethSrc="",
             ethDst="", bandwidth="", lambda_alloc=False, 
             ipProto="", ipSrc="", ipDst="", tcpSrc="", tcpDst=""):
         '''
@@ -1017,12 +1025,11 @@
                     and not bandwidth and not lambda_alloc \
                     and not ipProto and not ipSrc and not ipDst \
                     and not tcpSrc and not tcpDst:
-                cmd = "add-point-intent "+\
-                        str(ingress_device) + "/" + str(port_ingress) + " " +\
-                        str(egress_device) + "/" + str(port_egress)
-       
+                cmd = "add-point-intent"
+      
+
             else:
-                cmd = "add-point-intent "
+                cmd = "add-point-intent"
                 
                 if ethType:
                     cmd += " --ethType " + str(ethType)
@@ -1045,18 +1052,39 @@
                 if tcpDst:
                     cmd += " --tcpDst " + str(tcpDst)
 
-                cmd += " "+str(ingress_device) +\
-                    "/" + str(port_ingress) + " " +\
-                    str(egress_device) + "/" + str(port_egress) 
+            #Check whether the user appended the port 
+            #or provided it as an input
+            if "/" in ingress_device:
+                cmd += " "+str(ingress_device) 
+            else:
+                if not port_ingress:
+                    main.log.error("You must specify "+
+                        "the ingress port")
+                    #TODO: perhaps more meaningful return
+                    return main.FALSE
+
+                cmd += " "+ \
+                    str(ingress_device) + "/" +\
+                    str(port_ingress) + " " 
+
+            if "/" in egress_device:
+                cmd += " "+str(egress_device)
+            else:
+                if not port_egress:
+                    main.log.error("You must specify "+
+                        "the egress port")
+                    return main.FALSE
+                
+                cmd += " "+\
+                    str(egress_device) + "/" +\
+                    str(port_egress)  
 
             self.handle.sendline(cmd)
+            
+            main.log.info(cmd + " sent")
             i = self.handle.expect([
                 "Error",
                 "onos>"])
-          
-            self.handle.sendline("intents")
-            self.handle.expect("onos>")
-            Intenthandle = self.handle.before
 
             if i == 0:
                 main.log.error("Error in adding point-to-point intent")
@@ -1222,6 +1250,51 @@
             main.cleanup()
             main.exit()
 
+    def push_test_intents(self, dpid_src, dpid_dst, num_intents,
+            report=True):
+        '''
+        Description:
+            Push a number of intents in a batch format to 
+            a specific point-to-point intent definition
+        Required:
+            * dpid_src: specify source dpid
+            * dpid_dst: specify destination dpid
+            * num_intents: specify number of intents to push
+        Optional:
+            * report: default True, returns latency information
+        '''
+        try:
+            cmd = "push-test-intents "+\
+                  str(dpid_src)+" "+str(dpid_dst)+" "+\
+                  str(num_intents)
+            self.handle.sendline(cmd)
+            self.handle.expect(cmd)
+            self.handle.expect("onos>")
+                
+            handle = self.handle.before
+              
+            #Some color thing that we want to escape
+            ansi_escape = re.compile(r'\r\r\n\x1b[^m]*m')
+            handle = ansi_escape.sub('', handle)
+    
+            if report:
+                main.log.info(handle)
+                return handle
+            else:
+                return main.TRUE
+
+        except pexpect.EOF:
+            main.log.error(self.name + ": EOF exception found")
+            main.log.error(self.name + ":    " + self.handle.before)
+            main.cleanup()
+            main.exit()
+        except:
+            main.log.info(self.name+" ::::::")
+            main.log.error( traceback.print_exc())
+            main.log.info(self.name+" ::::::")
+            main.cleanup()
+            main.exit()
+
     def intents_events_metrics(self, json_format=True):
         '''
         Description:Returns topology metrics 
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index 5cc7eb6..ca9fa01 100644
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -405,6 +405,11 @@
                 print line
             if report:
                 for line in lines[2:-1]:
+                    #Bracket replacement is for Wiki-compliant
+                    #formatting. '<' or '>' are interpreted 
+                    #as xml specific tags that cause errors
+                    line = line.replace("<","[")
+                    line = line.replace(">","]")
                     main.log.report(line)
             return lines[2]
         except pexpect.EOF:
diff --git a/TestON/tests/IntentPerfNext/IntentPerfNext.params b/TestON/tests/IntentPerfNext/IntentPerfNext.params
index 7e1de77..87e7998 100644
--- a/TestON/tests/IntentPerfNext/IntentPerfNext.params
+++ b/TestON/tests/IntentPerfNext/IntentPerfNext.params
@@ -1,5 +1,5 @@
 <PARAMS>
-    <testcases>1,2</testcases>
+    <testcases>1,4</testcases>
 
     <ENV>
         <cellName>intent_perf_test</cellName>
@@ -32,7 +32,8 @@
 
     <TEST>
         #Number of times to iterate each case
-        <numIter>5</numIter>
+        <numIter>3</numIter>
+        <batchIntentSize>50</batchIntentSize>
     </TEST>
 
     <JSON>
diff --git a/TestON/tests/IntentPerfNext/IntentPerfNext.py b/TestON/tests/IntentPerfNext/IntentPerfNext.py
index 2fb22dc..dc9fadc 100644
--- a/TestON/tests/IntentPerfNext/IntentPerfNext.py
+++ b/TestON/tests/IntentPerfNext/IntentPerfNext.py
@@ -31,7 +31,8 @@
 
         main.step("Creating cell file")
         cell_file_result = main.ONOSbench.create_cell_file(
-                BENCH_ip, cell_name, MN1_ip, "onos-core",
+                BENCH_ip, cell_name, MN1_ip,
+                "onos-core,onos-app-metrics,onos-gui",
                 ONOS1_ip, ONOS2_ip, ONOS3_ip)
 
         main.step("Applying cell file to environment")
@@ -53,6 +54,9 @@
             build_result = main.TRUE
             main.log.info("Git pull skipped by configuration")
 
+        main.log.report("Commit information - ")
+        main.ONOSbench.get_version(report=True)
+
         main.step("Creating ONOS package")
         package_result = main.ONOSbench.onos_package()
 
@@ -73,11 +77,6 @@
         cli2 = main.ONOS2cli.start_onos_cli(ONOS2_ip)
         cli3 = main.ONOS3cli.start_onos_cli(ONOS3_ip)
 
-        main.step("Enable metrics feature")
-        main.ONOS1cli.feature_install("onos-app-metrics")
-        main.ONOS2cli.feature_install("onos-app-metrics")
-        main.ONOS3cli.feature_install("onos-app-metrics")
-
         utilities.assert_equals(expect=main.TRUE,
                 actual = cell_file_result and cell_apply_result and\
                          verify_cell_result and checkout_result and\
@@ -112,10 +111,25 @@
         install_time = main.params['JSON']['installedTime']
         wdRequest_time = main.params['JSON']['wdRequestTime']
         withdrawn_time = main.params['JSON']['withdrawnTime']
+        
+        intent_add_lat_list = []
+
+        #Assign 'linear' switch format for basic intent testing
+        main.Mininet1.assign_sw_controller(
+                sw="1", ip1=ONOS1_ip,port1=default_sw_port)
+        main.Mininet1.assign_sw_controller(
+                sw="2", ip1=ONOS2_ip,port1=default_sw_port)
+        main.Mininet1.assign_sw_controller(
+                sw="3", ip1=ONOS2_ip,port1=default_sw_port)
+        main.Mininet1.assign_sw_controller(
+                sw="4", ip1=ONOS2_ip,port1=default_sw_port)
+        main.Mininet1.assign_sw_controller(
+                sw="5", ip1=ONOS3_ip,port1=default_sw_port)
+
+        time.sleep(10)
 
         devices_json_str = main.ONOS1cli.devices()
         devices_json_obj = json.loads(devices_json_str)
-
         device_id_list = []
 
         #Obtain device id list in ONOS format.
@@ -123,14 +137,11 @@
         for device in devices_json_obj:
             device_id_list.append(device['id'])
 
-        intent_add_lat_list = []
-
         for i in range(0, int(num_iter)):
-            #add_point_intent(ingr_device, ingr_port, 
-            #                 egr_device, egr_port)
+            #add_point_intent(ingr_device,  egr_device,
+            #                 ingr_port,    egr_port)
             main.ONOS1cli.add_point_intent(
-                device_id_list[0], 2,
-                device_id_list[2], 1)
+                device_id_list[0]+"/1", device_id_list[4]+"/1")
         
             #Allow some time for intents to propagate
             time.sleep(5)
@@ -213,6 +224,175 @@
 
     def CASE3(self, main):
         '''
-        CASE3 coming soon
+        Intent Reroute latency
         '''
+        import time
+        import json
+        import requests
+        import os
+
+        ONOS1_ip = main.params['CTRL']['ip1']
+        ONOS2_ip = main.params['CTRL']['ip2']
+        ONOS3_ip = main.params['CTRL']['ip3']
+        ONOS_user = main.params['CTRL']['user']
+
+        default_sw_port = main.params['CTRL']['port1']
+
+        #number of iterations of case
+        num_iter = main.params['TEST']['numIter']
+
+        #Timestamp keys for json metrics output
+        submit_time = main.params['JSON']['submittedTime']
+        install_time = main.params['JSON']['installedTime']
+        wdRequest_time = main.params['JSON']['wdRequestTime']
+        withdrawn_time = main.params['JSON']['withdrawnTime']
+
+        devices_json_str = main.ONOS1cli.devices()
+        devices_json_obj = json.loads(devices_json_str)
+
+        device_id_list = []
+
+        #Obtain device id list in ONOS format.
+        #They should already be in order (1,2,3,10,11,12,13, etc)
+        for device in devices_json_obj:
+            device_id_list.append(device['id'])
+
+        intent_reroute_lat_list = []
+
+        print device_id_list
+
+        for i in range(0, int(num_iter)):
+            #add_point_intent(ingr_device, ingr_port, 
+            #                 egr_device, egr_port)
+            main.ONOS1cli.add_point_intent(
+                device_id_list[0]+"/2", device_id_list[4]+"/1")
+       
+            time.sleep(5)
+
+            intents_str = main.ONOS1cli.intents(json_format=True)
+            intents_obj = json.loads(intents_str)
+            for intent in intents_obj:
+                if intent['state'] == "INSTALLED":
+                    main.log.info("Intent installed successfully")
+                    intent_id = intent['id']
+                else:
+                    #TODO: Add error handling
+                    main.log.info("Intent installation failed")
+                    intent_id = ""
+
+            #NOTE: this interface is specific to
+            #      topo-intentFlower.py topology
+            #      reroute case.
+            main.log.info("Disabling interface s2-eth3 <--> s4")
+            main.Mininet1.handle.sendline(
+                    "sh ifconfig s2-eth3 down")
+            t0_system = time.time()*1000
+                    
+            #TODO: Check for correct intent reroute
+            time.sleep(5)
+
+            #Obtain metrics from ONOS 1, 2, 3
+            intents_json_str_1 = main.ONOS1cli.intents_events_metrics()
+            intents_json_str_2 = main.ONOS2cli.intents_events_metrics()
+            intents_json_str_3 = main.ONOS3cli.intents_events_metrics()
+
+            intents_json_obj_1 = json.loads(intents_json_str_1)
+            intents_json_obj_2 = json.loads(intents_json_str_2)
+            intents_json_obj_3 = json.loads(intents_json_str_3)
+
+            #Parse values from the json object
+            intent_install_1 = \
+                    intents_json_obj_1[install_time]['value']
+            intent_install_2 = \
+                    intents_json_obj_2[install_time]['value']
+            intent_install_3 = \
+                    intents_json_obj_3[install_time]['value']
+
+            intent_reroute_lat_1 = \
+                    int(intent_install_1) - int(t0_system)
+            intent_reroute_lat_2 = \
+                    int(intent_install_2) - int(t0_system)
+            intent_reroute_lat_3 = \
+                    int(intent_install_3) - int(t0_system)
+            
+            intent_reroute_lat_avg = \
+                    (intent_reroute_lat_1 + 
+                     intent_reroute_lat_2 +
+                     intent_reroute_lat_3 ) / 3
+    
+            main.log.info("Intent reroute latency avg for iteration "+
+                    str(i)+": "+str(intent_reroute_lat_avg))
+
+            if intent_reroute_lat_avg > 0.0 and \
+               intent_reroute_lat_avg < 1000:
+                intent_reroute_lat_list.append(intent_reroute_lat_avg)
+            else:
+                main.log.info("Intent reroute latency exceeded "+
+                        "threshold. Skipping iteration "+str(i))
+
+            #TODO: Possibly put this in the driver function
+            main.log.info("Removing intents for next iteration")
+            
+            #NOTE: TODO: Currently, the remove intent will
+            #            not trigger the intent request 
+            #            timestamp. Thus we cannot use the same
+            #            intent to get the latency over iterations.
+            #            we can 1) install different intents every
+            #            time, or 2) look into state machine and 
+            #            determine what timestsamp to get
+            main.ONOS1cli.remove_intent(intent_id)
+            
+        #TODO: Report framework
+        print intent_reroute_lat_list
+
+
+    def CASE4(self, main):
+        import time
+        import json
+        import requests
+        import os
+
+        ONOS1_ip = main.params['CTRL']['ip1']
+        ONOS2_ip = main.params['CTRL']['ip2']
+        ONOS3_ip = main.params['CTRL']['ip3']
+        ONOS_user = main.params['CTRL']['user']
+
+        default_sw_port = main.params['CTRL']['port1']
+    
+        batch_intent_size = main.params['TEST']['batchIntentSize']
+
+        #number of iterations of case
+        num_iter = main.params['TEST']['numIter']
+        
+        main.Mininet1.assign_sw_controller(
+                sw="1", ip1=ONOS1_ip,port1=default_sw_port)
+        main.Mininet1.assign_sw_controller(
+                sw="2", ip1=ONOS2_ip,port1=default_sw_port)
+        main.Mininet1.assign_sw_controller(
+                sw="3", ip1=ONOS2_ip,port1=default_sw_port)
+        main.Mininet1.assign_sw_controller(
+                sw="4", ip1=ONOS2_ip,port1=default_sw_port)
+        main.Mininet1.assign_sw_controller(
+                sw="5", ip1=ONOS3_ip,port1=default_sw_port)
+
+        main.log.report("Batch intent installation test of "+
+                str(batch_intent_size) +" intents")
+
+        main.log.info("Getting list of available devices")
+        device_id_list = []
+        json_str = main.ONOS1cli.devices()
+        json_obj = json.loads(json_str)
+        for device in json_obj:
+            device_id_list.append(device['id'])
+
+        for i in range(0, int(num_iter)):
+            main.log.info("Pushing "+batch_intent_size+" intents")
+            
+            batch_result = main.ONOS1cli.push_test_intents(
+                "of:0000000000000001/1", "of:0000000000000005/2", 
+                batch_intent_size)
+
+            time.sleep(5)
+
+
 
diff --git a/TestON/tests/IntentPerfNext/IntentPerfNext.topo b/TestON/tests/IntentPerfNext/IntentPerfNext.topo
index fbde0e1..75cb259 100644
--- a/TestON/tests/IntentPerfNext/IntentPerfNext.topo
+++ b/TestON/tests/IntentPerfNext/IntentPerfNext.topo
@@ -56,7 +56,7 @@
                 <arg1> --custom topo-intentFlower.py </arg1>
                 <arg2> --arp --mac --topo mytopo</arg2>
                 <arg3> </arg3>
-                <controller> remote,ip=10.128.174.1 </controller>
+                <controller> remote </controller>
             </COMPONENTS>
         </Mininet1>
 
diff --git a/TestON/tests/MultiProd13/MultiProd13.params b/TestON/tests/MultiProd13/MultiProd13.params
index 2f99555..b60f5cf 100755
--- a/TestON/tests/MultiProd13/MultiProd13.params
+++ b/TestON/tests/MultiProd13/MultiProd13.params
@@ -1,6 +1,6 @@
 <PARAMS>
     
-    <testcases>1,4,5,6,7,8,9</testcases>
+    <testcases>1,4,10,31</testcases>    
 
     #Environment variables
     <ENV>
diff --git a/TestON/tests/MultiProd13/MultiProd13.py b/TestON/tests/MultiProd13/MultiProd13.py
index 1c989c0..d825c62 100755
--- a/TestON/tests/MultiProd13/MultiProd13.py
+++ b/TestON/tests/MultiProd13/MultiProd13.py
@@ -223,9 +223,9 @@
         devices1 = main.ONOScli1.devices()
         devices2 = main.ONOScli2.devices()
         devices3 = main.ONOScli3.devices()
-        print "devices1 = ", devices1
-        print "devices2 = ", devices2
-        print "devices3 = ", devices3
+        #print "devices1 = ", devices1
+        #print "devices2 = ", devices2
+        #print "devices3 = ", devices3
         hosts1 = main.ONOScli1.hosts()
         hosts2 = main.ONOScli2.hosts()
         hosts3 = main.ONOScli3.hosts()
@@ -355,14 +355,33 @@
                 onpass="Topology Check Test successful",
                 onfail="Topology Check Test NOT successful")
 
+
+
+
+    def CASE10(self):
+        main.log.report("This testcase uninstalls the reactive forwarding app")
+        main.log.report("__________________________________")
+        main.case("Uninstalling reactive forwarding app")
+        #Unistall onos-app-fwd app to disable reactive forwarding
+        appUninstall_result1 = main.ONOScli1.feature_uninstall("onos-app-fwd")
+        appUninstall_result2 = main.ONOScli2.feature_uninstall("onos-app-fwd")
+        appUninstall_result3 = main.ONOScli3.feature_uninstall("onos-app-fwd")
+        main.log.info("onos-app-fwd uninstalled")
+
+        #After reactive forwarding is disabled, the reactive flows on switches timeout in 10-15s
+        #So sleep for 15s
+        time.sleep(15)
+
+        case10_result = appUninstall_result1 and appUninstall_result2 and appUninstall_result3
+        utilities.assert_equals(expect=main.TRUE, actual=case10_result,onpass="Reactive forwarding app uninstallation successful",onfail="Reactive forwarding app uninstallation failed")
+
+
     def CASE6(self):
         main.log.report("This testcase is testing the addition of host intents and then doing pingall")
         main.log.report("__________________________________")        
-        main.case("Uninstalling reactive forwarding app and addhost intents")
+        main.case("Obtaining hostsfor adding host intents")
         main.step("Get hosts")
-        main.ONOScli1.handle.sendline("hosts")
-        main.ONOScli1.handle.expect("onos>")
-        hosts = main.ONOScli1.handle.before
+        hosts = main.ONOScli1.hosts()
         main.log.info(hosts)
 
         main.step("Get all devices id")
@@ -371,7 +390,8 @@
 
         #ONOS displays the hosts in hex format unlike mininet which does in decimal format
         #So take care while adding intents
-
+        
+        '''
         main.step("Add host intents for mn hosts(h8-h18,h9-h19,h10-h20,h11-h21,h12-h22,h13-h23,h14-h24,h15-h25,h16-h26,h17-h27)")
         hth_intent_result = main.ONOScli1.add_host_intent("00:00:00:00:00:08/-1", "00:00:00:00:00:12/-1")
         hth_intent_result = main.ONOScli1.add_host_intent("00:00:00:00:00:09/-1", "00:00:00:00:00:13/-1")
@@ -383,16 +403,17 @@
         hth_intent_result = main.ONOScli1.add_host_intent("00:00:00:00:00:0F/-1", "00:00:00:00:00:19/-1")
         hth_intent_result = main.ONOScli1.add_host_intent("00:00:00:00:00:10/-1", "00:00:00:00:00:1A/-1")
         hth_intent_result = main.ONOScli1.add_host_intent("00:00:00:00:00:11/-1", "00:00:00:00:00:1B/-1") 
+        '''
 
-
-        #Unistall onos-app-fwd app to disable reactive forwarding
-        main.step("Unistall onos-app-fwd app to disable reactive forwarding")
-        appUninstall_result = main.ONOScli1.feature_uninstall("onos-app-fwd")
-        main.log.info("onos-app-fwd uninstalled")
-
-        #After reactive forwarding is disabled, the reactive flows on switches timeout in 10-15s
-        #So sleep for 15s
-        time.sleep(15)
+        for i in range(8,18):
+            main.log.info("Adding host intent between h"+str(i)+" and h"+str(i+10))
+            host1 =  "00:00:00:00:00:" + str(hex(i)[2:]).zfill(2).upper()
+            host2 =  "00:00:00:00:00:" + str(hex(i+10)[2:]).zfill(2).upper()
+            #NOTE: get host can return None
+            #TODO: handle this
+            host1_id = main.ONOScli1.get_host(host1)['id']
+            host2_id = main.ONOScli1.get_host(host2)['id']
+            tmp_result = main.ONOScli1.add_host_intent(host1_id, host2_id )
 
         flowHandle = main.ONOScli1.flows()
         #print "flowHandle = ", flowHandle
@@ -634,7 +655,7 @@
 
     def CASE8(self):
         '''
-        Host intents removal
+        Intent removal
         ''' 
         main.log.report("This testcase removes host intents before adding the point intents")
         main.log.report("__________________________________")        
@@ -643,31 +664,37 @@
         main.step("Obtain the intent id's")
         intent_result = main.ONOScli1.intents()
         #print "intent_result = ",intent_result
+        
         intent_linewise = intent_result.split("\n")
-        intent_linewise = intent_linewise[1:-1] #ignore the first and last item of the list obtained from split 
-        #for line in intent_linewise:
-            #print "line = ", line
-        intentids = []
+        intentList = []
         for line in intent_linewise:
+            if line.startswith("id="):
+                intentList.append(line)
+
+        intentids = []
+        for line in intentList:
             intentids.append(line.split(",")[0].split("=")[1])
         for id in intentids:
             print "id = ", id
-        
+
         main.step("Iterate through the intentids list and remove each intent")
         for id in intentids:
             main.ONOScli1.remove_intent(intent_id = id)
-        
+
         intent_result = main.ONOScli1.intents()
         intent_linewise = intent_result.split("\n")
-        intent_linewise = intent_linewise[1:-1] #ignore the first and last item of the list obtained from split 
-        
+        list_afterRemoval = []
+        for line in intent_linewise:
+            if line.startswith("id="):
+                list_afterRemoval.append(line)
+
         intentState = {}
-        for id, line in zip(intentids, intent_linewise):
+        for id, line in zip(intentids, list_afterRemoval):
             #print "line after removing intent = ", line
             x = line.split(",")
             state = x[1].split("=")[1]
             intentState[id] = state
-            
+
         case8_result = main.TRUE
         for key,value in intentState.iteritems():
             print "key,value = ", key, value
@@ -676,12 +703,36 @@
             else:    
                 case8_result = case8_result and main.FALSE
 
-        if case8_result == main.TRUE:
+        i = 8
+        Ping_Result = main.TRUE
+        while i <18 :
+            main.log.info("\n\nh"+str(i)+" is Pinging h" + str(i+10))
+            ping = main.Mininet1.pingHost(src="h"+str(i),target="h"+str(i+10))
+            if ping==main.TRUE:
+                Ping_Result = main.TRUE
+            elif ping==main.FALSE:
+                i+=1
+                Ping_Result = main.FALSE
+            else:
+                main.log.info("Unknown error")
+                Ping_Result = main.ERROR
+        
+        #Note: If the ping result failed, that means the intents have been withdrawn correctly.
+        if Ping_Result==main.TRUE:
+            main.log.report("Host intents have not been withdrawn correctly")
+            #main.cleanup()
+            #main.exit()
+        if Ping_Result==main.FALSE:
+            main.log.report("Host intents have been withdrawn correctly")
+
+        case8_result = case8_result and Ping_Result
+
+        if case8_result == main.FALSE:
             main.log.report("Intent removal successful")
         else:
             main.log.report("Intent removal failed")
                         
-        utilities.assert_equals(expect=main.TRUE, actual=case8_result,
+        utilities.assert_equals(expect=main.FALSE, actual=case8_result,
                 onpass="Intent removal test successful",
                 onfail="Intent removal test failed")
              
@@ -867,3 +918,34 @@
                 onpass="Ping all test after Point intents addition successful",
                 onfail="Ping all test after Point intents addition failed")
 
+    def CASE31(self):
+        ''' 
+            This test case adds point intent related to SDN-IP matching on ICMP (ethertype=IPV4, ipProto=1)
+        '''
+        import json
+
+        main.log.report("This test case adds point intent related to SDN-IP matching on ICMP")
+        main.step("Adding bidirectional point intent")
+        #add-point-intent --ipSrc=10.0.0.8/32 --ipDst=10.0.0.18/32 --ethType=IPV4 --ipProto=1  of:0000000000003008/1 of:0000000000006018/1
+        
+        hosts_json = json.loads(main.ONOScli1.hosts())
+        for  i in range(8,11):
+            main.log.info("Adding point intent between h"+str(i)+" and h"+str(i+10))
+            host1 =  "00:00:00:00:00:" + str(hex(i)[2:]).zfill(2).upper()
+            host2 =  "00:00:00:00:00:" + str(hex(i+10)[2:]).zfill(2).upper()
+            host1_id = main.ONOScli1.get_host(host1)['id']
+            host2_id = main.ONOScli1.get_host(host2)['id']
+            for host in hosts_json:
+                if host['id'] == host1_id:
+                    ip1 = host['ips']+"/"+"32"
+                    device1 = str(host['location']['device'])
+                    port1 = 1
+                    print "ip1 = ", ip1
+                    print "device1 = ", device1
+                elif host['id'] == host2_id:
+                    ip2 = str(host['ips'])+"/"+"32"
+                    device2 = str(host['location']["device"])
+                    port2 = 1
+                    print "ip2 = ", ip2
+                    print "device2 = ", device2
+           
diff --git a/TestON/tests/TopoConvNext/TopoConvNext.params b/TestON/tests/TopoConvNext/TopoConvNext.params
index a7a5ac6..f96123a 100644
--- a/TestON/tests/TopoConvNext/TopoConvNext.params
+++ b/TestON/tests/TopoConvNext/TopoConvNext.params
@@ -1,5 +1,5 @@
 <PARAMS>
-    <testcases>1,2,3,2,3,2</testcases>
+    <testcases>1,2,3,2,3,2,4,2,3,2,3,2,4,2,3,2,3,2</testcases>
 
     <ENV>
         <cellName>topo_conv_test</cellName>
@@ -43,9 +43,20 @@
 
         #Number of times to iterate each case
         <numIter>10</numIter>
-        <numSwitch>100</numSwitch>
+        <numSwitch1>100</numSwitch1>
+        <numSwitch2>200</numSwitch2>
+        <numSwitch3>500</numSwitch3>
         #Number of iterations to ignore initially
-        <iterIgnore>0</iterIgnore>
+        <iterIgnore>2</iterIgnore>
+cp single_topo_event_accumulator.cfg ~/ONOS/tools/package/etc/org.onlab.onos.net.topology.impl.DefaultTopologyProvider.cfg
+
+        <topo_accumulator_config>
+        large_topo_event_accumulator.cfg
+        </topo_accumulator_config>
+        <topo_config_name>
+        org.onlab.onos.net.topology.impl.DefaultTopologyProvider.cfg
+        </topo_config_name>
+
 
         <swDisc100Threshold>0,100000</swDisc100Threshold>
     </TEST>
diff --git a/TestON/tests/TopoConvNext/TopoConvNext.py b/TestON/tests/TopoConvNext/TopoConvNext.py
index 37fb24d..0c14867 100644
--- a/TestON/tests/TopoConvNext/TopoConvNext.py
+++ b/TestON/tests/TopoConvNext/TopoConvNext.py
@@ -27,6 +27,8 @@
         #******
         #Global cluster count for scale-out purposes
         global cluster_count 
+        global topo_iteration
+        topo_iteration = 1
         cluster_count = 3 
         #******
         cell_name = main.params['ENV']['cellName']
@@ -45,18 +47,25 @@
         BENCH_ip = main.params['BENCH']['ip']
 
         main.case("Setting up test environment")
+        main.log.info("copying topology event accumulator config file"+\
+                " to ONOS package/etc/ directory")
+        topo_config_name = main.params['TEST']['topo_config_name']
+        topo_config =\
+                main.params['TEST']['topo_accumulator_config']
+        main.ONOSbench.handle.sendline("cp ~/"+topo_config+\
+            " ~/ONOS/tools/package/etc/"+\
+            topo_config_name)
+        main.ONOSbench.handle.expect("\$")
+
         main.log.info("Uninstalling previous instances")
-        main.ONOSbench.onos_uninstall(node_ip = ONOS1_ip)
-        main.ONOSbench.onos_uninstall(node_ip = ONOS2_ip)
-        main.ONOSbench.onos_uninstall(node_ip = ONOS3_ip)
+        #main.ONOSbench.onos_uninstall(node_ip = ONOS1_ip)
+        #main.ONOSbench.onos_uninstall(node_ip = ONOS2_ip)
+        #main.ONOSbench.onos_uninstall(node_ip = ONOS3_ip)
         main.ONOSbench.onos_uninstall(node_ip = ONOS4_ip)
         main.ONOSbench.onos_uninstall(node_ip = ONOS5_ip)
         main.ONOSbench.onos_uninstall(node_ip = ONOS6_ip)
         main.ONOSbench.onos_uninstall(node_ip = ONOS7_ip)
       
-        main.case("Removing raft logs")
-        main.ONOSbench.onos_remove_raft_logs()
-
         main.log.report("Setting up test environment")
 
         main.step("Creating cell file")
@@ -69,6 +78,9 @@
         cell_apply_result = main.ONOSbench.set_cell(cell_name)
         verify_cell_result = main.ONOSbench.verify_cell()
         
+        main.step("Removing raft logs")
+        main.ONOSbench.onos_remove_raft_logs()
+        
         main.step("Git checkout and pull "+checkout_branch)
         if git_pull == 'on':
             checkout_result = \
@@ -79,6 +91,9 @@
             pull_result = main.TRUE
             main.log.info("Skipped git checkout and pull")
 
+        main.log.report("Commit information - ")
+        main.ONOSbench.get_version()
+
         main.step("Using mvn clean & install")
         #mvn_result = main.ONOSbench.clean_install()
         mvn_result = main.TRUE
@@ -154,7 +169,20 @@
        
         #Number of iterations of case
         num_iter = main.params['TEST']['numIter']
-        num_sw = main.params['TEST']['numSwitch']
+        iter_ignore = int(main.params['TEST']['iterIgnore'])
+
+        #***********
+        #Global number of switches that change 
+        #throughout the test
+        global num_sw
+        global topo_iteration    
+        if topo_iteration == 1:
+            num_sw = main.params['TEST']['numSwitch1']
+        elif topo_iteration == 2:
+            num_sw = main.params['TEST']['numSwitch2']
+        elif topo_iteration == 3:
+            num_sw = main.params['TEST']['numSwitch3']
+        #***********
 
         #Timestamp 'keys' for json metrics output.
         #These are subject to change, hence moved into params
@@ -171,8 +199,8 @@
         sw_discovery_lat_list = []
         syn_ack_delta_list = []
 
-        main.case(str(num_sw)+" switch per "+str(cluster_count)+
-                " nodes convergence latency")
+        main.case(str(num_sw)+" switches distributed across "+
+                str(cluster_count)+" nodes convergence latency")
        
         main.log.report("Large topology convergence and scale-out test")
         main.log.report("Currently active ONOS node(s): ")
@@ -180,11 +208,12 @@
         for node in range(1, cluster_count+1):
             report_str += (str(node) + " ") 
         main.log.report(report_str)
-        
-        main.step("Assigning "+num_sw+" switches to each ONOS")
+        main.log.report("Topology size: "+str(num_sw)+" switches")
+
+        main.step("Distributing "+num_sw+" switches to each ONOS")
         index = 1 
         for node in range(1, cluster_count+1):
-            for i in range(index, int(num_sw)+index):
+            for i in range(index, (int(num_sw)/cluster_count)+index):
                 main.Mininet1.assign_sw_controller(
                         sw=str(i),
                         ip1=ONOS_ip_list[node],
@@ -246,13 +275,15 @@
                     MN1_ip+" --dport "+default_sw_port+" -j DROP")
 
             main.log.info("Please wait for switch connection to timeout")
-            time.sleep(60)
-            if cluster_count >= 3:
-                time.sleep(60)
-            if cluster_count >= 5:
-                time.sleep(30)
-            if cluster_count >= 6:
-                time.sleep(30)
+           
+
+            #time.sleep(60)
+            #if cluster_count >= 3:
+            #    time.sleep(60)
+            #if cluster_count >= 5:
+            #    time.sleep(30)
+            #if cluster_count >= 6:
+            #    time.sleep(30)
 
             if cluster_count >= 3:
                 main.ONOS1.tshark_grep("SYN, ACK",
@@ -273,16 +304,35 @@
             if cluster_count == 7:
                 main.ONOS7.tshark_grep("SYN, ACK",
                         "/tmp/syn_ack_onos7_iter"+str(i)+".txt")
+           
+            loop_count = 0
+            device_count = 0
+            while loop_count < 60: 
+                main.log.info("Checking devices for device down")
+                device_str = main.ONOS1cli.devices()
+                device_json = json.loads(device_str)
+                for device in device_json:
+                    if device['available'] == False:
+                        #print device_count
+                        device_count += 1
+                    else:
+                        device_count = 0
+                if device_count >= int(num_sw)*int(cluster_count):
+                    main.step("Flushing iptables and obtaining t0")
+                    t0_system = time.time()*1000
+                    main.ONOS1.handle.sendline("sudo iptables -F")
+                    main.ONOS2.handle.sendline("sudo iptables -F")
+                    main.ONOS3.handle.sendline("sudo iptables -F")
+                    main.ONOS4.handle.sendline("sudo iptables -F")
+                    main.ONOS5.handle.sendline("sudo iptables -F")
+                    main.ONOS6.handle.sendline("sudo iptables -F")
+                    main.ONOS7.handle.sendline("sudo iptables -F")
+                    
+                    break
+                
+                time.sleep(1)
 
-            main.step("Flushing iptables and obtaining t0")
-            t0_system = time.time()*1000
-            main.ONOS1.handle.sendline("sudo iptables -F")
-            main.ONOS2.handle.sendline("sudo iptables -F")
-            main.ONOS3.handle.sendline("sudo iptables -F")
-            main.ONOS4.handle.sendline("sudo iptables -F")
-            main.ONOS5.handle.sendline("sudo iptables -F")
-            main.ONOS6.handle.sendline("sudo iptables -F")
-            main.ONOS7.handle.sendline("sudo iptables -F")
+            main.log.info("System time t0: "+str(t0_system))
 
             counter_loop = 0
             counter_avail1 = 0
@@ -423,7 +473,8 @@
                             int(graph_timestamp_1) - int(t0_system)
                         
                         if graph_lat_1 > sw_disc_threshold_min\
-                            and graph_lat_1 < sw_disc_threshold_max:
+                            and graph_lat_1 < sw_disc_threshold_max\
+                            and int(i) > iter_ignore:
                             sw_discovery_lat_list.append(
                                     graph_lat_1)
                             main.log.info("Sw discovery latency of "+
@@ -461,7 +512,8 @@
                              int(graph_lat_2)) / 2
 
                         if avg_graph_lat > sw_disc_threshold_min\
-                            and avg_graph_lat < sw_disc_threshold_max:
+                            and avg_graph_lat < sw_disc_threshold_max\
+                            and int(i) > iter_ignore:
                             sw_discovery_lat_list.append(
                                     avg_graph_lat)
                             main.log.info("Sw discovery latency of "+
@@ -481,7 +533,7 @@
                         #TODO: Investigate this sleep
                         #      added to 'pad' the results with 
                         #      plenty of time to 'catch up'
-                        time.sleep(20)
+                        time.sleep(5)
 
                         json_str_metrics_1 =\
                             main.ONOS1cli.topology_events_metrics()
@@ -506,13 +558,17 @@
                         graph_lat_3 = \
                             int(graph_timestamp_3) - int(t0_system)
 
+                        main.log.info("DEBUG: graph_timestamp_1: "+
+                                str(graph_timestamp_1))
+
                         avg_graph_lat = \
                             (int(graph_lat_1) +\
                              int(graph_lat_2) +\
                              int(graph_lat_3)) / 3 
                         
                         if avg_graph_lat > sw_disc_threshold_min\
-                            and avg_graph_lat < sw_disc_threshold_max:
+                            and avg_graph_lat < sw_disc_threshold_max\
+                            and int(i) > iter_ignore:
                             sw_discovery_lat_list.append(
                                     avg_graph_lat)
                             main.log.info("Sw discovery latency of "+
@@ -566,7 +622,8 @@
                              int(graph_lat_4)) / 4 
                         
                         if avg_graph_lat > sw_disc_threshold_min\
-                            and avg_graph_lat < sw_disc_threshold_max:
+                            and avg_graph_lat < sw_disc_threshold_max\
+                            and int(i) > iter_ignore:
                             sw_discovery_lat_list.append(
                                     avg_graph_lat)
                             main.log.info("Sw discovery latency of "+
@@ -587,7 +644,7 @@
                         #TODO: Investigate this sleep
                         #      added to 'pad' the results with 
                         #      plenty of time to 'catch up'
-                        time.sleep(20)
+                        time.sleep(5)
                         
                         json_str_metrics_1 =\
                             main.ONOS1cli.topology_events_metrics()
@@ -634,7 +691,8 @@
                              int(graph_lat_5)) / 5 
                         
                         if avg_graph_lat > sw_disc_threshold_min\
-                            and avg_graph_lat < sw_disc_threshold_max:
+                            and avg_graph_lat < sw_disc_threshold_max\
+                            and int(i) > iter_ignore:
                             sw_discovery_lat_list.append(
                                     avg_graph_lat)
                             main.log.info("Sw discovery latency of "+
@@ -704,7 +762,8 @@
                              int(graph_lat_6)) / 6 
                         
                         if avg_graph_lat > sw_disc_threshold_min\
-                            and avg_graph_lat < sw_disc_threshold_max:
+                            and avg_graph_lat < sw_disc_threshold_max\
+                            and int(i) > iter_ignore:
                             sw_discovery_lat_list.append(
                                     avg_graph_lat)
                             main.log.info("Sw discovery latency of "+
@@ -726,7 +785,7 @@
                         #TODO: Investigate this sleep
                         #      added to 'pad' the results with 
                         #      plenty of time to 'catch up'
-                        time.sleep(20)
+                        time.sleep(5)
                         
                         json_str_metrics_1 =\
                             main.ONOS1cli.topology_events_metrics()
@@ -789,7 +848,8 @@
                              int(graph_lat_7)) / 7 
                         
                         if avg_graph_lat > sw_disc_threshold_min\
-                            and avg_graph_lat < sw_disc_threshold_max:
+                            and avg_graph_lat < sw_disc_threshold_max\
+                            and int(i) > iter_ignore:
                             sw_discovery_lat_list.append(
                                     avg_graph_lat)
                             main.log.info("Sw discovery latency of "+
@@ -906,11 +966,10 @@
             "(last sw SYN/ACK time - first sw SYN/ACK time) "+
             str(sum(syn_ack_delta_list)/len(syn_ack_delta_list)) +
             " ms")
-        main.log.report("Switch discovery lat for "+\
-            str(cluster_count)+" instance(s), 100 sw each: ")
-        main.log.report("Avg: "+str(sw_lat_avg)+" ms")
-        main.log.report("Std Deviation: "+
-                str(round(sw_lat_dev,1))+" ms")
+        main.log.report(str(num_sw)+" Switch discovery lat for "+\
+            str(cluster_count)+" instance(s): ")
+        main.log.report("Avg: "+str(sw_lat_avg)+" ms  "+
+            "Std Deviation: "+str(round(sw_lat_dev,1))+" ms")
 
         utilities.assert_equals(expect=main.TRUE, actual=assertion,
                 onpass="Switch discovery convergence latency" +\
@@ -946,10 +1005,12 @@
         #cluster count and start from 3.
         #You can optionally change the increment to
         #test steps of node sizes, such as 3,5,7
-        
+       
         global cluster_count
         cluster_count += 2 
-      
+        main.log.report("Increasing cluster size to "+
+            str(cluster_count))
+
         install_result = main.FALSE
         #Supports up to 7 node configuration
         #TODO: Cleanup this ridiculous repetitive code 
@@ -957,16 +1018,18 @@
             main.log.info("Installing ONOS on node 4")
             install_result = \
                 main.ONOSbench.onos_install(node=ONOS4_ip)
+            time.sleep(5)
             main.log.info("Starting CLI")
             main.ONOS4cli.start_onos_cli(ONOS4_ip)
             main.ONOS1cli.add_node(ONOS4_ip, ONOS4_ip)
         
         elif cluster_count == 5:
-            main.log.info("Installing ONOS on node 5")
+            main.log.info("Installing ONOS on nodes 4 and 5")
             install_result1 = \
-                main.ONOSbench.onos_install(options="",node=ONOS4_ip)
+                main.ONOSbench.onos_install(node=ONOS4_ip)
             install_result2 = \
                 main.ONOSbench.onos_install(node=ONOS5_ip)
+            time.sleep(5)
             main.log.info("Starting CLI")
             main.ONOS4cli.start_onos_cli(ONOS4_ip)
             main.ONOS5cli.start_onos_cli(ONOS5_ip)
@@ -975,13 +1038,14 @@
             install_result = install_result1 and install_result2
 
         elif cluster_count == 6:
-            main.log.info("Installing ONOS on node 6")
+            main.log.info("Installing ONOS on nodes 4, 5,and 6")
             install_result1 = \
                 main.ONOSbench.onos_install(options="",node=ONOS4_ip)
             install_result2 = \
                 main.ONOSbench.onos_install(options="",node=ONOS5_ip)
             install_result3 = \
                 main.ONOSbench.onos_install(node=ONOS6_ip)
+            time.sleep(5)
             main.log.info("Starting CLI")
             main.ONOS4cli.start_onos_cli(ONOS4_ip)
             main.ONOS5cli.start_onos_cli(ONOS5_ip)
@@ -993,7 +1057,7 @@
                     install_result3
 
         elif cluster_count == 7:
-            main.log.info("Installing ONOS on node 7")
+            main.log.info("Installing ONOS on nodes 4, 5, 6,and 7")
             install_result1 = \
                 main.ONOSbench.onos_install(options="",node=ONOS4_ip)
             install_result2 = \
@@ -1027,3 +1091,37 @@
                        " nodes successful",
                 onfail="Scale out to "+str(cluster_count)+\
                        " nodes failed")
+
+
+    def CASE4(self, main):
+        '''
+        Cleanup ONOS nodes and Increase topology size
+        '''
+        #TODO: use meaningful assertion
+        assertion=main.TRUE
+
+        ONOS1_ip = main.params['CTRL']['ip1']
+        ONOS2_ip = main.params['CTRL']['ip2']
+        ONOS3_ip = main.params['CTRL']['ip3']
+        ONOS4_ip = main.params['CTRL']['ip4']
+        ONOS5_ip = main.params['CTRL']['ip5']
+        ONOS6_ip = main.params['CTRL']['ip6']
+        ONOS7_ip = main.params['CTRL']['ip7']
+        MN1_ip = main.params['MN']['ip1']
+        BENCH_ip = main.params['BENCH']['ip']
+
+        main.log.info("Uninstalling previous instances")
+        main.ONOSbench.onos_uninstall(node_ip = ONOS4_ip)
+        main.ONOSbench.onos_uninstall(node_ip = ONOS5_ip)
+        main.ONOSbench.onos_uninstall(node_ip = ONOS6_ip)
+        main.ONOSbench.onos_uninstall(node_ip = ONOS7_ip)
+        
+        global topo_iteration
+        global cluster_count
+        cluster_count = 3 
+        topo_iteration += 1
+
+        main.log.report("Increasing topology size")
+        utilities.assert_equals(expect=main.TRUE, actual=assertion,
+            onpass="Topology size increased successfully",
+            onfail="Topology size was not increased")
diff --git a/TestON/tests/TopoConvNext/TopoConvNext.topo b/TestON/tests/TopoConvNext/TopoConvNext.topo
index 855e688..b7e9e96 100644
--- a/TestON/tests/TopoConvNext/TopoConvNext.topo
+++ b/TestON/tests/TopoConvNext/TopoConvNext.topo
@@ -143,7 +143,7 @@
             <type>MininetCliDriver</type>
             <connect_order>16</connect_order>
             <COMPONENTS>
-                <arg1> --custom topo-700sw.py </arg1>
+                <arg1> --custom topo-500sw.py </arg1>
                 <arg2> --arp --mac --topo mytopo</arg2>
                 <arg3> </arg3>
                 <controller> remote </controller>
diff --git a/TestON/tests/TopoPerfNext/TopoPerfNext.params b/TestON/tests/TopoPerfNext/TopoPerfNext.params
index 7eac6ef..42512e8 100644
--- a/TestON/tests/TopoPerfNext/TopoPerfNext.params
+++ b/TestON/tests/TopoPerfNext/TopoPerfNext.params
@@ -1,5 +1,5 @@
 <PARAMS>
-    <testcases>1,2,3,4</testcases>
+    <testcases>1,2,3</testcases>
 
     <ENV>
         <cellName>topo_perf_test</cellName>
@@ -38,6 +38,13 @@
         <debugMode>off</debugMode>
         <onosLogFile>/opt/onos/log/karaf*</onosLogFile>
 
+        <topo_config_file>
+        single_topo_event_accumulator.cfg
+        </topo_config_file>
+        <topo_config_name>
+        org.onlab.onos.net.topology.impl.DefaultTopologyProvider.cfg
+        </topo_config_name>
+
         #Number of times to iterate each case
         <numIter>20</numIter>
         <numSwitch>2</numSwitch>
diff --git a/TestON/tests/TopoPerfNext/TopoPerfNext.py b/TestON/tests/TopoPerfNext/TopoPerfNext.py
index a710f82..49089bf 100644
--- a/TestON/tests/TopoPerfNext/TopoPerfNext.py
+++ b/TestON/tests/TopoPerfNext/TopoPerfNext.py
@@ -42,7 +42,18 @@
         MN1_ip = main.params['MN']['ip1']
         BENCH_ip = main.params['BENCH']['ip']
 
+        topo_cfg_file = main.params['TEST']['topo_config_file']
+        topo_cfg_name = main.params['TEST']['topo_config_name']
+        
         main.case("Setting up test environment")
+        main.log.info("Copying topology event accumulator config"+\
+            " to ONOS /ppackage/etc")
+        main.ONOSbench.handle.sendline("cp ~/"+\
+            topo_cfg_file+\
+            "~/ONOS/tools/package/etc/"+\
+            topo_cfg_name)
+        main.ONOSbench.handle.expect("\$")
+
         main.log.report("Setting up test environment")
 
         main.step("Cleaning previously installed ONOS if any")
@@ -75,6 +86,10 @@
             pull_result = main.TRUE
             main.log.info("Skipped git checkout and pull")
 
+        #TODO: Uncomment when wiki posting works
+        #main.log.report("Commit information - ")
+        #main.ONOSbench.get_version(report=True)
+
         main.step("Using mvn clean & install")
         #mvn_result = main.ONOSbench.clean_install()
         mvn_result = main.TRUE
@@ -360,6 +375,17 @@
                     and avg_delta_ofp_graph < threshold_max\
                     and int(i) > iter_ignore:
                 latency_ofp_to_graph_list.append(avg_delta_ofp_graph)
+            elif avg_delta_ofp_graph > (-10) and \
+                    avg_delta_ofp_graph < 0.0 and\
+                    int(i) > iter_ignore:
+                main.log.info("Sub-millisecond result likely; "+
+                    "negative result was rounded to 0")
+                #NOTE: Current metrics framework does not 
+                #support sub-millisecond accuracy. Therefore,
+                #if the result is negative, we can reasonably
+                #conclude sub-millisecond results and just 
+                #append the best rounded effort - 0 ms. 
+                latency_ofp_to_graph_list.append(0)
             else:
                 main.log.info("Results for ofp-to-graph "+\
                         "ignored due to excess in threshold")
@@ -509,7 +535,9 @@
                 "Avg: "+str(latency_end_to_end_avg)+" ms "+
                 "Std Deviation: "+latency_end_to_end_std_dev+" ms")
         main.log.report("Switch add - OFP-to-Graph latency: "+\
-                "Avg: "+str(latency_ofp_to_graph_avg)+" ms "+
+                "Note: results are not accurate to sub-millisecond. "+
+                "Any sub-millisecond results are rounded to 0 ms. ")
+        main.log.report("Avg: "+str(latency_ofp_to_graph_avg)+" ms "+
                 "Std Deviation: "+latency_ofp_to_graph_std_dev+" ms")
         main.log.report("Switch add - TCP-to-OFP latency: "+\
                 "Avg: "+str(latency_tcp_to_ofp_avg)+" ms "+