Stratum Support for Segement Rounting Suite

- Add Stratum Bmv2 switch support for SRDhcpRelay and SRRouting tests
- Add Support for 0x1 topology on a Stratum Tofino HW switch
- Support for dockerized mininet with Stratum BMv2 switches
- Update scapy driver to work with newer versions of scapy
- Simple parsing for scapy ping output
- Add support for fetching and installing external onos apps
- Add support for onos-diagnostics profiles
- Move onos log levels to params file
- Add onos cfg settings to SR tests

Change-Id: I7c4a71484c8fd5735da9ef09b96d8990283b199b
(cherry picked from commit bef6d9bd943996483fed32130cb30ad26a06aac0)
diff --git a/TestON/core/logger.py b/TestON/core/logger.py
index 263e95b..7826017 100644
--- a/TestON/core/logger.py
+++ b/TestON/core/logger.py
@@ -27,6 +27,7 @@
 import datetime
 import re
 import os
+import json
 class Logger:
     '''
         Add continuous logs and reports of the test.
@@ -47,11 +48,7 @@
         logmsg = logmsg + "\n\tTest Params : " + main.testDir + "/" +  main.paramsFile + ""
         logmsg = logmsg + "\n\tTopology : " + main.testDir + "/" + main.topoFile + ""
         logmsg = logmsg + "\n" + " " * 30 + "+" + "-" * 18 + "+" + "\n" + "-" * 27 + "  { Script Exec Params }  " + "-" * 27 + "\n" + " " * 30 + "+" + "-" * 18 + "+\n"
-        values = "\n\t" + str( main.params )
-        values = re.sub( ",", "\n\t", values )
-        values = re.sub( "{", "\n\t", values )
-        values = re.sub( "}", "\n\t", values )
-        logmsg = logmsg + values
+        logmsg += "\n" + json.dumps( main.params, sort_keys=True, indent=4 )
         logmsg = logmsg + "\n\n" + " " * 31 + "+---------------+\n" + "-" * 29 + " { Components Used }  " + "-" * 29 + "\n" + " " * 31 + "+---------------+\n"
         component_list = []
         component_list.append( None )
@@ -72,11 +69,8 @@
                 logmsg += "\t" + str( component_list[ index ] ) + "\n"
 
         logmsg = logmsg + "\n\n" + " " * 30 + "+--------+\n" + "-" * 28 + " { Topology }  " + "-" * 28 + "\n" + " " * 30 + "+--------+\n"
-        values = "\n\t" + str( main.topology[ 'COMPONENT' ] )
-        values = re.sub( ",", "\n\t", values )
-        values = re.sub( "{", "\n\t", values )
-        values = re.sub( "}", "\n\t", values )
-        logmsg = logmsg + values
+        sortedComponents = sorted( main.topology['COMPONENT'].items(), key=lambda (k, v): v[ 'connect_order' ] )
+        logmsg += "\n" + json.dumps( sortedComponents, indent=4 )
         logmsg = logmsg + "\n" + "-" * 60 + "\n"
 
         # enter into log file all headers
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index 55a106f..94664ad 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -63,6 +63,8 @@
         self.scapyPrompt = ">>>"
         self.graph = Graph()
         self.sudoRequired = True
+        self.mExecDir = None
+        self.hostHome = None
 
     def connect( self, **connectargs ):
         """
@@ -109,6 +111,8 @@
                                self.user_name +
                                "@" +
                                self.ip_address )
+                self.handle.sendline( "bash -i" )
+                self.handle.expect( self.bashPrompt )
                 return main.TRUE
             else:
                 main.log.error( "Connection failed to the host " +
@@ -608,7 +612,10 @@
                 cmds = []
                 if self.getIPAddress( host ):
                     flushCmd = "{} ip neigh flush all".format( host )
-                    cmds.append( "{} arping -c 1 -w {} {}".format( host, wait, dstIp ) )
+                    intf = hosts[ host ][ 'interfaces' ][ 0 ].get( 'name' )
+                    intfStr = "-i {}".format( intf ) if intf else ""
+                    cmds.append( "{} arping -c 1 -w {} {} {}".format(
+                        host, wait, intfStr, dstIp ) )
                     main.log.debug( "Sending IPv4 arping from host {}".format( host ) )
                 elif self.getIPAddress( host, proto='IPV6' ):
                     flushCmd = "{} ip -6 neigh flush all".format( host )
@@ -827,10 +834,11 @@
                                         timeout=wait + 5 )
                 # For some reason we need to send something
                 # Otherwise ping results won't be read by handle
+                response = self.handle.before
                 self.handle.sendline( "" )
                 self.handle.expect( self.hostPrompt )
                 if i == 0:
-                    response = self.handle.before
+                    response += self.handle.before
                     if not re.search( ',\s0\%\spacket\sloss', response ):
                         main.log.debug( "Ping failed between %s and %s" % ( self.name, dstIP ) )
                         isReachable = main.FALSE
@@ -1145,19 +1153,23 @@
 
             pattern = ''
             if proto == 'IPV4':
-                pattern = "inet\saddr:(\d+\.\d+\.\d+\.\d+)\s\sBcast"
+                ip4Pat = r"(\d+\.\d+\.\d+\.\d+)"
+                pattern = r"inet\s(addr:)?(?P<ip>" + ip4Pat + ")\s\s((Bcast:" + ip4Pat + "\s\s|netmask\s" + ip4Pat + "\s\sbroadcast\s" + ip4Pat + "))"
             else:
-                pattern = "inet6\saddr:\s([\w,:]*)/\d+\sScope:Global"
+                inet6Pat = r'(?P<ip>((?:[0-9a-fA-F]{1,4})?(?:[:0-9a-fA-F]{1,4}){1,7}(?:::)?(?:[:0-9a-fA-F]{1,4}){1,7}))'
+                pattern = r"inet6\s(addr:\s)?" + inet6Pat + r"(/\d+)?\s(Scope:(Global|Link)|\sprefixlen\s(\d)+\s\sscopeid 0x(\d+)\<(link|global>))"
             ipAddressSearch = re.search( pattern, response )
             if not ipAddressSearch:
+                main.log.debug( response )
+                main.log.warn( "Could not find %s address" % proto )
                 return None
             main.log.info(
                 self.name +
                 ": IP-Address of Host " +
                 host +
                 " is " +
-                ipAddressSearch.group( 1 ) )
-            return ipAddressSearch.group( 1 )
+                ipAddressSearch.group( 'ip' ) )
+            return ipAddressSearch.group( 'ip' )
         else:
             main.log.error( self.name + ": Connection failed to the host" )
 
@@ -3613,14 +3625,23 @@
         """
            updates the port address and status information for
            each port in mn"""
-        # TODO: Add error checking. currently the mininet command has no output
         main.log.info( "Updating MN port information" )
         try:
             self.handle.sendline( "" )
             self.handle.expect( "mininet>" )
 
+            # If update command isn't available, do it manually
             self.handle.sendline( "update" )
-            self.handle.expect( "mininet>", timeout )
+            self.handle.expect( "update" )
+            i = self.handle.expect( [ "Unknown command: update", "mininet>" ], timeout )
+            if i == 0:
+                main.log.debug( self.handle.before + self.handle.after )
+                main.log.warn( "Mininet cli does not have update command, attempting to update interfaces without it" )
+                self.handle.expect( "mininet>" )
+                self.handle.sendline( "px [i.updateAddr() for h in net.hosts for i in h.intfs.values() ] " )
+                self.handle.expect( "mininet>", timeout )
+                self.handle.sendline( "px [i.updateAddr() for s in net.switches for i in h.intfs.values() ] " )
+                self.handle.expect( "mininet>", timeout )
 
             self.handle.sendline( "" )
             self.handle.expect( "mininet>" )
@@ -3777,7 +3798,7 @@
                 main.log.exception( self.name + ": Uncaught exception!" )
                 return main.FALSE
 
-    def createHostComponent( self, name ):
+    def createHostComponent( self, name, execDir=None, hostHome=None ):
         """
         Creates a new mininet cli component with the same parameters as self.
         This new component is intended to be used to login to the hosts created
@@ -3795,7 +3816,17 @@
             # namespace is clear, creating component
             main.componentDictionary[ name ] = main.componentDictionary[ self.name ].copy()
             main.componentDictionary[ name ][ 'connect_order' ] = str( int( main.componentDictionary[ name ][ 'connect_order' ] ) + 1 )
-            main.componentInit( name )
+            component = main.componentInit( name )
+            if execDir is not None:
+                component.mExecDir = execDir
+            else:
+                component.mExecDir = self.mExecDir
+
+            if hostHome is not None:
+                component.hostHome = hostHome
+            else:
+                component.hostHome = self.hostHome
+            component.hostPrompt = self.hostPrompt
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
             main.log.error( self.name + ":     " + self.handle.before )
@@ -3840,17 +3871,31 @@
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanAndExit()
 
-    def startHostCli( self, host=None ):
+    def startHostCli( self, host=None, execDir=None, hostHome=None ):
         """
         Use the mininet m utility to connect to the host's cli
+        mnexec tries to cd to cwd after it connects to the host. If execDir
+        is set, this will change cwd to execDir before executing m.
+        If hostHome is set, the function will export the value to the HOME
+        environment variable.
         """
         # These are fields that can be used by scapy packets. Initialized to None
         self.hostIp = None
         self.hostMac = None
+        if execDir is not None:
+            self.mExecDir = execDir
+        if hostHome is not None:
+            self.hostHome = hostHome
         try:
             if not host:
                 host = self.name
+            if self.mExecDir:
+                self.handle.sendline( "cd %s" % self.mExecDir )
+                self.handle.expect( self.prompt )
+
             self.handle.sendline( self.home + "/util/m " + host )
+            if self.hostHome:
+                self.handle.sendline( "export HOME=%s" % self.hostHome )
             self.handle.sendline( "cd" )
             self.handle.expect( self.hostPrompt )
             self.handle.sendline( "" )
@@ -3858,6 +3903,7 @@
             return main.TRUE
         except pexpect.TIMEOUT:
             main.log.exception( self.name + ": Command timed out" )
+            main.log.debug( self.handle.before )
             return main.FALSE
         except pexpect.EOF:
             main.log.exception( self.name + ": connection closed." )
diff --git a/TestON/drivers/common/cli/emulator/mininethostdriver.py b/TestON/drivers/common/cli/emulator/mininethostdriver.py
index 360fd9a..7c87136 100644
--- a/TestON/drivers/common/cli/emulator/mininethostdriver.py
+++ b/TestON/drivers/common/cli/emulator/mininethostdriver.py
@@ -22,13 +22,8 @@
 
 import pexpect
 import re
-import sys
-import types
 import os
-import time
-from math import pow
 from drivers.common.cli.emulatordriver import Emulator
-from core.graph import Graph
 
 
 class MininetHostDriver( Emulator ):
@@ -82,10 +77,11 @@
                 pwd=self.pwd )
 
             if self.handle:
-                main.log.info( "Connection successful to the " +
+                main.log.info( "Connection successful to " +
                                self.user_name +
                                "@" +
                                self.ip_address )
+                self.handle.sendline( "bash -i" )
                 self.handle.sendline( "~/mininet/util/m " + self.shortName )
                 self.handle.sendline( "cd" )
                 self.handle.expect( self.hostPrompt )
diff --git a/TestON/drivers/common/cli/emulator/scapyclidriver.py b/TestON/drivers/common/cli/emulator/scapyclidriver.py
index 6a24aa2..e2d5b0b 100644
--- a/TestON/drivers/common/cli/emulator/scapyclidriver.py
+++ b/TestON/drivers/common/cli/emulator/scapyclidriver.py
@@ -27,7 +27,6 @@
 import pexpect
 import re
 import sys
-import types
 import os
 from drivers.common.cli.emulatordriver import Emulator
 
@@ -58,6 +57,20 @@
             self.home = self.options[ 'home' ] if 'home' in self.options.keys() else "~/"
             self.name = self.options[ 'name' ]
             self.ifaceName = self.options[ 'ifaceName' ] if 'ifaceName' in self.options.keys() else self.name + "-eth0"
+
+            # Parse route config
+            self.routes = []
+            routes = self.options.get( 'routes' )
+            if routes:
+                for route in routes:
+                    route = routes[ route ]
+                    iface = route.get( 'interface' )
+                    if not iface:
+                        iface = None
+                    self.routes.append( { 'network': route[ 'network' ],
+                                          'netmask': route[ 'netmask' ],
+                                          'gw': route.get( 'gw' ),
+                                          'interface': iface } )
             try:
                 if os.getenv( str( self.ip_address ) ) is not None:
                     self.ip_address = os.getenv( str( self.ip_address ) )
@@ -67,11 +80,11 @@
                                    self.ip_address )
 
             except KeyError:
-                main.log.info( "Invalid host name," +
+                main.log.info( self.name + ": Invalid host name," +
                                " connecting to local host instead" )
                 self.ip_address = 'localhost'
             except Exception as inst:
-                main.log.error( "Uncaught exception: " + str( inst ) )
+                main.log.error( self.name + ": Uncaught exception: " + str( inst ) )
 
             self.handle = super(
                 ScapyCliDriver,
@@ -82,7 +95,7 @@
                 pwd=self.pwd )
 
             if self.handle:
-                main.log.info( "Connection successful to the host " +
+                main.log.info( self.name + ": Connection successful to the host " +
                                self.user_name +
                                "@" +
                                self.ip_address )
@@ -107,6 +120,7 @@
         Called at the end of the test to stop the scapy component and
         disconnect the handle.
         """
+        main.log.debug( self.name + ": Disconnecting" )
         response = main.TRUE
         try:
             if self.handle:
@@ -120,12 +134,13 @@
             response = main.FALSE
         return response
 
-    def startScapy( self, mplsPath="" ):
+    def startScapy( self, mplsPath="", ifaceName=None ):
         """
         Start the Scapy cli
         optional:
             mplsPath - The path where the MPLS class is located
             NOTE: This can be a relative path from the user's home dir
+            ifaceName - the name of the default interface to use.
         """
         mplsLines = [ 'import imp',
                       'imp.load_source( "mplsClass", "{}mplsClass.py" )'.format( mplsPath ),
@@ -135,17 +150,35 @@
                       'bind_layers(MPLS, IP)' ]
 
         try:
+            main.log.debug( self.name + ": Starting scapy" )
             self.handle.sendline( "sudo scapy" )
             self.handle.expect( self.scapyPrompt )
             self.handle.sendline( "conf.color_theme = NoTheme()" )
             self.handle.expect( self.scapyPrompt )
+            response = self.cleanOutput( self.handle.before )
+            self.handle.sendline( "conf.fancy_prompt = False" )
+            self.handle.expect( self.scapyPrompt )
+            response = self.cleanOutput( self.handle.before )
+            self.handle.sendline( "conf.interactive = False" )
+            self.handle.expect( "interactive" )
+            self.handle.expect( self.scapyPrompt )
+            response = self.cleanOutput( self.handle.before )
+            self.handle.sendline( "" )
+            self.handle.expect( self.scapyPrompt )
+            response = self.cleanOutput( self.handle.before )
             if mplsPath:
-                main.log.info( "Adding MPLS class" )
-                main.log.info( "MPLS class path: " + mplsPath )
+                main.log.debug( self.name + ": Adding MPLS class" )
+                main.log.debug( self.name + ": MPLS class path: " + mplsPath )
                 for line in mplsLines:
-                    main.log.info( "sending line: " + line )
+                    main.log.debug( self.name + ": sending line: " + line )
                     self.handle.sendline( line )
                     self.handle.expect( self.scapyPrompt )
+                    response = self.cleanOutput( self.handle.before )
+
+            # Set interface
+            if ifaceName:
+                self.handle.sendline( 'conf.iface = "' + ifaceName + '"' )
+            self.clearBuffer()
             return main.TRUE
         except pexpect.TIMEOUT:
             main.log.exception( self.name + ": Command timed out" )
@@ -162,6 +195,7 @@
         Exit the Scapy cli
         """
         try:
+            main.log.debug( self.name + ": Stopping scapy" )
             self.handle.sendline( "exit()" )
             self.handle.expect( self.hostPrompt )
             return main.TRUE
@@ -191,6 +225,7 @@
         Returns main.TRUE or main.FALSE on error
         """
         try:
+            main.log.debug( self.name + ": Building Ethernet Frame" )
             # Set the Ethernet frame
             cmd = 'ether = Ether( '
             options = []
@@ -202,15 +237,17 @@
             cmd += ' )'
             self.handle.sendline( cmd )
             self.handle.expect( self.scapyPrompt )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( "Error in sending command: " + response )
                 return main.FALSE
             self.handle.sendline( "packet = ether" )
             self.handle.expect( self.scapyPrompt )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( "Error in sending command: " + response )
                 return main.FALSE
             return main.TRUE
         except pexpect.TIMEOUT:
@@ -249,6 +286,7 @@
         Returns main.TRUE or main.FALSE on error
         """
         try:
+            main.log.debug( self.name + ": Building IP Frame" )
             # Set the IP frame
             cmd = 'ip = IP( '
             options = []
@@ -260,15 +298,17 @@
             cmd += ' )'
             self.handle.sendline( cmd )
             self.handle.expect( self.scapyPrompt )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( "Error in sending command: " + response )
                 return main.FALSE
             self.handle.sendline( "packet = ether/ip" )
             self.handle.expect( self.scapyPrompt )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( "Error in sending command: " + response )
                 return main.FALSE
             return main.TRUE
         except pexpect.TIMEOUT:
@@ -302,6 +342,7 @@
         Returns main.TRUE or main.FALSE on error
         """
         try:
+            main.log.debug( self.name + ": Building IPv6 Frame" )
             # Set the IPv6 frame
             cmd = 'ipv6 = IPv6( '
             options = []
@@ -313,15 +354,17 @@
             cmd += ' )'
             self.handle.sendline( cmd )
             self.handle.expect( self.scapyPrompt )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( "Error in sending command: " + response )
                 return main.FALSE
             self.handle.sendline( "packet = ether/ipv6" )
             self.handle.expect( self.scapyPrompt )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( "Error in sending command: " + response )
                 return main.FALSE
             return main.TRUE
         except pexpect.TIMEOUT:
@@ -366,6 +409,7 @@
         Returns main.TRUE or main.FALSE on error
         """
         try:
+            main.log.debug( self.name + ": Building TCP" )
             # Set the TCP frame
             cmd = 'tcp = TCP( '
             options = []
@@ -375,9 +419,10 @@
             cmd += ' )'
             self.handle.sendline( cmd )
             self.handle.expect( self.scapyPrompt )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( "Error in sending command: " + response )
                 return main.FALSE
             if str( ipVersion ) is '4':
                 self.handle.sendline( "packet = ether/ip/tcp" )
@@ -388,9 +433,10 @@
                                 repr( ipVersion ) )
                 return main.FALSE
             self.handle.expect( self.scapyPrompt )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( "Error in sending command: " + response )
                 return main.FALSE
             return main.TRUE
         except pexpect.TIMEOUT:
@@ -428,6 +474,7 @@
         Returns main.TRUE or main.FALSE on error
         """
         try:
+            main.log.debug( self.name + ": Building UDP Frame" )
             # Set the UDP frame
             cmd = 'udp = UDP( '
             options = []
@@ -437,9 +484,10 @@
             cmd += ' )'
             self.handle.sendline( cmd )
             self.handle.expect( self.scapyPrompt )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( "Error in sending command: " + response )
                 return main.FALSE
             if str( ipVersion ) is '4':
                 self.handle.sendline( "packet = ether/ip/udp" )
@@ -450,9 +498,10 @@
                                 repr( ipVersion ) )
                 return main.FALSE
             self.handle.expect( self.scapyPrompt )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( "Error in sending command: " + response )
                 return main.FALSE
             return main.TRUE
         except pexpect.TIMEOUT:
@@ -490,6 +539,7 @@
         Returns main.TRUE or main.FALSE on error
         """
         try:
+            main.log.debug( self.name + ": Building SCTP Frame" )
             # Set the SCTP frame
             cmd = 'sctp = SCTP( '
             options = [ ]
@@ -499,9 +549,10 @@
             cmd += ' )'
             self.handle.sendline( cmd )
             self.handle.expect( self.scapyPrompt )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( "Error in sending command: " + response )
                 return main.FALSE
             if str( ipVersion ) is '4':
                 self.handle.sendline( "packet = ether/ip/sctp" )
@@ -512,9 +563,10 @@
                                 repr( ipVersion ) )
                 return main.FALSE
             self.handle.expect( self.scapyPrompt )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( "Error in sending command: " + response )
                 return main.FALSE
             return main.TRUE
         except pexpect.TIMEOUT:
@@ -554,6 +606,7 @@
         Returns main.TRUE or main.FALSE on error
         """
         try:
+            main.log.debug( self.name + ": Building ARP Frame" )
             # Set the ARP frame
             cmd = 'arp = ARP( '
             options = []
@@ -565,15 +618,17 @@
             cmd += ' )'
             self.handle.sendline( cmd )
             self.handle.expect( self.scapyPrompt )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( "Error in sending command: " + response )
                 return main.FALSE
             self.handle.sendline( "packet = ether/arp" )
             self.handle.expect( self.scapyPrompt )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( "Error in sending command: " + response )
                 return main.FALSE
             return main.TRUE
         except pexpect.TIMEOUT:
@@ -608,6 +663,7 @@
         Returns main.TRUE or main.FALSE on error
         """
         try:
+            main.log.debug( self.name + ": Building ICMP Frame" )
             # Set the ICMP frame
             if str( ipVersion ) is '4':
                 cmd = 'icmp = ICMP( '
@@ -626,9 +682,10 @@
             cmd += ' )'
             self.handle.sendline( cmd )
             self.handle.expect( self.scapyPrompt )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( "Error in sending command: " + response )
                 return main.FALSE
 
             if str( ipVersion ) is '4':
@@ -640,9 +697,10 @@
                                 repr( ipVersion ) )
                 return main.FALSE
             self.handle.expect( self.scapyPrompt )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( "Error in sending command: " + response )
                 return main.FALSE
             return main.TRUE
         except pexpect.TIMEOUT:
@@ -655,7 +713,26 @@
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanAndExit()
 
-    def sendPacket( self, iface=None, packet=None, timeout=1 ):
+    def clearBuffer( self, debug=False ):
+        """
+        Keep reading from buffer until its empty
+        Everything seems to be printed twice in newer versions of
+        scapy, even when turning off fancy output
+        """
+        i = 0
+        response = ''
+        while True:
+            try:
+                i += 1
+                # clear buffer
+                if debug:
+                    main.log.warn( "%s expect loop iteration" % i )
+                self.handle.expect( self.scapyPrompt, timeout=1 )
+                response += self.cleanOutput( self.handle.before, debug )
+            except pexpect.TIMEOUT:
+                return response
+
+    def sendPacket( self, iface=None, packet=None, timeout=1, debug=True ):
         """
         Send a packet with either the given scapy packet command, or use the
         packet saved in the variable 'packet'.
@@ -672,8 +749,13 @@
         Returns main.TRUE or main.FALSE on error
         """
         try:
+            main.log.debug( self.name + ": Sending Packet" )
+            if debug:
+                self.handle.sendline( "packet.summary()" )
+                self.handle.expect( self.scapyPrompt )
+            self.clearBuffer()
             # TODO: add all params, or use kwargs
-            sendCmd = 'srp( '
+            sendCmd = 'sendp( '
             if packet:
                 sendCmd += packet
             else:
@@ -681,13 +763,15 @@
             if iface:
                 sendCmd += ", iface='{}'".format( iface )
 
-            sendCmd += ', timeout=' + str( timeout ) + ')'
+            if debug:
+                sendCmd += ', return_packets=True).summary()'  # show packet(s) sent
             self.handle.sendline( sendCmd )
             self.handle.expect( self.scapyPrompt )
-            # main.log.warn( "Send packet response: {}".format( self.handle.before ) )
-            if "Traceback" in self.handle.before:
+            response = self.cleanOutput( self.handle.before )
+            main.log.debug( self.name + ": Send packet response: {}".format( response ) )
+            if "Traceback" in response:
                 # KeyError, SyntaxError, ...
-                main.log.error( "Error in sending command: " + self.handle.before )
+                main.log.error( self.name + ": Error in sending command: " + response )
                 return main.FALSE
             # TODO: Check # of packets sent?
             return main.TRUE
@@ -715,24 +799,30 @@
         Returns main.TRUE or main.FALSE on error
         """
         try:
+            main.log.info( self.name + ": Starting filter on interface %s" % ifaceName )
             # TODO: add all params, or use kwargs
             ifaceName = str( ifaceName ) if ifaceName else self.ifaceName
             # Set interface
             self.handle.sendline( 'conf.iface = "' + ifaceName + '"' )
+            self.handle.expect( ifaceName )
+            self.cleanOutput( self.handle.before + self.handle.after )
+            self.cleanOutput( self.handle.before )
             self.handle.expect( self.scapyPrompt )
-            cmd = 'pkt = sniff(count = ' + str( sniffCount ) +\
-                  ', filter = "' + str( pktFilter ) + '")'
-            main.log.info( "Filter on " + self.name + ' > ' + cmd )
+            response = self.handle.before + self.handle.after
+            self.cleanOutput( response )
+            cmd = 'pkts = sniff(count = %s, filter = "%s", prn=lambda p: p.summary() )' % ( sniffCount, pktFilter )
+            main.log.info( self.name + ": Starting filter on " + self.name + ' > ' + cmd )
             self.handle.sendline( cmd )
-            self.handle.expect( '"\)\r\n' )
+            response = self.clearBuffer()
+
             # Make sure the sniff function didn't exit due to failures
             i = self.handle.expect( [ self.scapyPrompt, pexpect.TIMEOUT ], timeout=3 )
+            response = self.cleanOutput( self.handle.before + str( self.handle.after ) )
             if i == 0:
                 # sniff exited
                 main.log.error( self.name + ": sniff function exited" )
-                main.log.error( self.name + ":     " + self.handle.before )
+                main.log.error( self.name + ":     " + response )
                 return main.FALSE
-            # TODO: parse this?
             return main.TRUE
         except pexpect.TIMEOUT:
             main.log.exception( self.name + ": Command timed out" )
@@ -746,10 +836,16 @@
 
     def checkFilter( self, timeout=10 ):
         """
-        Check that a filter returned and returns the reponse
+        Check if a filter is still running.
+        Returns:
+            main.TRUE if the filter stopped
+            main.FALSE if the filter is still running
         """
         try:
+            main.log.debug( self.name + ": Checking Filter" )
+            self.handle.sendline( "" )
             i = self.handle.expect( [ self.scapyPrompt, pexpect.TIMEOUT ], timeout=timeout )
+            response = self.cleanOutput( self.handle.before + str( self.handle.after ), debug=True )
             if i == 0:
                 return main.TRUE
             else:
@@ -766,9 +862,11 @@
         Kill a scapy filter
         """
         try:
+            main.log.debug( self.name + ": Killing scapy filter" )
             self.handle.send( "\x03" )  # Send a ctrl-c to kill the filter
             self.handle.expect( self.scapyPrompt )
-            return self.handle.before
+            output = self.cleanOutput( self.handle.before, debug=True )
+            return output
         except pexpect.TIMEOUT:
             main.log.exception( self.name + ": Command timed out" )
             return None
@@ -784,9 +882,13 @@
         Read all the packets captured by the previous filter
         """
         try:
-            self.handle.sendline( "for p in pkt: p \n")
-            self.handle.expect( "for p in pkt: p \r\n... \r\n" )
-            self.handle.expect( self.scapyPrompt )
+            main.log.debug( self.name + ": Reading Packets" )
+            main.log.debug( self.name + ": Begin clear buffer" )
+            self.clearBuffer()
+            main.log.debug( self.name + ": end clear buffer" )
+
+            self.handle.sendline( "pkts.summary()")
+            output = self.clearBuffer()
         except pexpect.TIMEOUT:
             main.log.exception( self.name + ": Command timed out" )
             return None
@@ -796,7 +898,7 @@
         except Exception:
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanAndExit()
-        return self.handle.before
+        return output
 
     def updateSelf( self, IPv6=False ):
         """
@@ -817,8 +919,9 @@
             cmd = 'get_if_hwaddr("' + str( ifaceName ) + '")'
             self.handle.sendline( cmd )
             self.handle.expect( self.scapyPrompt )
+            response = self.cleanOutput( self.handle.before )
             pattern = r'(([0-9a-f]{2}[:-]){5}([0-9a-f]{2}))'
-            match = re.search( pattern, self.handle.before )
+            match = re.search( pattern, response )
             if match:
                 return match.group()
             else:
@@ -851,11 +954,12 @@
                 cmd = 'get_if_raw_addr6("' + str( ifaceName ) + '")'
             self.handle.sendline( cmd )
             self.handle.expect( self.scapyPrompt )
+            response = self.cleanOutput( self.handle.before )
 
             pattern = r'(((2[0-5]|1[0-9]|[0-9])?[0-9]\.){3}((2[0-5]|1[0-9]|[0-9])?[0-9]))'
             if IPv6:
                 pattern = r'(\\x([0-9]|[a-f]|[A-F])([0-9]|[a-f]|[A-F])){16}'
-            match = re.search( pattern, self.handle.before )
+            match = re.search( pattern, response )
             if match:
                 # NOTE: The command will return 0.0.0.0 if the iface doesn't exist
                 if IPv6 is not True:
@@ -908,6 +1012,50 @@
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanAndExit()
 
+    def addRoute( self, network, gateway, interface=None ):
+        """
+        Add a route to the current scapy session
+        """
+        main.log.info( self.name + ": Adding route to scapy session; %s via %s out of interface %s" % ( network, gateway, interface ) )
+        if gateway is None:
+            main.log.error( self.name + ": Gateway is None, cannot set route" )
+            return main.FALSE
+        try:
+            cmdStr = 'conf.route.add( net="%s", gw="%s"' % ( network, gateway )
+            if interface:
+                cmdStr += ', dev="%s"' % interface
+            cmdStr += ')'
+            self.handle.sendline( cmdStr )
+            self.handle.expect( self.scapyPrompt )
+            response = self.cleanOutput( self.handle.before )
+            if "Traceback" in response:
+                main.log.error( self.name + ": Error in adding route to scappy session" )
+                main.log.debug( response )
+                return main.FALSE
+            return main.TRUE
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": Command timed out" )
+            return None
+        except pexpect.EOF:
+            main.log.exception( self.name + ": connection closed." )
+            main.cleanAndExit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanAndExit()
+
+    def addRoutes( self ):
+        """
+        Add any routes configured for the host
+        """
+        returnValues = []
+        for route in self.routes:
+            gw = route.get( 'gw' )
+            iface = route.get( 'interface' )
+            returnValues .append( self.addRoute( "%s/%s" % ( route.get( 'network' ), route.get( 'netmask' ) ),
+                                                 gw if gw else main.Cluster.active(0).ipAddress,
+                                                 interface=iface if iface else self.interfaces[ 0 ].get( 'name' ) ) )
+        return returnValues
+
     def getIfList( self ):
         """
         Return List of Interfaces
@@ -915,7 +1063,8 @@
         try:
             self.handle.sendline( 'get_if_list()' )
             self.handle.expect( self.scapyPrompt )
-            ifList = self.handle.before.split( '\r\n' )
+            response = self.cleanOutput( self.handle.before )
+            ifList = response.split( '\r\n' )
             ifList = ifList[ 1 ].replace( "'", "" )[ 1:-1 ].split( ', ' )
             return ifList
 
diff --git a/TestON/drivers/common/cli/hostdriver.py b/TestON/drivers/common/cli/hostdriver.py
index 7c7cd80..e14a38d 100644
--- a/TestON/drivers/common/cli/hostdriver.py
+++ b/TestON/drivers/common/cli/hostdriver.py
@@ -22,11 +22,7 @@
 
 import pexpect
 import re
-import sys
-import types
 import os
-import time
-from math import pow
 from drivers.common.cli.emulator.scapyclidriver import ScapyCliDriver
 
 class HostDriver( ScapyCliDriver ):
@@ -60,7 +56,7 @@
             self.interfaces.append( { 'ips': [ self.options[ 'ip' ] ],
                                       'isUp': True,
                                       'mac': self.options[ 'mac' ],
-                                      'name': None } )
+                                      'name': self.options.get( 'interfaceName', None ) } )
 
             try:
                 if os.getenv( str( self.ip_address ) ) is not None:
@@ -121,18 +117,18 @@
                     i = self.handle.expect( [ "closed", pexpect.TIMEOUT ] )
                     if i == 1:
                         main.log.error( self.name + ": timeout when waiting for response" )
-                        main.log.error( "response: " + str( self.handle.before ) )
+                        main.log.error( self.name + ": response: " + str( self.handle.before ) )
                 else:
                     self.handle.sendline( "" )
                     i = self.handle.expect( [ self.prompt, pexpect.TIMEOUT ], timeout=2 )
                     if i == 1:
                         main.log.warn( self.name + ": timeout when waiting for response" )
-                        main.log.warn( "response: " + str( self.handle.before ) )
+                        main.log.warn( self.name + ": response: " + str( self.handle.before ) )
                     self.handle.sendline( "exit" )
                     i = self.handle.expect( [ "closed", pexpect.TIMEOUT ], timeout=2 )
                     if i == 1:
                         main.log.warn( self.name + ": timeout when waiting for response" )
-                        main.log.warn( "response: " + str( self.handle.before ) )
+                        main.log.warn( self.name + ": response: " + str( self.handle.before ) )
                 return main.TRUE
         except TypeError:
             main.log.exception( self.name + ": Object not as expected" )
@@ -201,7 +197,7 @@
             i = self.handle.expect( [ "closed", pexpect.TIMEOUT ], timeout=2 )
             if i == 1:
                 main.log.error( self.name + ": timeout when waiting for response" )
-                main.log.error( "response: " + str( self.handle.before ) )
+                main.log.error( self.name + ": response: " + str( self.handle.before ) )
             return main.TRUE
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
@@ -212,7 +208,7 @@
             main.log.error( self.name + ":     " + self.handle.before )
             return main.FALSE
 
-    def ping( self, dst, ipv6=False, wait=3 ):
+    def ping( self, dst, ipv6=False, interface=None, wait=3 ):
         """
         Description:
             Ping from this host to another
@@ -220,10 +216,13 @@
             dst: IP address of destination host
         Optional:
             ipv6: will use ping6 command if True; otherwise use ping command
+            interface: Specify which interface to use for the ping
             wait: timeout for ping command
         """
         try:
             command = "ping6" if ipv6 else "ping"
+            if interface:
+                command += " -I %s " % interface
             command += " -c 1 -i 1 -W " + str( wait ) + " " + str( dst )
             main.log.info( self.name + ": Sending: " + command )
             self.handle.sendline( command )
@@ -233,7 +232,7 @@
                 main.log.error(
                     self.name +
                     ": timeout when waiting for response" )
-                main.log.error( "response: " + str( self.handle.before ) )
+                main.log.error( self.name + ": response: " + str( self.handle.before ) )
             self.handle.sendline( "" )
             self.handle.expect( self.prompt )
             response = self.handle.before
@@ -314,7 +313,7 @@
                 main.log.error(
                     self.name +
                     ": timeout when waiting for response" )
-                main.log.error( "response: " + str( self.handle.before ) )
+                main.log.error( self.name + ": response: " + str( self.handle.before ) )
             response = self.handle.before
             return response
         except pexpect.EOF:
@@ -337,7 +336,7 @@
                                     timeout=wait + 5 )
             if i == 1:
                 main.log.error( self.name + ": timeout when waiting for response" )
-                main.log.error( "response: " + str( self.handle.before ) )
+                main.log.error( self.name + ": response: " + str( self.handle.before ) )
             response = self.handle.before
             return response
         except pexpect.EOF:
@@ -348,7 +347,7 @@
             main.log.exception( self.name + ": uncaught exception!" )
             main.cleanAndExit()
 
-    def command( self, cmd, wait=3 ):
+    def command( self, cmd, wait=3, debug=False):
         """
         Run shell command on host and return output
         Required:
@@ -359,10 +358,12 @@
             self.handle.sendline( cmd )
             i = self.handle.expect( [ self.prompt, pexpect.TIMEOUT ],
                                     timeout=wait + 5 )
+            response = self.handle.before
+            if debug:
+                main.log.debug( response )
             if i == 1:
                 main.log.error( self.name + ": timeout when waiting for response" )
-                main.log.error( "response: " + str( self.handle.before ) )
-            response = self.handle.before
+                main.log.error( self.name + ": response: " + str( response ) )
             return response
         except pexpect.EOF:
             main.log.error( self.name + ": EOF exception found" )
diff --git a/TestON/drivers/common/cli/networkdriver.py b/TestON/drivers/common/cli/networkdriver.py
index 1cd242c..968973d 100755
--- a/TestON/drivers/common/cli/networkdriver.py
+++ b/TestON/drivers/common/cli/networkdriver.py
@@ -31,6 +31,9 @@
 import os
 import re
 import types
+import time
+import itertools
+import random
 from drivers.common.clidriver import CLI
 from core.graph import Graph
 
@@ -126,7 +129,7 @@
         try:
             for key, value in main.componentDictionary.items():
                 if hasattr( main, key ):
-                    if value[ 'type' ] in [ 'MininetSwitchDriver', 'OFDPASwitchDriver' ]:
+                    if value[ 'type' ] in [ 'MininetSwitchDriver', 'OFDPASwitchDriver', 'StratumOSSwitchDriver' ]:
                         component = getattr( main, key )
                         shortName = component.options[ 'shortName' ]
                         localName = self.name + "-" + shortName
@@ -275,7 +278,12 @@
                 continue
             if not includeStopped and not switchComponent.isup:
                 continue
-            dpid = switchComponent.dpid.replace( '0x', '' ).zfill( 16 )
+            try:
+                dpid = switchComponent.dpid
+            except AttributeError:
+                main.log.warn( "Switch has no dpid, ignore this if not an OpenFlow switch" )
+                dpid = "0x0"
+            dpid = dpid.replace( '0x', '' ).zfill( 16 )
             ports = switchComponent.ports
             swClass = 'Unknown'
             pid = None
@@ -344,7 +352,6 @@
         """
         Return MAC address of a host
         """
-        import re
         try:
             hostComponent = self.hosts[ host ]
             response = hostComponent.ifconfig()
@@ -460,8 +467,6 @@
             main.TRUE if pingall completes with no pings dropped
             otherwise main.FALSE
         """
-        import time
-        import itertools
         try:
             timeout = int( timeout )
             main.log.info( self.name + ": Checking reachabilty to the hosts using ping" )
@@ -495,7 +500,7 @@
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanAndExit()
 
-    def pingallHosts( self, hostList, wait=1 ):
+    def pingallHosts( self, hostList, ipv6=False, wait=1, useScapy=False ):
         """
             Ping all specified IPv4 hosts
 
@@ -507,8 +512,6 @@
 
             Returns main.FALSE if one or more of hosts specified
             cannot reach each other"""
-        import time
-        import itertools
         hostComponentList = []
         for hostName in hostList:
             hostComponent = self.hosts[ hostName ]
@@ -522,8 +525,49 @@
             hostPairs = itertools.permutations( list( hostComponentList ), 2 )
             for hostPair in list( hostPairs ):
                 pingResponse += hostPair[ 0 ].options[ 'shortName' ] + " -> "
-                ipDst = hostPair[ 1 ].options[ 'ip6' ] if ipv6 else hostPair[ 1 ].options[ 'ip' ]
-                pingResult = hostPair[ 0 ].ping( ipDst, wait=int( wait ) )
+                ipDst = hostPair[ 1 ].options.get( 'ip6', hostPair[ 1 ].options[ 'ip' ] ) if ipv6 else hostPair[ 1 ].options[ 'ip' ]
+                srcIface = hostPair[ 0 ].interfaces[0].get( 'name' )
+                dstIface = hostPair[ 1 ].interfaces[0].get( 'name' )
+                srcMac = hostPair[0].interfaces[0].get( 'mac' )
+                dstMac = hostPair[1].interfaces[0].get( 'mac' )
+                if useScapy:
+                    main.log.debug( "Pinging from " + str( hostPair[ 0 ].shortName ) + " to " + str( hostPair[ 1 ].shortName ) )
+                    srcIPs = hostPair[ 0 ].interfaces[0].get( 'ips' )
+                    dstIPs = hostPair[ 1 ].interfaces[0].get( 'ips' )
+                    # Use scapy to send and recieve packets
+                    hostPair[ 1 ].startScapy( ifaceName=dstIface )
+                    hostPair[ 1 ].addRoutes()
+                    hostPair[ 1 ].startFilter( ifaceName=dstIface, pktFilter="ether host %s and ip host %s" % ( srcMac, srcIPs[0] ) )
+
+                    hostPair[ 0 ].startScapy( ifaceName=srcIface )
+                    hostPair[ 0 ].addRoutes()
+                    hostPair[ 0 ].buildEther( dst=dstMac )
+                    hostPair[ 0 ].buildIP( src=srcIPs, dst=dstIPs )
+                    hostPair[ 0 ].buildICMP( )
+                    hostPair[ 0 ].sendPacket( iface=srcIface )
+
+                    waiting = not hostPair[ 1 ].checkFilter()
+                    if not waiting:
+                        pingResult = main.FALSE
+                        packets = hostPair[ 1 ].readPackets()
+                        main.log.warn( packets )
+                        for packet in packets.splitlines():
+                            main.log.debug( packet )
+                            if srcIPs[0] in packet:
+                                pingResult = main.TRUE
+                    else:
+                        main.log.warn( "Did not receive packets, killing filter" )
+                        kill = hostPair[ 1 ].killFilter()
+                        main.log.debug( kill )
+                        hostPair[ 1 ].handle.sendline( "" )
+                        hostPair[ 1 ].handle.expect( hostPair[ 1 ].scapyPrompt )
+                        main.log.debug( hostPair[ 1 ].handle.before )
+                        # One of the host to host pair is unreachable
+                        pingResult = main.FALSE
+                    hostPair[ 0 ].stopScapy()
+                    hostPair[ 1 ].stopScapy()
+                else:
+                    pingResult = hostPair[ 0 ].ping( ipDst, interface=srcIface, wait=int( wait ) )
                 if pingResult:
                     pingResponse += hostPair[ 1 ].options[ 'shortName' ]
                 else:
@@ -538,6 +582,122 @@
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanAndExit()
 
+    def pingallHostsUnidirectional( self, srcList, dstList, ipv6=False, wait=1, acceptableFailed=0, useScapy=False ):
+        """
+        Verify ping from each host in srcList to each host in dstList
+
+        acceptableFailed: max number of acceptable failed pings
+
+        Returns main.TRUE if all src hosts can reach all dst hosts
+        Returns main.FALSE if one or more of src hosts cannot reach one or more of dst hosts
+        """
+        try:
+            main.log.info( "Verifying ping from each src host to each dst host" )
+
+            srcComponentList = []
+            for hostName in srcList:
+                hostComponent = self.hosts[ hostName ]
+                if hostComponent:
+                    main.log.debug( repr( hostComponent ) )
+                    srcComponentList.append( hostComponent )
+            dstComponentList = []
+            for hostName in dstList:
+                hostComponent = self.hosts[ hostName ]
+                if hostComponent:
+                    main.log.debug( repr( hostComponent ) )
+                    dstComponentList.append( hostComponent )
+
+            isReachable = main.TRUE
+            wait = int( wait )
+            cmd = " ping" + ("6" if ipv6 else "") + " -c 1 -i 1 -W " + str( wait ) + " "
+            pingResponse = "Ping output:\n"
+            failedPingsTotal = 0
+            for srcHost in srcComponentList:
+                pingResponse += str( str( srcHost.shortName ) + " -> " )
+                for dstHost in dstComponentList:
+                    failedPings = 0
+                    dstIP = dstHost.ip
+                    assert dstIP, "Not able to get IP address of host {}".format( dstHost )
+                    for iface in srcHost.interfaces:
+                        # FIXME This only works if one iface name is configured
+                        # NOTE: We can use an IP with -I instead of an interface name as well
+                        name = iface.get( 'name' )
+                        if name:
+                            cmd += " -I %s " % name
+
+                    if useScapy:
+                        while failedPings <= acceptableFailed:
+                            main.log.debug( "Pinging from " + str( srcHost.shortName ) + " to " + str( dstHost.shortName ) )
+                            # Use scapy to send and recieve packets
+                            dstHost.startFilter()
+                            srcHost.buildEther( dst=srcHost.interfaces[0].get( 'mac') )
+                            srcHost.sendPacket()
+                            output = dstHost.checkFilter()
+                            main.log.debug( output )
+                            if output:
+                                #TODO: parse output?
+                                packets = dstHost.readPackets()
+                                for packet in packets.splitlines():
+                                    main.log.debug( packet )
+                                pingResponse += " " + str( dstHost.shortName )
+                                break
+                            else:
+                                kill = dstHost.killFilter()
+                                main.log.debug( kill )
+                                dstHost.handle.sendline( "" )
+                                dstHost.handle.expect( dstHost.scapyPrompt )
+                                main.log.debug( dstHost.handle.before )
+                                failedPings += 1
+                                time.sleep(1)
+                        if failedPings > acceptableFailed:
+                            # One of the host to host pair is unreachable
+                            pingResponse += " X"
+                            isReachable = main.FALSE
+                            failedPingsTotal += 1
+
+                    else:
+                        pingCmd = cmd + str( dstIP )
+                        while failedPings <= acceptableFailed:
+                            main.log.debug( "Pinging from " + str( srcHost.shortName ) + " to " + str( dstHost.shortName ) )
+                            self.handle.sendline( pingCmd )
+                            self.handle.expect( self.prompt, timeout=wait + 5 )
+                            response = self.handle.before
+                            if re.search( ',\s0\%\spacket\sloss', response ):
+                                pingResponse += " " + str( dstHost.shortName )
+                                break
+                            else:
+                                failedPings += 1
+                                time.sleep(1)
+                        if failedPings > acceptableFailed:
+                            # One of the host to host pair is unreachable
+                            pingResponse += " X"
+                            isReachable = main.FALSE
+                            failedPingsTotal += 1
+                pingResponse += "\n"
+            main.log.info( pingResponse + "Failed pings: " + str( failedPingsTotal ) )
+            return isReachable
+        except AssertionError:
+            main.log.exception( "" )
+            return main.FALSE
+        except pexpect.TIMEOUT:
+            main.log.exception( self.name + ": TIMEOUT exception" )
+            response = self.handle.before
+            # NOTE: Send ctrl-c to make sure command is stopped
+            self.exitFromCmd( [ "Interrupt", self.prompt ] )
+            response += self.handle.before + self.handle.after
+            self.handle.sendline( "" )
+            self.handle.expect( self.prompt )
+            response += self.handle.before + self.handle.after
+            main.log.debug( response )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":     " + self.handle.before )
+            main.cleanAndExit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanAndExit()
+
     def iperftcp( self, host1="h1", host2="h2", timeout=6 ):
         '''
         Creates an iperf TCP test between two hosts. Returns main.TRUE if test results
@@ -658,7 +818,6 @@
         Any link that has either end included in skipLinks will be excluded.
         Returns the link as a list, e.g. [ 's1', 's2' ].
         """
-        import random
         candidateLinks = []
         try:
             if not nonCut:
@@ -708,7 +867,6 @@
         Switches specified in skipSwitches will be excluded.
         Returns the name of the chosen switch.
         """
-        import random
         candidateSwitches = []
         try:
             if not nonCut:
@@ -896,9 +1054,11 @@
             for host in hostList:
                 flushCmd = ""
                 cmd = ""
-                if self.getIPAddress( host ):
+                if self.getIPAddress( host ) or hosts[host]['interfaces'][0].get( 'ips', False ) :
                     flushCmd = "sudo ip neigh flush all"
-                    cmd = "arping -c 1 -w {} {}".format( wait, dstIp )
+                    intf = hosts[host]['interfaces'][0].get( 'name' )
+                    intfStr = "-i {}".format( intf ) if intf else ""
+                    cmd = "sudo arping -c 1 -w {} {} {}".format( wait, intfStr, dstIp )
                     main.log.debug( "Sending IPv4 arping from host {}".format( host ) )
                 elif self.getIPAddress( host, proto='IPV6' ):
                     flushCmd = "sudo ip -6 neigh flush all"
diff --git a/TestON/drivers/common/cli/onosclidriver.py b/TestON/drivers/common/cli/onosclidriver.py
index 10a015d..c317fb0 100755
--- a/TestON/drivers/common/cli/onosclidriver.py
+++ b/TestON/drivers/common/cli/onosclidriver.py
@@ -442,6 +442,7 @@
             return main.TRUE
         except pexpect.TIMEOUT:
             main.log.exception( self.name + ": TIMEOUT exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
             if noExit:
                 main.cleanup()
                 return None
@@ -564,11 +565,7 @@
                 main.log.debug( self.name + ": karafEscape output" )
                 main.log.debug( self.name + ": " + repr( response ) )
             # Remove ANSI color control strings from output
-            ansiEscape = re.compile( r'((\x9b|\x1b\[)[0-?]*[ -/]*[@-~])' )
-            response = ansiEscape.sub( '', response )
-            if debug:
-                main.log.debug( self.name + ": ansiEscape output" )
-                main.log.debug( self.name + ": " + repr( response ) )
+            response = self.cleanOutput( response, debug )
 
             # Remove ANSI color control strings from output
             # NOTE: karaf is sometimes adding a single character then two
@@ -1290,7 +1287,6 @@
             main.TRUE if host is discovered on all locations provided
             main.FALSE otherwise
         """
-        import json
         locations = [ location ] if isinstance( location, str ) else location
         assert isinstance( locations, list ), "Wrong type of location: {}".format( type( location ) )
         try:
@@ -1344,7 +1340,6 @@
             main.TRUE if all hosts have specific IP address assigned;
             main.FALSE otherwise
         """
-        import json
         try:
             hosts = self.hosts()
             hosts = json.loads( hosts )
@@ -1366,6 +1361,8 @@
                         hostList.remove( hostId )
             if hostList:
                 main.log.warn( self.name + ": failed to verify IP on following hosts: " + str( hostList) )
+                # Print info for debugging
+                main.log.debug( self.name + ": hosts output: " + str( hosts ) )
                 return main.FALSE
             else:
                 return main.TRUE
@@ -3232,7 +3229,6 @@
         Return:
             topology = current ONOS topology
         """
-        import json
         try:
             # either onos:topology or 'topology' will work in CLI
             topology = json.loads( topologyOutput )
@@ -3265,7 +3261,6 @@
                  main.FALSE if the number of switches and links is incorrect,
                  and main.ERROR otherwise
         """
-        import json
         try:
             summary = self.summary()
             summary = json.loads( summary )
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index 6e4c71d..a0a8dd1 100755
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -2679,7 +2679,7 @@
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanAndExit()
 
-    def onosDiagnostics( self, onosIPs, dstDir, suffix, timeout=300 ):
+    def onosDiagnostics( self, onosIPs, dstDir, suffix, timeout=300, profile="TRELLIS_PROFILE" ):
         """
             Run onos-diagnostics with given ONOS instance IPs and save output to dstDir
             with suffix specified E.g. onos-diags-suffix.tar.gz
@@ -2691,6 +2691,8 @@
                 main.FALSE if there's an error executing the command, and main.TRUE otherwise
         """
         try:
+            self.handle.sendline( "export DIAGS_PROFILE=%s" % profile )
+            self.handle.expect( self.prompt )
             cmd = "onos-diagnostics"
             assert isinstance( onosIPs, list )
             for ip in onosIPs:
@@ -2894,3 +2896,71 @@
         except Exception:
             main.log.exception( self.name + ": Uncaught exception!" )
             main.cleanAndExit()
+
+    def onosFetchApp( self, url, dstPath=None ):
+        """
+        Fetch an external onos app
+
+        Required:
+        url - url for where to download the app
+        dstPath - where the file will be saved
+
+        Returns main.TRUE on successfully fetching file, and main.FALSE if
+        there is an error.
+        """
+        try:
+            cmd = "wget -q --backups=1 "
+            if dstPath:
+                cmd += "-P %s " % ( dstPath )
+            cmd += str( url )
+            main.log.info( "Sending: " + cmd )
+            main.ONOSbench.handle.sendline( cmd )
+            main.ONOSbench.handle.expect( self.prompt )
+            output = self.handle.before
+            main.log.debug( output )
+            if "Error" in output or "No such file or directory" in output:
+                main.log.error( self.name + ":    " + output + self.handle.after )
+                return main.FALSE
+            return main.TRUE
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanAndExit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanAndExit()
+
+    def onosApp( self, onosIP, option, fileName, filePath='~/onos/'):
+        """
+        Wrapper for onos-app script
+
+        Required:
+        - onosIP - The ip address of the onos instance
+        - option - What command are we doing?
+            [ list|install|install!|reinstall|reinstall!|activate|deactivate|uninstall ]
+        - fileName - The name of the app file
+        Optional Arguments:
+        - filePath - The location of the file
+
+        Returns main.TRUE on successfully executing the command, and main.FALSE if
+        there is an error.
+        """
+        # FIXME: Not all options may work, more testing is required, only tested with install(!)
+        try:
+            cmd = "onos-app %s %s %s/%s" % ( onosIP, option, filePath, fileName )
+            main.log.info( "Sending: " + cmd )
+            main.ONOSbench.handle.sendline( cmd )
+            main.ONOSbench.handle.expect( self.prompt )
+            handle = self.handle.before
+            main.log.debug( handle )
+            if "Error" in handle or "usage: " in handle or "curl: " in handle:
+                main.log.error( self.name + ":    " + handle + self.handle.after )
+                return main.FALSE
+            return main.TRUE
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":    " + self.handle.before )
+            main.cleanAndExit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanAndExit()
diff --git a/TestON/drivers/common/cli/stratumosswitchdriver.py b/TestON/drivers/common/cli/stratumosswitchdriver.py
new file mode 100644
index 0000000..79f1d89
--- /dev/null
+++ b/TestON/drivers/common/cli/stratumosswitchdriver.py
@@ -0,0 +1,294 @@
+#!/usr/bin/env python
+"""
+Copyright 2020 Open Networking Foundation (ONF)
+
+Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
+the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
+or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
+
+TestON is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+( at your option ) any later version.
+
+TestON is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with TestON.  If not, see <http://www.gnu.org/licenses/>.
+"""
+
+import pexpect
+import types
+import os
+from drivers.common.clidriver import CLI
+
+class StratumOSSwitchDriver( CLI ):
+
+    def __init__( self ):
+        """
+        Initialize client
+        """
+        super( CLI, self ).__init__()
+        self.name = None
+        self.shortName = None
+        self.handle = None
+        self.prompt = "~(/TestON)?#"
+        self.dockerPrompt = "/run/stratum#"
+
+        self.home = "/root"
+        # Local home for functions using scp
+        self.tempDirectory = "/tmp/"
+        self.ports = []
+        self.isup = True
+
+    def connect( self, **connectargs ):
+        """
+        Creates ssh handle for cli.
+        """
+        try:
+            # Parse keys in xml object
+            for key in connectargs:
+                vars( self )[ key ] = connectargs[ key ]
+            # Get the name
+            self.name = self.options[ 'name' ]
+            self.shortName = self.options[ 'shortName' ]
+            # Parse the IP address
+            try:
+                if os.getenv( str( self.ip_address ) ) is not None:
+                    self.ip_address = os.getenv( str( self.ip_address ) )
+                # Otherwise is an ip address
+                else:
+                    main.log.info( self.name + ": Trying to connect to " + self.ip_address )
+            # Error handling
+            except KeyError:
+                main.log.info( "Invalid host name," + " connecting to local host instead" )
+                self.ip_address = 'localhost'
+            except Exception as inst:
+                main.log.error( "Uncaught exception: " + str( inst ) )
+            self.handle = super( StratumOSSwitchDriver, self ).connect(
+                user_name=self.user_name,
+                ip_address=self.ip_address,
+                port=None,
+                pwd=self.pwd)
+            # Successful connection
+            if self.handle:
+                main.log.info( "Connection successful to the host " + self.user_name + "@" + self.ip_address )
+                self.handle.sendline( "" )
+                self.handle.expect( self.prompt )
+                return main.TRUE
+            # Connection failed
+            else:
+                main.log.error( "Connection failed to the host " + self.user_name + "@" + self.ip_address )
+                main.log.error( "Failed to connect to the Stratum Switch" )
+                return main.FALSE
+        # Error handling
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":     " + self.handle.before )
+            main.cleanup()
+            main.exit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
+    def disconnect( self ):
+        """
+        Called when Test is complete to disconnect the component handle.
+        """
+        response = main.TRUE
+        try:
+            if self.handle:
+                # Stop the agent
+                self.stopSwitchAgent()
+                main.log.debug( self.name + ": Disconnected" )
+                # Disconnect from the device
+                self.handle.sendline( "" )
+                self.handle.expect( self.prompt )
+                self.handle.sendline( "exit" )
+                self.handle.expect( "closed" )
+        # Errors handling
+        except pexpect.TIMEOUT:
+            main.log.error( self.name + ": pexpect.TIMEOUT found" )
+            main.log.debug( self.handle.before )
+            return main.FALSE
+        except TypeError:
+            main.log.exception( self.name + ": Object not as expected" )
+            response = main.FALSE
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":     " + self.handle.before )
+        except ValueError:
+            main.log.exception( "Exception in disconnect of " + self.name )
+            response = main.TRUE
+        except Exception:
+            main.log.exception( self.name + ": Connection failed to the host" )
+            response = main.FALSE
+            return response
+
+    def assignSwController( self, ip, updateConf=True, **kwargs ):
+        """
+        Description:
+            Edit the config file for the switch and upload it to the onos
+            controller to connect the switch and controller
+
+            NOTE that this function is available on all switch drivers,
+            and the name is a hold over from ovs switches.
+            kwargs contains any arguments for other types of switches
+        Required:
+            ip - Ip addresses of controllers. This can be a list or a string.
+            updateConf - whether to pull and update configurations and scripts
+        Return:
+            Returns main.TRUE if the switch is correctly assigned to controllers,
+            otherwise it will return main.FALSE or an appropriate exception(s)
+        """
+        assignResult = main.TRUE
+        onosIp = ""
+        # Parses the controller option
+        # We only need one onos ip
+        try:
+            if isinstance( ip, types.StringType ):
+                onosIp = str( ip )
+            elif isinstance( ip, types.ListType ):
+                onosIp = ip[ 0 ]
+            else:
+                main.log.error( self.name + ": Invalid controller ip address" )
+                return main.FALSE
+            if updateConf:
+                self.setupContainer()
+                main.ONOSbench.onosNetCfg( onosIp, self.options[ 'onosConfigPath' ], self.options[ 'onosConfigFile' ] )
+
+            assignResult = self.startSwitchAgent()
+            if not assignResult:
+                self.isup = False
+            else:
+                self.isup = True
+            # Done return true
+            return assignResult
+        # Errors handling
+        except pexpect.TIMEOUT:
+            main.log.error( self.name + ": pexpect.TIMEOUT found" )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":     " + self.handle.before )
+            main.cleanAndExit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanAndExit()
+
+    def setupContainer( self ):
+        """
+        Prepare for the container to be run. Includes pulling scripts
+        and modifying them
+        """
+        try:
+            #TODO Remove hardcoding
+            main.log.info( "Creating working directory" )
+            self.handle.sendline( "mkdir TestON" )
+            self.handle.expect( self.prompt )
+            self.handle.sendline( "cd TestON" )
+            self.handle.expect( self.prompt )
+
+            main.log.info( "Getting start container script" )
+            # TODO: Parameterize this
+            self.handle.sendline( "wget --backups=1 https://raw.githubusercontent.com/stratum/stratum/master/stratum/hal/bin/barefoot/docker/start-stratum-container.sh" )
+            self.handle.expect( self.prompt )
+            main.log.info( "Modify start container script" )
+            self.handle.sendline( "sed -i '/--privileged/a \    --name stratum \\\\' start-stratum-container.sh" )
+            self.handle.expect( self.prompt )
+            #self.handle.sendline( "sed -i '/LOG_DIR:\/var\/log\/stratum/a \    --entrypoint /bin/bash \\\\' start-stratum-container.sh" )
+            #self.handle.expect( self.prompt )
+            # TODO: Add docker pull command to the start-stratum-container.sh script
+
+            main.log.info( "Getting chassis config" )
+            # TODO: Parameterize this
+            self.handle.sendline( "wget --backups=1 https://raw.githubusercontent.com/stratum/stratum/master/stratum/hal/config/x86-64-accton-wedge100bf-32x-r0/chassis_config.pb.txt" )
+            self.handle.expect( self.prompt )
+            main.log.info( "Modify chassis config" )
+            # TODO: Parameterize this
+            self.handle.sendline( "sed -i '$!N;s/\(port: [5|6]\\n\  speed_bps: \)\([0-9]*\)/\\1 40000000000/;P;D' chassis_config.pb.txt" )
+            self.handle.expect( self.prompt )
+            self.handle.sendline( "export CHASSIS_CONFIG=~/TestON/chassis_config.pb.txt" )
+            self.handle.expect( self.prompt )
+            self.handle.sendline( "chmod +x start-stratum-container.sh" )
+            self.handle.expect( self.prompt )
+        except pexpect.TIMEOUT:
+            main.log.error( self.name + ": pexpect.TIMEOUT found" )
+            main.log.debug( self.handle.before )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":     " + self.handle.before )
+            main.cleanAndExit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanAndExit()
+
+    def startSwitchAgent( self ):
+        """
+        Start the stratum agent on the device
+        """
+        try:
+            main.log.info( "Starting switch agent" )
+            self.handle.sendline( "./start-stratum-container.sh --bf-sim" )
+            self.handle.expect( "Chassis config pushed successfully." )
+            return main.TRUE
+        except pexpect.TIMEOUT:
+            main.log.error( self.name + ": pexpect.TIMEOUT found" )
+            main.log.debug( self.handle.before )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":     " + self.handle.before )
+            main.cleanAndExit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanAndExit()
+
+    def stopSwitchAgent( self ):
+        """
+        Stop the strratum agent on the device
+        """
+        try:
+            main.log.info( self.name + ": stopping Stratum Switch agent" )
+            while True:
+                self.handle.sendline( "" )
+                i = self.handle.expect( [ self.prompt, self.dockerPrompt, pexpect.TIMEOUT, "Aborted at" ] )
+                if i == 2:
+                    self.handle.send( "\x03" )  # ctrl-c to close switch agent
+                    self.handle.sendline( "" )
+                elif i == 1:
+                    self.handle.sendline( "exit" )  # exit docker
+                    self.handle.expect( self.prompt )
+                elif i == 0:
+                    self.handle.sendline( "docker stop stratum" )  # Make sure the container is stopped
+                    self.handle.expect( self.prompt )
+                    main.log.debug( self.name + ": Stratum Switch agent stopped" )
+                    return
+                elif i == 3:
+                    main.log.error( "Stratum agent aborted" )
+                    # TODO: Find and save any extra logs
+                    output = self.handle.before + self.handle.after
+                    self.handle.sendline( "" )
+                    self.handle.expect( self.prompt )
+                    output += self.handle.before + self.handle.after
+                    main.log.debug( output )
+                    main.cleanAndExit()
+        except pexpect.TIMEOUT:
+            main.log.error( self.name + ": pexpect.TIMEOUT found" )
+            main.log.debug( self.handle.before )
+            return main.FALSE
+        except pexpect.EOF:
+            main.log.error( self.name + ": EOF exception found" )
+            main.log.error( self.name + ":     " + self.handle.before )
+            main.cleanAndExit()
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanAndExit()
diff --git a/TestON/drivers/common/clidriver.py b/TestON/drivers/common/clidriver.py
index 25986b3..2db3914 100644
--- a/TestON/drivers/common/clidriver.py
+++ b/TestON/drivers/common/clidriver.py
@@ -515,6 +515,10 @@
         except AssertionError:
             main.log.error( self.name + ": Could not execute command: " + output )
             return False
+        except ValueError as e:
+            main.log.error( self.name + ": Error parsing output: " + output )
+            main.log.error( e )
+            return False
         except pexpect.TIMEOUT:
             main.log.exception( self.name + ": TIMEOUT exception found" )
             main.log.error( self.name + ":    " + self.handle.before )
@@ -589,3 +593,14 @@
         except Exception:
             main.log.exception( self.name + ": Uncaught exception!" )
             return main.FALSE
+
+    def cleanOutput( self, output, debug=False ):
+        """
+        Clean ANSI characters from output
+        """
+        ansiEscape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
+        cleaned = ansiEscape.sub( '', output )
+        if debug:
+            main.log.debug( self.name + ": cleanOutput:" )
+            main.log.debug( self.name + ": " + repr( cleaned ) )
+        return cleaned
diff --git a/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.params b/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.params
index 97d83a1..1d44485 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.params
+++ b/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.params
@@ -20,6 +20,7 @@
         <stratumRoot>~/stratum</stratumRoot>
         <topology>trellis_fabric.py</topology>
         <lib>routinglib.py,trellislib.py</lib>
+        <conf>bgpdbgp1.conf,bgpdbgp2.conf,bgpdr1.conf,bgpdr2.conf,dhcpd6.conf,dhcpd.conf,zebradbgp1.conf,zebradbgp2.conf</conf>
         <trellisOar>/home/sdn/segmentrouting-oar-3.0.0-SNAPSHOT.oar</trellisOar>
     </DEPENDENCY>
 
@@ -28,6 +29,21 @@
         <cellApps>drivers,openflow,fpm,netcfghostprovider,drivers.bmv2,pipelines.fabric</cellApps>
     </ENV>
 
+    <ONOS_Configuration>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+    </ONOS_Logging>
+
     <GIT>
         <pull>False</pull>
         <branch>master</branch>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.params.stratum b/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.params.stratum
index e1e7395..f530cf9 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.params.stratum
+++ b/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.params.stratum
@@ -17,14 +17,17 @@
         <useCommonTopo>True</useCommonTopo>
         <useBmv2>True</useBmv2>
         <bmv2SwitchType>stratum</bmv2SwitchType>
+        <switchPrefix>bmv2</switchPrefix>
         <stratumRoot>~/stratum</stratumRoot>
         <topology>trellis_fabric.py</topology>
         <lib>routinglib.py,trellislib.py</lib>
+        <conf>bgpdbgp1.conf,bgpdbgp2.conf,bgpdr1.conf,bgpdr2.conf,dhcpd6.conf,dhcpd.conf,zebradbgp1.conf,zebradbgp2.conf</conf>
     </DEPENDENCY>
 
     <MN_DOCKER>
-        <args>--privileged --net host --rm -v topo:/topo -v ~/mininet/custom:/root/mininet/custom -v /var/run/openvswitch/:/var/run/openvswitch/ -v /tmp/mn-stratum:/tmp --hostname mn-stratum -v /etc/network/interfaces:/etc/network/interfaces -it -d</args>
+        <args>--privileged --net host --rm -v topo:/topo -v ~/mininet/custom:/home/root/mininet/custom -v /var/run/openvswitch/:/var/run/openvswitch/ -v /tmp/mn-stratum:/tmp -v /tmp/mn_conf/:/home/root --hostname mn-stratum -v /etc/network/interfaces:/etc/network/interfaces -it -d</args>
         <name>trellis_mininet</name>
+        <home>/home/root/</home>
     </MN_DOCKER>
 
     <ENV>
@@ -32,6 +35,34 @@
         <cellApps>drivers,segmentrouting,openflow,fpm,netcfghostprovider,drivers.bmv2,pipelines.fabric</cellApps>
     </ENV>
 
+    <ONOS_Configuration>
+        <org.onosproject.grpc.ctl.GrpcChannelControllerImpl>
+            <enableMessageLog>true</enableMessageLog>
+        </org.onosproject.grpc.ctl.GrpcChannelControllerImpl>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+        <org.onosproject.p4runtime>DEBUG</org.onosproject.p4runtime>
+        <org.onosproject.protocols.p4runtime>DEBUG</org.onosproject.protocols.p4runtime>
+        <org.onosproject.drivers.p4runtime>DEBUG</org.onosproject.drivers.p4runtime>
+        <org.onosproject.protocols.grpc>DEBUG</org.onosproject.protocols.grpc>
+        <org.onosproject.protocols.gnmi>DEBUG</org.onosproject.protocols.gnmi>
+        <org.onosproject.protocols.gnoi>DEBUG</org.onosproject.protocols.gnoi>
+        <org.onosproject.drivers.gnoi>DEBUG</org.onosproject.drivers.gnoi>
+        <org.onosproject.drivers.gmni>DEBUG</org.onosproject.drivers.gmni>
+        <org.onosproject.drivers.stratum>DEBUG</org.onosproject.drivers.stratum>
+        <org.onosproject.bmv2>DEBUG</org.onosproject.bmv2>
+    </ONOS_Logging>
+
     <GIT>
         <pull>False</pull>
         <branch>master</branch>
@@ -50,6 +81,11 @@
         <startup>10</startup>
     </SLEEP>
 
+    <TOPO>
+        <switchNum>1</switchNum>
+        <linkNum>0</linkNum>
+    </TOPO>
+
     <ALARM>
         <minPassPercent>100</minPassPercent>
     </ALARM>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.params.tofino b/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.params.tofino
new file mode 100644
index 0000000..c495160
--- /dev/null
+++ b/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.params.tofino
@@ -0,0 +1,97 @@
+<PARAMS>
+    <testcases>1</testcases>
+
+    <GRAPH>
+        <nodeCluster>Fabric</nodeCluster>
+        <builds>20</builds>
+    </GRAPH>
+
+    <SCALE>
+        <size>3</size>
+        <max>3</max>
+    </SCALE>
+
+    <DEPENDENCY>
+        <useCommonConf>False</useCommonConf>
+        <useCommonTopo>True</useCommonTopo>
+        <useBmv2>True</useBmv2>
+        <bmv2SwitchType>stratum</bmv2SwitchType>
+        <switchPrefix>tofino</switchPrefix>
+        <stratumRoot>~/stratum</stratumRoot>
+        <topology>trellis_fabric.py</topology>
+        <lib>routinglib.py,trellislib.py</lib>
+    </DEPENDENCY>
+
+    <jsonFileSuffix>.hw</jsonFileSuffix>
+
+    <MN_DOCKER>
+        <args>--privileged --net host --rm -v topo:/topo -v ~/mininet/custom:/home/root/mininet/custom -v /var/run/openvswitch/:/var/run/openvswitch/ -v /tmp/mn-stratum:/tmp -v /tmp/mn_conf/:/home/root --hostname mn-stratum -v /etc/network/interfaces:/etc/network/interfaces -it -d</args>
+        <name>trellis_mininet</name>
+        <home>/home/root/</home>
+    </MN_DOCKER>
+
+    <ENV>
+        <cellName>productionCell</cellName>
+        <cellApps>drivers,segmentrouting,openflow,fpm,netcfghostprovider,drivers.bmv2,pipelines.fabric,drivers.barefoot</cellApps>
+    </ENV>
+
+    <EXTERNAL_APPS>
+        <fabric-tofino>https://oss.sonatype.org/content/groups/public/org/opencord/fabric-tofino/1.1.0/fabric-tofino-1.1.0.oar</fabric-tofino>
+    </EXTERNAL_APPS>
+
+    <ONOS_Configuration>
+        <org.onosproject.grpc.ctl.GrpcChannelControllerImpl>
+            <enableMessageLog>true</enableMessageLog>
+        </org.onosproject.grpc.ctl.GrpcChannelControllerImpl>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+        <org.onosproject.p4runtime>DEBUG</org.onosproject.p4runtime>
+        <org.onosproject.protocols.p4runtime>DEBUG</org.onosproject.protocols.p4runtime>
+        <org.onosproject.drivers.p4runtime>DEBUG</org.onosproject.drivers.p4runtime>
+        <org.onosproject.protocols.grpc>DEBUG</org.onosproject.protocols.grpc>
+        <org.onosproject.protocols.gnmi>DEBUG</org.onosproject.protocols.gnmi>
+        <org.onosproject.protocols.gnoi>DEBUG</org.onosproject.protocols.gnoi>
+        <org.onosproject.drivers.gnoi>DEBUG</org.onosproject.drivers.gnoi>
+        <org.onosproject.drivers.gmni>DEBUG</org.onosproject.drivers.gmni>
+        <org.onosproject.drivers.barefoot>DEBUG</org.onosproject.drivers.barefoot>
+        <org.opencord.fabric.tofino>DEBUG</org.opencord.fabric.tofino>
+        <org.onosproject.bmv2>DEBUG</org.onosproject.bmv2>
+    </ONOS_Logging>
+
+    <GIT>
+        <pull>False</pull>
+        <branch>master</branch>
+    </GIT>
+
+    <CTRL>
+        <port>6653</port>
+    </CTRL>
+
+    <timers>
+        <LinkDiscovery>12</LinkDiscovery>
+        <SwitchDiscovery>12</SwitchDiscovery>
+    </timers>
+
+    <SLEEP>
+        <startup>10</startup>
+    </SLEEP>
+
+    <TOPO>
+        <switchNum>1</switchNum>
+        <linkNum>0</linkNum>
+    </TOPO>
+
+    <ALARM>
+        <minPassPercent>100</minPassPercent>
+    </ALARM>
+</PARAMS>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.topo.0x1.physical b/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.topo.0x1.physical
new file mode 100644
index 0000000..2e2fb6f
--- /dev/null
+++ b/TestON/tests/USECASE/SegmentRouting/SRBridging/SRBridging.topo.0x1.physical
@@ -0,0 +1,102 @@
+<TOPOLOGY>
+    <COMPONENT>
+        <ONOScell>
+            <host>localhost</host>  # ONOS "bench" machine
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>OnosClusterDriver</type>
+            <connect_order>1</connect_order>
+            <home></home>   # defines where onos home is on the build machine. Defaults to "~/onos/" if empty.
+            <COMPONENTS>
+                <cluster_name></cluster_name>  # Used as a prefix for cluster components. Defaults to 'ONOS'
+                <diff_clihost></diff_clihost> # if it has different host other than localhost for CLI. True or empty. OC# will be used if True.
+                <karaf_username></karaf_username>
+                <karaf_password></karaf_password>
+                <web_user></web_user>
+                <web_pass></web_pass>
+                <rest_port></rest_port>
+                <prompt></prompt>  # TODO: we technically need a few of these, one per component
+                <onos_home></onos_home>  # defines where onos home is on the target cell machine. Defaults to entry in "home" if empty.
+                <nodes>3</nodes>  # number of nodes in the cluster
+            </COMPONENTS>
+        </ONOScell>
+
+        <SwitchLeaf1>
+            <host>10.128.13.232</host>
+            <user>root</user>
+            <password>onl</password>
+            <type>StratumOSSwitchDriver</type>
+            <connect_order>2</connect_order>
+            <COMPONENTS>
+                <shortName>leaf1</shortName>
+                <port1>1</port1>
+                <link1>Host1</link1>
+                <port2>2</port2>
+                <link2>Host2</link2>
+                <onosConfigPath>~/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/</onosConfigPath>
+                <onosConfigFile>tofino-onos-netcfg.json</onosConfigFile>
+            </COMPONENTS>
+        </SwitchLeaf1>
+
+        <Host1>
+            <host>OCN</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>HostDriver</type>
+            <connect_order>6</connect_order>
+            <COMPONENTS>
+                <mac>3c:fd:fe:a8:ea:31</mac>
+                <inband>false</inband>
+                <ip>10.0.2.1</ip>
+                <shortName>h1</shortName>
+                <port1>0</port1>
+                <link1>SwitchLeaf1</link1>
+                <interfaceName>ens6f1</interfaceName>
+                <routes>
+                    <route1>
+                        <network>10.0.2.0</network>
+                        <netmask>24</netmask>
+                        <gw></gw>
+                        <interface></interface>
+                    </route1>
+                </routes>
+            </COMPONENTS>
+        </Host1>
+
+        <Host2>
+            <host>OCN</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>HostDriver</type>
+            <connect_order>7</connect_order>
+            <COMPONENTS>
+                <mac>3c:fd:fe:a8:ea:30</mac>
+                <inband>false</inband>
+                <ip>10.0.2.2</ip>
+                <shortName>h2</shortName>
+                <port1>0</port1>
+                <link1>SwitchLeaf1</link1>
+                <interfaceName>ens6f0</interfaceName>
+                <routes>
+                    <route1>
+                        <network>10.0.2.0</network>
+                        <netmask>24</netmask>
+                        <gw></gw>
+                        <interface></interface>
+                    </route1>
+                </routes>
+            </COMPONENTS>
+        </Host2>
+
+        <NetworkBench>
+            <host>OCN</host>
+            <user>sdn</user>
+            <password>rocks</password>
+            <type>NetworkDriver</type>
+            <connect_order>10</connect_order>
+            <COMPONENTS>
+            </COMPONENTS>
+        </NetworkBench>
+
+    </COMPONENT>
+</TOPOLOGY>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/SRBridgingTest.py b/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/SRBridgingTest.py
index 3368950..984ba6b 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/SRBridgingTest.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/SRBridgingTest.py
@@ -36,7 +36,9 @@
         # topo[ '2x3' ] = ( 2, 3, True, '2x3 leaf-spine topology with dual ToR and single ToR', 28 )
         self.topo[ '2x4' ] = ( 2, 4, True, '2x4 dual-homed leaf-spine topology', 53, 53 )
         self.switchNames = {}
+        self.switchNames[ '0x1' ] = [ "leaf1" ]
         self.switchNames[ '2x2' ] = [ "leaf1", "leaf2", "spine101", "spine102" ]
+        main.switchType = "ovs"
 
     def runTest( self, main, test_idx, topology, onosNodes, description, vlan = [] ):
         skipPackage = False
@@ -48,44 +50,27 @@
         if not init and onosNodes == main.Cluster.numCtrls:
             skipPackage = True
 
-        main.case( '%s, with %s and %d ONOS instance%s' %
-                   ( description, self.topo[ topology ][ 3 ], onosNodes, 's' if onosNodes > 1 else '' ) )
+        main.case( '%s, with %s, %s switches and %d ONOS instance%s' %
+                   ( description, self.topo[ topology ][ 3 ], main.switchType, onosNodes, 's' if onosNodes > 1 else '' ) )
 
         main.cfgName = 'CASE%01d%01d' % ( test_idx / 10, ( ( test_idx - 1 ) % 10 ) % 4 + 1 )
         main.Cluster.setRunningNode( onosNodes )
         run.installOnos( main, skipPackage=skipPackage, cliSleep=5 )
         if main.useBmv2:
+            switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
             # Translate configuration file from OVS-OFDPA to BMv2 driver
-            translator.ofdpaToBmv2( main )
+            translator.bmv2ToOfdpa( main ) # Try to cleanup if switching between switch types
+            translator.ofdpaToBmv2( main, switchPrefix=switchPrefix )
         else:
             translator.bmv2ToOfdpa( main )
-        run.loadJson( main )
+        suf = main.params.get( 'jsonFileSuffix', None)
+        if suf:
+            run.loadJson( main, suffix=suf )
+        else:
+            run.loadJson( main )
         run.loadChart( main )
         if hasattr( main, 'Mininet1' ):
-            if 'MN_DOCKER' in main.params and main.params['MN_DOCKER']['args']:
-                main.log.info( "Creating Mininet Docker" )
-                main.Mininet1.dockerPrompt = '#'
-                # Start docker container
-                handle = main.Mininet1.handle
-                handle.sendline( "docker run %s %s" % ( main.params[ 'MN_DOCKER' ][ 'args' ], main.params[ 'MN_DOCKER' ][ 'name' ] ) )
-                handle.expect( main.Mininet1.bashPrompt )
-                output = handle.before + handle.after
-                main.log.debug( repr(output) )
-                startStr = main.params[ 'MN_DOCKER' ][ 'name' ]
-                endStr = main.Mininet1.user_name
-                start = output.find( startStr ) + len( startStr )
-                end = output.find( endStr )
-                containerId = output[start:end].strip()
-                main.log.debug( repr( containerId ) )
-
-                handle = main.Mininet1.handle
-                handle.sendline( "docker attach %s " % containerId )  # Strip?
-                handle.expect( main.Mininet1.dockerPrompt )
-                main.log.debug( handle.before + handle.after )
-                # We should be good to go
-                main.Mininet1.prompt = main.Mininet1.dockerPrompt
-                main.Mininet1.sudoRequired = False
-
+            run.mnDockerSetup( main )  # optionally create and setup docker image
 
             # Run the test with Mininet
             mininet_args = ' --spine=%d --leaf=%d' % ( self.topo[ topology ][ 0 ], self.topo[ topology ][ 1 ] )
@@ -94,27 +79,14 @@
             if len( vlan ) > 0 :
                 mininet_args += ' --vlan=%s' % ( ','.join( ['%d' % vlanId for vlanId in vlan ] ) )
             if main.useBmv2:
-                switchType = main.params[ 'DEPENDENCY' ].get( 'bmv2SwitchType', 'stratum' )
-                mininet_args += ' --switch %s' % switchType
-                main.log.info( "Using %s switch" % switchType )
+                mininet_args += ' --switch %s' % main.switchType
+                main.log.info( "Using %s switch" % main.switchType )
 
             run.startMininet( main, 'trellis_fabric.py', args=mininet_args )
 
-            if main.useBmv2:
-                filename = "onos-netcfg.json"
-                for switch in main.Mininet1.getSwitches(switchRegex=r"(StratumBmv2Switch)|(Bmv2Switch)").keys():
-                    path = "/tmp/mn-stratum/%s/" % switch
-                    main.ONOSbench1.handle.sendline( "sudo sed -i 's/localhost/%s/g' %s%s" % ( main.Mininet1.ip_address, path, filename ) )
-                    main.ONOSbench1.handle.expect( main.ONOSbench1.prompt )
-                    main.log.debug( main.ONOSbench1.handle.before + main.ONOSbench1.handle.after )
-                    main.ONOSbench1.handle.sendline( "sudo sed -i 's/device:%s/device:bmv2:%s/g' %s%s" % ( switch, switch, path, filename ) )
-                    main.ONOSbench1.handle.expect( main.ONOSbench1.prompt )
-                    main.log.debug( main.ONOSbench1.handle.before + main.ONOSbench1.handle.after )
-                    main.ONOSbench1.onosNetCfg( main.ONOSserver1.ip_address, path, filename )
-
         else:
             # Run the test with physical devices
-            run.connectToPhysicalNetwork( main, self.switchNames[ topology ] )
+            run.connectToPhysicalNetwork( main )
 
         run.checkFlows( main, minFlowCount=self.topo[ topology ][ 5 if main.useBmv2 else 4 ] * self.topo[ topology ][ 1 ], sleep=5 )
         if main.useBmv2:
@@ -126,22 +98,3 @@
         run.pingAll( main )
 
         run.cleanup( main )
-        if 'MN_DOCKER' in main.params and main.params['MN_DOCKER']['args']:
-                main.log.info( "Deleting Mininet Docker" )
-
-                # Detach from container
-                handle = main.Mininet1.handle
-                try:
-                    handle.sendline( "exit" )  # ctrl-p ctrk-q  to detach from container
-                    import time
-                    time.sleep(5)
-                    handle.expect( main.Mininet1.dockerPrompt )
-                    main.log.debug( handle.before + handle.after )
-                    main.Mininet1.prompt = main.Mininet1.bashPrompt
-                    handle.expect( main.Mininet1.prompt )
-                    main.log.debug( handle.before + handle.after )
-                    main.Mininet1.sudoRequired = True
-                except Exception as e:
-                    main.log.error( e )
-
-                # We should be good to go
diff --git a/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/CASE01.json.hw b/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/CASE01.json.hw
new file mode 100644
index 0000000..38dbc9a
--- /dev/null
+++ b/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/CASE01.json.hw
@@ -0,0 +1,35 @@
+{
+    "ports":{
+        "device:tofino:leaf1/168":{
+            "interfaces":[
+                {
+                    "ips":[
+                        "10.0.2.254/24"
+                    ],
+                    "vlan-untagged":10
+                }
+            ]
+        },
+        "device:tofino:leaf1/160":{
+            "interfaces":[
+                {
+                    "ips":[
+                        "10.0.2.254/24"
+                    ],
+                    "vlan-untagged":10
+                }
+            ]
+        }
+    },
+    "devices":{
+        "device:tofino:leaf1":{
+            "segmentrouting":{
+                "isEdgeRouter":true,
+                "routerMac":"00:90:fb:64:cc:9e",
+                "ipv4NodeSid":1,
+                "ipv4Loopback":"10.128.13.232",
+                "adjacencySids":[]
+            }
+        }
+    }
+}
diff --git a/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/tofino-onos-netcfg.json b/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/tofino-onos-netcfg.json
new file mode 100644
index 0000000..5cc17ed
--- /dev/null
+++ b/TestON/tests/USECASE/SegmentRouting/SRBridging/dependencies/json/tofino-onos-netcfg.json
@@ -0,0 +1,12 @@
+{
+  "devices": {
+    "device:tofino:leaf1": {
+      "basic": {
+        "name": "leaf1",
+        "managementAddress": "grpc://10.128.13.232:28000?device_id=1",
+        "driver": "stratum-tofino",
+        "pipeconf": "org.opencord.fabric.tofino.montara_sde_9_0_0"
+      }
+    }
+  }
+}
diff --git a/TestON/tests/USECASE/SegmentRouting/SRClusterRestart/SRClusterRestart.params b/TestON/tests/USECASE/SegmentRouting/SRClusterRestart/SRClusterRestart.params
index a991004..85c0e30 100755
--- a/TestON/tests/USECASE/SegmentRouting/SRClusterRestart/SRClusterRestart.params
+++ b/TestON/tests/USECASE/SegmentRouting/SRClusterRestart/SRClusterRestart.params
@@ -28,6 +28,21 @@
         <branch>master</branch>
     </GIT>
 
+    <ONOS_Configuration>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+    </ONOS_Logging>
+
     <CTRL>
         <port>6653</port>
     </CTRL>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRDhcprelay/SRDhcprelay.params b/TestON/tests/USECASE/SegmentRouting/SRDhcprelay/SRDhcprelay.params
index 719f5f6..e52c4a7 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRDhcprelay/SRDhcprelay.params
+++ b/TestON/tests/USECASE/SegmentRouting/SRDhcprelay/SRDhcprelay.params
@@ -31,6 +31,22 @@
         <branch>master</branch>
     </GIT>
 
+    <ONOS_Configuration>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+    </ONOS_Logging>
+
+
     <CTRL>
         <port>6653</port>
     </CTRL>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRDhcprelay/SRDhcprelay.params.stratum b/TestON/tests/USECASE/SegmentRouting/SRDhcprelay/SRDhcprelay.params.stratum
new file mode 100644
index 0000000..e727787
--- /dev/null
+++ b/TestON/tests/USECASE/SegmentRouting/SRDhcprelay/SRDhcprelay.params.stratum
@@ -0,0 +1,86 @@
+<PARAMS>
+    <testcases>1,2,11,12,21,22,31,41,51,61,71</testcases>
+
+    <GRAPH>
+        <nodeCluster>Fabric</nodeCluster>
+        <builds>20</builds>
+    </GRAPH>
+
+    <SCALE>
+        <size>3</size>
+        <max>3</max>
+    </SCALE>
+
+    <DEPENDENCY>
+        <useCommonConf>False</useCommonConf>
+        <useCommonTopo>True</useCommonTopo>
+        <useBmv2>True</useBmv2>
+        <bmv2SwitchType>stratum</bmv2SwitchType>
+        <stratumRoot>~/stratum</stratumRoot>
+        <topology>trellis_fabric.py</topology>
+        <lib>routinglib.py,trellislib.py</lib>
+        <conf>dhcpd.conf,dhcpd6.conf,bgpdr1.conf,bgpdr2.conf,bgpdbgp1.conf,zebradbgp1.conf,bgpdbgp2.conf,zebradbgp2.conf</conf>
+    </DEPENDENCY>
+
+    <MN_DOCKER>
+        <args>--privileged --net host --rm -v topo:/topo -v ~/mininet/custom:/home/root/mininet/custom -v /var/run/openvswitch/:/var/run/openvswitch/ -v /tmp/mn-stratum:/tmp -v /tmp/mn_conf/:/home/root --hostname mn-stratum -v /etc/network/interfaces:/etc/network/interfaces -v /lib/modules:/lib/modules -it -d</args>
+        <name>trellis_mininet</name>
+        <home>/home/root/</home>
+    </MN_DOCKER>
+
+    <ENV>
+        <cellName>productionCell</cellName>
+        <cellApps>drivers,openflow,segmentrouting,fpm,dhcprelay,netcfghostprovider,routeradvertisement,drivers.bmv2,pipelines.fabric</cellApps>
+    </ENV>
+
+    <GIT>
+        <pull>False</pull>
+        <branch>master</branch>
+    </GIT>
+
+    <ONOS_Configuration>
+        <org.onosproject.grpc.ctl.GrpcChannelControllerImpl>
+            <enableMessageLog>true</enableMessageLog>
+        </org.onosproject.grpc.ctl.GrpcChannelControllerImpl>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+        <org.onosproject.p4runtime>DEBUG</org.onosproject.p4runtime>
+        <org.onosproject.protocols.p4runtime>DEBUG</org.onosproject.protocols.p4runtime>
+        <org.onosproject.drivers.p4runtime>DEBUG</org.onosproject.drivers.p4runtime>
+        <org.onosproject.protocols.grpc>DEBUG</org.onosproject.protocols.grpc>
+        <org.onosproject.protocols.gnmi>DEBUG</org.onosproject.protocols.gnmi>
+        <org.onosproject.protocols.gnoi>DEBUG</org.onosproject.protocols.gnoi>
+        <org.onosproject.drivers.gnoi>DEBUG</org.onosproject.drivers.gnoi>
+        <org.onosproject.drivers.gmni>DEBUG</org.onosproject.drivers.gmni>
+        <org.onosproject.drivers.stratum>DEBUG</org.onosproject.drivers.stratum>
+        <org.onosproject.bmv2>DEBUG</org.onosproject.bmv2>
+    </ONOS_Logging>
+
+
+    <CTRL>
+        <port>6653</port>
+    </CTRL>
+
+    <timers>
+        <LinkDiscovery>12</LinkDiscovery>
+        <SwitchDiscovery>12</SwitchDiscovery>
+    </timers>
+
+    <SLEEP>
+        <startup>10</startup>
+    </SLEEP>
+
+    <ALARM>
+        <minPassPercent>63</minPassPercent>
+    </ALARM>
+</PARAMS>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRDhcprelay/dependencies/SRDhcprelayTest.py b/TestON/tests/USECASE/SegmentRouting/SRDhcprelay/dependencies/SRDhcprelayTest.py
index 46220de..a2ceb25 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRDhcprelay/dependencies/SRDhcprelayTest.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRDhcprelay/dependencies/SRDhcprelayTest.py
@@ -47,12 +47,15 @@
         run.installOnos( main, skipPackage=skipPackage, cliSleep=5 )
         if main.useBmv2:
             # Translate configuration file from OVS-OFDPA to BMv2 driver
-            translator.ofdpaToBmv2( main )
+            translator.bmv2ToOfdpa( main ) # Try to cleanup if switching between switch types
+            switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
+            translator.ofdpaToBmv2( main, switchPrefix=switchPrefix )
         else:
             translator.bmv2ToOfdpa( main )
         run.loadJson( main )
         run.loadHost( main )
         if hasattr( main, 'Mininet1' ):
+            run.mnDockerSetup( main )
             # Run the test with Mininet
             if dualHomed:
                 mininet_args = ' --spine=2 --leaf=4 --dual-homed'
@@ -70,8 +73,8 @@
             if len( vlan ) > 0 :
                 mininet_args += ' --vlan=%s' % ( ','.join( ['%d' % vlanId for vlanId in vlan ] ) )
             if main.useBmv2:
-                mininet_args += ' --switch bmv2'
-                main.log.info( "Using BMv2 switch" )
+                mininet_args += ' --switch %s' % main.switchType
+                main.log.info( "Using %s switch" % main.switchType )
 
             run.startMininet( main, 'trellis_fabric.py', args=mininet_args )
         else:
diff --git a/TestON/tests/USECASE/SegmentRouting/SRDynamic/SRDynamic.params b/TestON/tests/USECASE/SegmentRouting/SRDynamic/SRDynamic.params
index f15f207..fdd3a93 100755
--- a/TestON/tests/USECASE/SegmentRouting/SRDynamic/SRDynamic.params
+++ b/TestON/tests/USECASE/SegmentRouting/SRDynamic/SRDynamic.params
@@ -28,6 +28,22 @@
         <branch>master</branch>
     </GIT>
 
+    <ONOS_Configuration>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+    </ONOS_Logging>
+
+
     <CTRL>
         <port>6653</port>
     </CTRL>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRDynamicConf/SRDynamicConf.params b/TestON/tests/USECASE/SegmentRouting/SRDynamicConf/SRDynamicConf.params
index 376898b..ea42a59 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRDynamicConf/SRDynamicConf.params
+++ b/TestON/tests/USECASE/SegmentRouting/SRDynamicConf/SRDynamicConf.params
@@ -30,6 +30,22 @@
         <branch>master</branch>
     </GIT>
 
+    <ONOS_Configuration>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+    </ONOS_Logging>
+
+
     <CTRL>
         <port>6653</port>
     </CTRL>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRDynamicConf/dependencies/SRDynamicConfTest.py b/TestON/tests/USECASE/SegmentRouting/SRDynamicConf/dependencies/SRDynamicConfTest.py
index 4e1703e..78f3e6a 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRDynamicConf/dependencies/SRDynamicConfTest.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRDynamicConf/dependencies/SRDynamicConfTest.py
@@ -73,7 +73,9 @@
         # TODO: Generate json and chart dynamically, according to topologies and scenarios
         if main.useBmv2:
             # Translate configuration file from OVS-OFDPA to BMv2 driver
-            translator.ofdpaToBmv2( main )
+            translator.bmv2ToOfdpa( main ) # Try to cleanup if switching between switch types
+            switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
+            translator.ofdpaToBmv2( main, switchPrefix=switchPrefix )
         else:
             translator.bmv2ToOfdpa( main )
         run.loadJson( main )
@@ -85,7 +87,9 @@
             intfCfg = "%s%s%s.json" % ( main.configPath, main.forJson, TAG )
             if main.useBmv2:
                 # Translate configuration file from OVS-OFDPA to BMv2 driver
-                translator.ofdpaToBmv2( main, intfCfg )
+                translator.bmv2ToOfdpa( main ) # Try to cleanup if switching between switch types
+                switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
+                translator.ofdpaToBmv2( main, switchPrefix=switchPrefix, cfgFile=intfCfg )
             else:
                 translator.bmv2ToOfdpa( main, intfCfg )
             with open( intfCfg ) as cfg:
@@ -95,7 +99,9 @@
             defaultIntfCfg = "%s%s%s_ports.json" % ( main.configPath, main.forJson, topology )
             if main.useBmv2:
                 # Translate configuration file from OVS-OFDPA to BMv2 driver
-                translator.ofdpaToBmv2( main, defaultIntfCfg )
+                translator.bmv2ToOfdpa( main ) # Try to cleanup if switching between switch types
+                switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
+                translator.ofdpaToBmv2( main, switchPrefix=switchPrefix, cfgFile=defaultIntfCfg )
             else:
                 translator.bmv2ToOfdpa( main, defaultIntfCfg )
             with open( defaultIntfCfg ) as cfg:
diff --git a/TestON/tests/USECASE/SegmentRouting/SRHighAvailability/SRHighAvailability.params b/TestON/tests/USECASE/SegmentRouting/SRHighAvailability/SRHighAvailability.params
index 577edac..b87d333 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRHighAvailability/SRHighAvailability.params
+++ b/TestON/tests/USECASE/SegmentRouting/SRHighAvailability/SRHighAvailability.params
@@ -28,6 +28,22 @@
         <branch>master</branch>
     </GIT>
 
+    <ONOS_Configuration>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+    </ONOS_Logging>
+
+
     <CTRL>
         <port>6653</port>
     </CTRL>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRLinkFailure/SRLinkFailure.params b/TestON/tests/USECASE/SegmentRouting/SRLinkFailure/SRLinkFailure.params
index 8e0bbbf..de88e07 100755
--- a/TestON/tests/USECASE/SegmentRouting/SRLinkFailure/SRLinkFailure.params
+++ b/TestON/tests/USECASE/SegmentRouting/SRLinkFailure/SRLinkFailure.params
@@ -28,6 +28,22 @@
         <branch>master</branch>
     </GIT>
 
+    <ONOS_Configuration>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+    </ONOS_Logging>
+
+
     <CTRL>
         <port>6653</port>
     </CTRL>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/SRMulticast.params b/TestON/tests/USECASE/SegmentRouting/SRMulticast/SRMulticast.params
index 4f61954..1fb91da 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/SRMulticast.params
+++ b/TestON/tests/USECASE/SegmentRouting/SRMulticast/SRMulticast.params
@@ -32,6 +32,22 @@
         <branch>master</branch>
     </GIT>
 
+    <ONOS_Configuration>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+    </ONOS_Logging>
+
+
     <CTRL>
         <port>6653</port>
     </CTRL>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/SRMulticast.params.flex b/TestON/tests/USECASE/SegmentRouting/SRMulticast/SRMulticast.params.flex
index fa4d15c..ba58a59 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/SRMulticast.params.flex
+++ b/TestON/tests/USECASE/SegmentRouting/SRMulticast/SRMulticast.params.flex
@@ -30,6 +30,22 @@
         <branch>master</branch>
     </GIT>
 
+    <ONOS_Configuration>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+    </ONOS_Logging>
+
+
     <CTRL>
         <port>6653</port>
     </CTRL>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/SRMulticastTest.py b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/SRMulticastTest.py
index 39897d5..1802221 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/SRMulticastTest.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRMulticast/dependencies/SRMulticastTest.py
@@ -42,7 +42,9 @@
     main.cfgName = "TEST_CONFIG_ipv4=1_ipv6=1" if hasattr( main, "Mininet1" ) else main.params[ "DEPENDENCY" ][ "confName" ]
     if main.useBmv2:
         # Translate configuration file from OVS-OFDPA to BMv2 driver
-        translator.ofdpaToBmv2( main )
+        translator.bmv2ToOfdpa( main ) # Try to cleanup if switching between switch types
+        switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
+        translator.ofdpaToBmv2( main, switchPrefix=switchPrefix )
     else:
         translator.bmv2ToOfdpa( main )
     lib.loadJson( main )
diff --git a/TestON/tests/USECASE/SegmentRouting/SROnosFailure/SROnosFailure.params b/TestON/tests/USECASE/SegmentRouting/SROnosFailure/SROnosFailure.params
index a991004..89f758c 100755
--- a/TestON/tests/USECASE/SegmentRouting/SROnosFailure/SROnosFailure.params
+++ b/TestON/tests/USECASE/SegmentRouting/SROnosFailure/SROnosFailure.params
@@ -28,6 +28,22 @@
         <branch>master</branch>
     </GIT>
 
+    <ONOS_Configuration>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+    </ONOS_Logging>
+
+
     <CTRL>
         <port>6653</port>
     </CTRL>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params
index 1d057b3..557f03d 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params
+++ b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params
@@ -32,6 +32,22 @@
         <branch>master</branch>
     </GIT>
 
+    <ONOS_Configuration>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+    </ONOS_Logging>
+
+
     <CTRL>
         <port>6653</port>
     </CTRL>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params.flex b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params.flex
index 7d2bd17..4b26f3b 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params.flex
+++ b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params.flex
@@ -30,6 +30,22 @@
         <branch>master</branch>
     </GIT>
 
+    <ONOS_Configuration>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+    </ONOS_Logging>
+
+
     <CTRL>
         <port>6653</port>
     </CTRL>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params.stratum b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params.stratum
new file mode 100644
index 0000000..f01fbf2
--- /dev/null
+++ b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.params.stratum
@@ -0,0 +1,98 @@
+<PARAMS>
+    <testcases>101,102,103,104,105,106,107,108,109,201,202,203,204,205,206,207,208,209,301,302,303,304,305,306,307,308,309,601,602,603,604,605,606,620,621,622,630,640,641,642,643,651,652,653,660,661,662,663,664,665</testcases>
+
+    <GRAPH>
+        <nodeCluster>Fabric</nodeCluster>
+        <builds>20</builds>
+    </GRAPH>
+
+    <SCALE>
+        <size>7</size>
+        <max>7</max>
+    </SCALE>
+
+    <DEPENDENCY>
+        <useCommonConf>False</useCommonConf>
+        <useCommonTopo>True</useCommonTopo>
+        <useBmv2>True</useBmv2>
+        <bmv2SwitchType>stratum</bmv2SwitchType>
+        <stratumRoot>~/stratum</stratumRoot>
+        <topology>hagg_fabric.py</topology>
+        <lib>routinglib.py,trellislib.py,trellis_fabric.py</lib>
+        <conf>bgpdbgp1.conf,bgpdbgp2.conf,bgpdr1.conf,bgpdr2.conf,dhcpd6.conf,dhcpd.conf,zebradbgp1.conf,zebradbgp2.conf</conf>
+    </DEPENDENCY>
+
+    <MN_DOCKER>
+        <args>--privileged --net host --rm -v topo:/topo -v ~/mininet/custom:/home/root/mininet/custom -v /var/run/openvswitch/:/var/run/openvswitch/ -v /tmp/mn-stratum:/tmp -v /tmp/mn_conf/:/home/root --hostname mn-stratum -v /etc/network/interfaces:/etc/network/interfaces -v /lib/modules:/lib/modules -it -d</args>
+        <name>trellis_mininet</name>
+        <home>/home/root/</home>
+    </MN_DOCKER>
+
+    <ENV>
+        <cellName>productionCell</cellName>
+        <cellApps>drivers,openflow,segmentrouting,fpm,dhcprelay,netcfghostprovider,routeradvertisement,t3,hostprobingprovider,drivers.bmv2,pipelines.fabric</cellApps>
+    </ENV>
+
+    <GIT>
+        <pull>False</pull>
+        <branch>master</branch>
+    </GIT>
+
+    <ONOS_Configuration>
+        <org.onosproject.grpc.ctl.GrpcChannelControllerImpl>
+            <enableMessageLog>true</enableMessageLog>
+        </org.onosproject.grpc.ctl.GrpcChannelControllerImpl>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+        <org.onosproject.p4runtime>DEBUG</org.onosproject.p4runtime>
+        <org.onosproject.protocols.p4runtime>DEBUG</org.onosproject.protocols.p4runtime>
+        <org.onosproject.drivers.p4runtime>DEBUG</org.onosproject.drivers.p4runtime>
+        <org.onosproject.protocols.grpc>DEBUG</org.onosproject.protocols.grpc>
+        <org.onosproject.protocols.gnmi>DEBUG</org.onosproject.protocols.gnmi>
+        <org.onosproject.protocols.gnoi>DEBUG</org.onosproject.protocols.gnoi>
+        <org.onosproject.drivers.gnoi>DEBUG</org.onosproject.drivers.gnoi>
+        <org.onosproject.drivers.gmni>DEBUG</org.onosproject.drivers.gmni>
+        <org.onosproject.drivers.stratum>DEBUG</org.onosproject.drivers.stratum>
+        <org.onosproject.bmv2>DEBUG</org.onosproject.bmv2>
+    </ONOS_Logging>
+
+
+    <CTRL>
+        <port>6653</port>
+    </CTRL>
+
+    <timers>
+        <LinkDiscovery>30</LinkDiscovery>
+        <SwitchDiscovery>45</SwitchDiscovery>
+        <OnosDiscovery>45</OnosDiscovery>
+        <loadNetcfgSleep>5</loadNetcfgSleep>
+        <startMininetSleep>25</startMininetSleep>
+        <dhcpSleep>150</dhcpSleep>
+        <balanceMasterSleep>10</balanceMasterSleep>
+    </timers>
+
+    <TOPO>
+        <internalIpv4Hosts>h1v4,h2v4,h3v4,h4v4,h5v4,h6v4,h7v4,h8v4,h9v4,h10v4,h11v4,h12v4,h13v4</internalIpv4Hosts>
+        <internalIpv6Hosts>h1v6,h2v6,h3v6,h4v6,h5v6,h6v6,h7v6,h8v6,h9v6,h10v6,h11v6,h12v6,h13v6</internalIpv6Hosts>
+        <externalIpv4Hosts>rh1v4,rh2v4</externalIpv4Hosts>
+        <externalIpv6Hosts>rh1v6,rh11v6,rh2v6,rh22v6</externalIpv6Hosts>
+        <staticIpv4Hosts>rh5v4</staticIpv4Hosts>
+        <staticIpv6Hosts>rh5v6</staticIpv6Hosts>
+        <switchNum>10</switchNum>
+        <linkNum>48</linkNum>
+    </TOPO>
+
+    <ALARM>
+        <minPassPercent>80</minPassPercent>
+    </ALARM>
+</PARAMS>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.py b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.py
index f379896..5ca5f40 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRRouting/SRRouting.py
@@ -508,6 +508,7 @@
         main.case( "Bring down all switches then recover" )
         setupTest( main, test_idx=601, external=False )
         main.Cluster.next().CLI.balanceMasters()
+        main.log.debug( "sleeping %i seconds" % float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
         time.sleep( float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
         main.Network.discoverHosts( hostList=main.internalIpv4Hosts + main.internalIpv6Hosts )
         totalSwitches = int( main.params[ 'TOPO' ][ 'switchNum' ] )
@@ -527,6 +528,7 @@
                                      onpass="All switches stopped",
                                      onfail="Failed to stop all switches" )
 
+            main.log.debug( "sleeping %i seconds" % float( 60 ) )
             time.sleep( 60 )
             lib.verifyTopology( main, 0, 0, main.Cluster.numCtrls )
             # Bring up all switches
@@ -542,8 +544,10 @@
             main.Network.discoverHosts( hostList=main.internalIpv4Hosts + main.internalIpv6Hosts )
             lib.verifyTopology( main, totalSwitches, totalLinks, main.Cluster.numCtrls )
             main.log.debug( main.Cluster.next().summary() )
+            main.log.debug( "sleeping %i seconds" % float( 60 ) )
             time.sleep( 60 )
             main.log.debug( main.Cluster.next().summary() )
+            main.log.debug( "sleeping %i seconds" % float( 60 ) )
             time.sleep( 60 )
             main.log.debug( main.Cluster.next().summary() )
             verifyPing( main )
@@ -935,6 +939,7 @@
             lib.restoreLinkBatch( main, linksToRemove, 48, 10 )
             lib.enablePortBatch( main, portsToDisable, 10, 48 )
             main.Network.discoverHosts( hostList=main.disconnectedIpv4Hosts + main.disconnectedIpv6Hosts )
+            main.log.debug( "sleeping %i seconds" % float( 10 ) )
             time.sleep( 10 )
             main.disconnectedIpv4Hosts = []
             main.disconnectedIpv6Hosts = []
@@ -1054,6 +1059,7 @@
                                                                                          switches ) )
             setupTest( main, test_idx=640 )
             main.Cluster.next().CLI.balanceMasters()
+            main.log.debug( "sleeping %i seconds" % float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
             time.sleep( float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
             main.Network.discoverHosts( hostList=main.internalIpv4Hosts + main.internalIpv6Hosts )
             instance = main.Cluster.controllers[ nodeIndex ]
@@ -1154,6 +1160,7 @@
                                                                                                  switches ) )
             setupTest( main, test_idx=641 )
             main.Cluster.next().CLI.balanceMasters()
+            main.log.debug( "sleeping %i seconds" % float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
             time.sleep( float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
             main.Network.discoverHosts( hostList=main.internalIpv4Hosts + main.internalIpv6Hosts )
             instance = main.Cluster.controllers[ nodeIndex ]
@@ -1208,6 +1215,7 @@
         main.case( "Drop ONOS instance and links at the same time" )
         setupTest( main, test_idx=642, onosNodes=3 )
         main.Cluster.active( 0 ).CLI.balanceMasters()
+        main.log.debug( "sleeping %i seconds" % float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
         time.sleep( float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
         verify( main )
         portsToDisable = [ [ "of:0000000000000001", 1 ], [ "of:0000000000000103", 1 ],
@@ -1255,6 +1263,7 @@
         main.case( "Drop ONOS instances and bring up links at the same time" )
         setupTest( main, test_idx=643, onosNodes=3 )
         main.Cluster.active( 0 ).CLI.balanceMasters()
+        main.log.debug( "sleeping %i seconds" % float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
         time.sleep( float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
         verify( main )
         portsToDisable = [ [ "of:0000000000000001", 1 ], [ "of:0000000000000103", 1 ],
@@ -1296,6 +1305,7 @@
         main.case( "Move a single-homed host to another port in the same DAAS" )
         setupTest( main, test_idx=651, onosNodes=3 )
         main.Cluster.active( 0 ).CLI.balanceMasters()
+        main.log.debug( "sleeping %i seconds" % float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
         time.sleep( float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
         verify( main )
         # Move an untagged IPv4 host on DAAS-1
@@ -1353,6 +1363,7 @@
         main.case( "Move a dual-homed host from porst 1A and 1B to ports 2A and 2B with the same MAC and IP" )
         setupTest( main, test_idx=652, onosNodes=3 )
         main.Cluster.active( 0 ).CLI.balanceMasters()
+        main.log.debug( "sleeping %i seconds" % float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
         time.sleep( float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
         verify( main )
 
@@ -1406,6 +1417,7 @@
         main.case( "Move a dual-homed host from porst 1A and 1B to ports 2A and 2B with the same IP and different MAC" )
         setupTest( main, test_idx=653, onosNodes=3 )
         main.Cluster.active( 0 ).CLI.balanceMasters()
+        main.log.debug( "sleeping %i seconds" % float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
         time.sleep( float( main.params[ 'timers' ][ 'balanceMasterSleep' ] ) )
         verify( main )
 
diff --git a/TestON/tests/USECASE/SegmentRouting/SRRouting/dependencies/SRRoutingTest.py b/TestON/tests/USECASE/SegmentRouting/SRRouting/dependencies/SRRoutingTest.py
index 0b13a61..2868b57 100644
--- a/TestON/tests/USECASE/SegmentRouting/SRRouting/dependencies/SRRoutingTest.py
+++ b/TestON/tests/USECASE/SegmentRouting/SRRouting/dependencies/SRRoutingTest.py
@@ -64,10 +64,13 @@
         main.cfgName = main.params[ "DEPENDENCY" ][ "confName" ]
     if main.useBmv2:
         # Translate configuration file from OVS-OFDPA to BMv2 driver
-        translator.ofdpaToBmv2( main )
+        translator.bmv2ToOfdpa( main ) # Try to cleanup if switching between switch types
+        switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
+        translator.ofdpaToBmv2( main, switchPrefix=switchPrefix )
     else:
         translator.bmv2ToOfdpa( main )
     lib.loadJson( main )
+    main.log.debug( "sleeping %i seconds" % float( main.params[ 'timers' ][ 'loadNetcfgSleep' ] ) )
     time.sleep( float( main.params[ 'timers' ][ 'loadNetcfgSleep' ] ) )
     lib.loadHost( main )
 
@@ -84,19 +87,22 @@
         lib.loadCount( main )
 
     if hasattr( main, 'Mininet1' ):
+        lib.mnDockerSetup( main )
         # Run the test with Mininet
         mininet_args = ' --dhcp=1 --routers=1 --ipv6={} --ipv4={}'.format( 1 if ipv6 else 0,
                                                                            1 if ipv4 else 0 )
         if main.useBmv2:
-            mininet_args += ' --switch bmv2'
-            main.log.info( "Using BMv2 switch" )
+            mininet_args += ' --switch %s' % main.switchType
+            main.log.info( "Using %s switch"  % main.switchType )
         lib.startMininet( main, main.params[ 'DEPENDENCY' ][ 'topology' ], args=mininet_args )
+        main.log.debug( "Waiting %i seconds for ONOS to discover dataplane" % float( main.params[ "timers" ][ "startMininetSleep" ] ))
         time.sleep( float( main.params[ "timers" ][ "startMininetSleep" ] ) )
     else:
         # Run the test with physical devices
         lib.connectToPhysicalNetwork( main )
 
     # wait some time for onos to install the rules!
+    main.log.info( "Waiting %i seconds for ONOS to program the dataplane" % float( main.params[ "timers" ][ "dhcpSleep" ] ))
     time.sleep( float( main.params[ 'timers' ][ 'dhcpSleep' ] ) )
 
 def verifyPingInternal( main, ipv4=True, ipv6=True, disconnected=True ):
@@ -240,11 +246,13 @@
         # Kill node
         lib.killOnos( main, [ ctrl ], switches, links, ( numCtrls - 1 ) )
         main.Cluster.active(0).CLI.balanceMasters()
+        main.log.debug( "sleeping %i seconds" % mastershipSleep )
         time.sleep( mastershipSleep )
         verify( main, ipv4, ipv6, disconnected, internal, external, countFlowsGroups )
         # Recover node
         lib.recoverOnos( main, [ ctrl ], switches, links, numCtrls )
         main.Cluster.active(0).CLI.balanceMasters()
+        main.log.debug( "sleeping %i seconds" % mastershipSleep )
         time.sleep( mastershipSleep )
         verify( main, ipv4, ipv6, disconnected, internal, external, countFlowsGroups )
 
diff --git a/TestON/tests/USECASE/SegmentRouting/SRSanity/SRSanity.params b/TestON/tests/USECASE/SegmentRouting/SRSanity/SRSanity.params
index 541c836..a0b85f8 100755
--- a/TestON/tests/USECASE/SegmentRouting/SRSanity/SRSanity.params
+++ b/TestON/tests/USECASE/SegmentRouting/SRSanity/SRSanity.params
@@ -28,6 +28,22 @@
         <branch>master</branch>
     </GIT>
 
+    <ONOS_Configuration>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+    </ONOS_Logging>
+
+
     <CTRL>
         <port>6653</port>
     </CTRL>
diff --git a/TestON/tests/USECASE/SegmentRouting/SRSwitchFailure/SRSwitchFailure.params b/TestON/tests/USECASE/SegmentRouting/SRSwitchFailure/SRSwitchFailure.params
index 8e0bbbf..de88e07 100755
--- a/TestON/tests/USECASE/SegmentRouting/SRSwitchFailure/SRSwitchFailure.params
+++ b/TestON/tests/USECASE/SegmentRouting/SRSwitchFailure/SRSwitchFailure.params
@@ -28,6 +28,22 @@
         <branch>master</branch>
     </GIT>
 
+    <ONOS_Configuration>
+    </ONOS_Configuration>
+
+    <ONOS_Logging>
+        <org.onosproject.events>TRACE</org.onosproject.events>
+        <org.onosproject.segmentrouting>DEBUG</org.onosproject.segmentrouting>
+        <org.onosproject.driver>DEBUG</org.onosproject.driver>
+        <org.onosproject.net.flowobjective.impl>DEBUG</org.onosproject.net.flowobjective.impl>
+        <org.onosproject.routeservice.impl>DEBUG</org.onosproject.routeservice.impl>
+        <org.onosproject.routeservice.store>DEBUG</org.onosproject.routeservice.store>
+        <org.onosproject.routing.fpm>DEBUG</org.onosproject.routing.fpm>
+        <org.onosproject.fpm>DEBUG</org.onosproject.fpm>
+        <org.onosproject.mcast>DEBUG</org.onosproject.mcast>
+    </ONOS_Logging>
+
+
     <CTRL>
         <port>6653</port>
     </CTRL>
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/Dockerfile b/TestON/tests/USECASE/SegmentRouting/dependencies/Dockerfile
index 1843055..4b714c5 100644
--- a/TestON/tests/USECASE/SegmentRouting/dependencies/Dockerfile
+++ b/TestON/tests/USECASE/SegmentRouting/dependencies/Dockerfile
@@ -1,6 +1,32 @@
 FROM opennetworking/mn-stratum
 
-RUN install_packages python-pip openvswitch-switch
-#RUN apt-get update && apt-get install -y python-pip
+ENV HOME /home/root
+WORKDIR $HOME
+RUN ln -s /root/* .
+RUN chmod 777 $HOME
+
+RUN install_packages python-pip openvswitch-switch vim quagga isc-dhcp-server isc-dhcp-client iptables vlan
 RUN pip install ipaddress
+
+RUN ln -s $HOME /var/run/quagga
+RUN ln -s /usr/sbin/zebra /usr/lib/quagga/zebra
+RUN ln -s /usr/sbin/bgpd /usr/lib/quagga/bgpd
+
+# try to ensure dhclient can write pid files
+RUN chmod 777 /run
+RUN ls -al $HOME
+# Issue with Uubuntu/Apparmour
+RUN mv /sbin/dhclient /usr/local/bin/ \
+&& touch /var/lib/dhcp/dhcpd.leases
+
+# Install custom mininet branch
+run install_packages git sudo lsb-release
+RUN git clone https://github.com/jhall11/mininet.git \
+&& cd mininet \
+&& git branch -v -a \
+&& git checkout -b dynamic_topo origin/dynamic_topo \
+&& cd util \
+&& alias sudo='' \
+&& apt-get update \
+&& ./install.sh -3fvn
 ENTRYPOINT bash
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py b/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
index efd8868..dd2b870 100644
--- a/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
+++ b/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
@@ -49,6 +49,7 @@
             main.cleanAndExit()
         from tests.dependencies.Network import Network
         main.Network = Network()
+        main.physicalNet = False
         main.testSetUp.envSetupDescription( False )
         stepResult = main.FALSE
         try:
@@ -63,6 +64,11 @@
                 main.useBmv2 = main.params[ 'DEPENDENCY' ][ 'useBmv2' ] == 'True'
             else:
                 main.useBmv2 = False
+            if main.useBmv2:
+                main.switchType = main.params[ 'DEPENDENCY' ].get( 'bmv2SwitchType', 'stratum' )
+            else:
+                main.switchType = "ovs"
+
             main.configPath = main.path + ( "/.." if main.useCommonConf else "" ) + "/dependencies/"
             main.bmv2Path = "/tools/dev/mininet/"
             main.forJson = "json/"
@@ -103,8 +109,16 @@
         - Connect to cli
         """
         # main.scale[ 0 ] determines the current number of ONOS controller
-        if not main.apps:
-            main.log.error( "App list is empty" )
+        try:
+            if main.params.get( 'EXTERNAL_APPS' ):
+                for app, url in main.params[ 'EXTERNAL_APPS' ].iteritems():
+                    main.log.info( "Downloading %s app from %s" )
+                    main.ONOSbench.onosFetchApp( url )
+            if not main.apps:
+                main.log.error( "App list is empty" )
+        except Exception as e:
+            main.log.debug( e )
+            main.cleanAndExit()
         main.log.info( "Cluster size: " + str( main.Cluster.numCtrls ) )
         main.log.info( "Cluster ips: " + ', '.join( main.Cluster.getIps() ) )
         main.dynamicHosts = [ 'in1', 'out1' ]
@@ -135,37 +149,35 @@
         if not appInstallResult:
             main.cleanAndExit()
 
-        for ctrl in main.Cluster.active():
-            ctrl.CLI.logSet( "DEBUG", "org.onosproject.segmentrouting" )
-            ctrl.CLI.logSet( "DEBUG", "org.onosproject.driver" )
-            ctrl.CLI.logSet( "DEBUG", "org.onosproject.net.flowobjective.impl" )
-            ctrl.CLI.logSet( "DEBUG", "org.onosproject.routeservice.impl" )
-            ctrl.CLI.logSet( "DEBUG", "org.onosproject.routeservice.store" )
-            ctrl.CLI.logSet( "DEBUG", "org.onosproject.routing.fpm" )
-            ctrl.CLI.logSet( "DEBUG", "org.onosproject.fpm" )
-            ctrl.CLI.logSet( "TRACE", "org.onosproject.events" )
-            ctrl.CLI.logSet( "DEBUG", "org.onosproject.mcast" )
+        # FIXME: move to somewhere else?
+        switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix' )
+        # TODO: Support other pipeconfs/making this configurable
+        if switchPrefix == "tofino":
+            # It seems to take some time for the pipeconfs to be loaded
+            ctrl = main.Cluster.next()
+            for i in range( 120 ):
+                try:
+                    main.log.debug( "Checking to see if pipeconfs are loaded" )
+                    output = ctrl.CLI.sendline( "pipeconfs" )
+                    if "tofino" in output:
+                        main.log.debug( "Took around %s seconds for the pipeconf to be loaded" % i )
+                        break
+                    time.sleep( 1 )
+                except Exception as e:
+                    main.log.error( e )
 
-            ctrl.CLI.logSet( "TRACE", "org.onosproject.p4runtime" )
-            ctrl.CLI.logSet( "TRACE", "org.onosproject.protocols.p4runtime" )
-            ctrl.CLI.logSet( "TRACE", "org.onosproject.drivers.p4runtime" )
-            ctrl.CLI.logSet( "TRACE", "org.onosproject.protocols.grpc" )
-            ctrl.CLI.logSet( "TRACE", "org.onosproject.protocols.gnmi" )
-            ctrl.CLI.logSet( "TRACE", "org.onosproject.protocols.gnoi" )
-            ctrl.CLI.logSet( "TRACE", "org.onosproject.drivers.gnoi" )
-            ctrl.CLI.logSet( "TRACE", "org.onosproject.drivers.gmni" )
-            ctrl.CLI.logSet( "TRACE", "org.onosproject.drivers.stratum" )
-            ctrl.CLI.logSet( "TRACE", "org.onosproject.bmv2" )
+        Testcaselib.setOnosLogLevels( main )
+        Testcaselib.setOnosConfig( main )
 
     @staticmethod
     def loadCount( main ):
-        with open("%s/count/%s.count" % (main.configPath, main.cfgName)) as count:
-                main.count = json.load(count)
+        with open( "%s/count/%s.count" % ( main.configPath, main.cfgName ) ) as count:
+                main.count = json.load( count )
 
     @staticmethod
-    def loadJson( main ):
-        with open( "%s%s.json" % ( main.configPath + main.forJson,
-                                   main.cfgName ) ) as cfg:
+    def loadJson( main, suffix='' ):
+        with open( "%s%s.json%s" % ( main.configPath + main.forJson,
+                                     main.cfgName, suffix ) ) as cfg:
             main.Cluster.active( 0 ).REST.setNetCfg( json.load( cfg ) )
 
     @staticmethod
@@ -173,7 +185,7 @@
         try:
             with open( "%s%s.chart" % ( main.configPath + main.forChart,
                                         main.cfgName ) ) as chart:
-                main.pingChart = json.load(chart)
+                main.pingChart = json.load( chart )
         except IOError:
             main.log.warn( "No chart file found." )
 
@@ -203,6 +215,7 @@
 
     @staticmethod
     def startMininet( main, topology, args="" ):
+        main.log.info( "Copying mininet topology file to mininet machine" )
         copyResult = main.ONOSbench.scp( main.Mininet1,
                                          main.topoPath + main.topology,
                                          main.Mininet1.home + "custom",
@@ -217,6 +230,22 @@
             import re
             controllerIPs = [ ctrl.ipAddress for ctrl in main.Cluster.runningNodes ]
             index = 0
+            destDir = "~/"
+            if 'MN_DOCKER' in main.params and main.params['MN_DOCKER']['args']:
+                destDir = "/tmp/mn_conf/"
+                # Try to ensure the destination exists
+                main.log.info( "Create folder for network config files" )
+                handle = main.Mininet1.handle
+                handle.sendline( "mkdir -p %s" % destDir )
+                handle.expect( [ main.Mininet1.prompt, main.Mininet1.dockerPrompt ] )
+                main.log.debug( handle.before + handle.after )
+                # Make sure permissions are correct
+                handle.sendline( "sudo chown %s:%s %s" % ( main.Mininet1.user_name, main.Mininet1.user_name, destDir ) )
+                handle.expect( [ main.Mininet1.prompt, main.Mininet1.dockerPrompt ] )
+                main.log.debug( handle.before + handle.after )
+                handle.sendline( "sudo chmod -R a+rwx %s" % ( destDir ) )
+                handle.expect( [ main.Mininet1.prompt, main.Mininet1.dockerPrompt ] )
+                main.log.debug( handle.before + handle.after )
             for conf in main.topologyConf.split(","):
                 # Update zebra configurations with correct ONOS instance IP
                 if conf in [ "zebradbgp1.conf", "zebradbgp2.conf" ]:
@@ -229,7 +258,7 @@
                         f.write( s )
                 copyResult = copyResult and main.ONOSbench.scp( main.Mininet1,
                                                                 main.configPath + main.forConfig + conf,
-                                                                "~/",
+                                                                destDir,
                                                                 direction="to" )
         copyResult = copyResult and main.ONOSbench.scp( main.Mininet1,
                                                         main.ONOSbench.home + main.bmv2Path + main.bmv2,
@@ -246,8 +275,6 @@
         main.step( "Starting Mininet Topology" )
         arg = "--onos-ip=%s %s" % (",".join([ctrl.ipAddress for ctrl in main.Cluster.runningNodes]), args)
         main.topology = topology
-        #switchType = " --switch=stratum"
-        #arg += switchType
         topoResult = main.Mininet1.startNet(
                 topoFile=main.Mininet1.home + "custom/" + main.topology, args=arg )
         stepResult = topoResult
@@ -258,25 +285,73 @@
         # Exit if topology did not load properly
         if not topoResult:
             main.cleanAndExit()
+        if main.useBmv2:
+            # Upload the net-cfg file created for each switch
+            filename = "onos-netcfg.json"
+            switchPrefix = main.params[ 'DEPENDENCY' ].get( 'switchPrefix', "bmv2" )
+            for switch in main.Mininet1.getSwitches( switchRegex=r"(StratumBmv2Switch)|(Bmv2Switch)" ).keys():
+                path = "/tmp/mn-stratum/%s/" % switch
+                dstPath = "/tmp/"
+                dstFileName = "%s-onos-netcfg.json" % switch
+                main.ONOSbench1.scp( main.Mininet1,
+                                     "%s%s" % ( path, filename ),
+                                     "%s%s" % ( dstPath, dstFileName ),
+                                     "from" )
+                main.ONOSbench1.handle.sendline( "sudo sed -i 's/localhost/%s/g' %s%s" % ( main.Mininet1.ip_address, dstPath, dstFileName ) )
+                # Configure managementAddress
+                main.ONOSbench1.handle.sendline( "sudo sed -i 's/localhost/%s/g' %s%s" % ( main.Mininet1.ip_address, dstPath, dstFileName ) )
+                main.ONOSbench1.handle.expect( main.ONOSbench1.prompt )
+                main.log.debug( main.ONOSbench1.handle.before + main.ONOSbench1.handle.after )
+                # Configure device id
+                main.ONOSbench1.handle.sendline( "sudo sed -i 's/device:%s/device:%s:%s/g' %s%s" % ( switch, switchPrefix, switch, dstPath, dstFileName ) )
+                main.ONOSbench1.handle.expect( main.ONOSbench1.prompt )
+                main.log.debug( main.ONOSbench1.handle.before + main.ONOSbench1.handle.after )
+                # Configure device name
+                main.ONOSbench1.handle.sendline( "sudo sed -i '/\"basic\"/a\        \"name\": \"%s\",' %s%s" % ( switch, dstPath, dstFileName ) )
+                main.ONOSbench1.handle.expect( main.ONOSbench1.prompt )
+                main.log.debug( main.ONOSbench1.handle.before + main.ONOSbench1.handle.after )
+                main.ONOSbench1.onosNetCfg( main.ONOSserver1.ip_address, dstPath, dstFileName )
+        # Make sure hosts make some noise
+        Testcaselib.discoverHosts( main )
+
+    @staticmethod
+    def discoverHosts( main ):
+        # TODO add option to only select specific hosts
+        if hasattr( main, "Mininet1" ):
+            network = main.Mininet1
+        elif hasattr( main, "NetworkBench" ):
+            network = main.NetworkBench
+        else:
+            main.log.warn( "Could not find component for test network, skipping host discovery" )
+            return
+        network.discoverHosts()
 
     @staticmethod
     def connectToPhysicalNetwork( main ):
         main.step( "Connecting to physical netowrk" )
+        main.physicalNet = True
         topoResult = main.NetworkBench.connectToNet()
         stepResult = topoResult
         utilities.assert_equals( expect=main.TRUE,
                                  actual=stepResult,
-                                 onpass="Successfully loaded topology",
-                                 onfail="Failed to load topology" )
+                                 onpass="Successfully connected to topology",
+                                 onfail="Failed to connect to topology" )
         # Exit if topology did not load properly
         if not topoResult:
             main.cleanAndExit()
 
+        # Perform any optional setup
+        for switch in main.NetworkBench.switches:
+            if hasattr( switch, "setup" ):
+                switch.setup()  # We might not need this
+
         main.step( "Assign switches to controllers." )
-        assignResult = main.TRUE
+        stepResult = main.TRUE
         switches = main.NetworkBench.getSwitches()
         pool = []
         for name in switches.keys():
+            # NOTE: although this terminology is ovsdb centric, we can use this function for other switches too
+            #       e.g. push onos net-cfg for stratum switches
             thread = main.Thread( target=main.NetworkBench.assignSwController,
                                   name="assignSwitchToController",
                                   args=[ name, main.Cluster.getIps(), '6653' ] )
@@ -293,7 +368,6 @@
 
         # Check devices
         Testcaselib.checkDevices( main, switches=int( main.params[ 'TOPO' ][ 'switchNum' ] ) )
-        time.sleep( float( main.params[ "timers" ][ "connectToNetSleep" ] ) )
         # Connecting to hosts that only have data plane connectivity
         main.step( "Connecting inband hosts" )
         stepResult = main.Network.connectInbandHosts()
@@ -301,6 +375,7 @@
                                  actual=stepResult,
                                  onpass="Successfully connected inband hosts",
                                  onfail="Failed to connect inband hosts" )
+        Testcaselib.discoverHosts( main )
 
     @staticmethod
     def saveOnosDiagnostics( main ):
@@ -408,8 +483,8 @@
         utilities.assertEquals(
                 expect=True,
                 actual=( count > minFlowCount ),
-                onpass="Flow count looks correct: " + str( count ),
-                onfail="Flow count looks wrong: " + str( count ) )
+                onpass="Flow count looks correct; found %s, expecting at least %s" % ( count, minFlowCount ),
+                onfail="Flow count looks wrong; found %s, expecting at least %s" % ( count, minFlowCount ) )
 
         main.step( "Check whether all flow status are ADDED" )
         flowCheck = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowsState,
@@ -450,7 +525,7 @@
     @staticmethod
     def checkFlowsByDpid( main, dpid, minFlowCount, sleep=10 ):
         main.step(
-            " Check whether the flow count of device %s is bigger than %s" % ( dpid, minFlowCount ) )
+            "Check whether the flow count of device %s is bigger than %s" % ( dpid, minFlowCount ) )
         count = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowAddedCount,
                                  main.FALSE,
                                  args=( dpid, minFlowCount ),
@@ -467,7 +542,7 @@
     @staticmethod
     def checkFlowEqualityByDpid( main, dpid, flowCount, sleep=10 ):
         main.step(
-                " Check whether the flow count of device %s is equal to %s" % ( dpid, flowCount ) )
+                "Check whether the flow count of device %s is equal to %s" % ( dpid, flowCount ) )
         count = utilities.retry( main.Cluster.active( 0 ).CLI.checkFlowAddedCount,
                                  main.FALSE,
                                  args=( dpid, flowCount, False, 1 ),
@@ -484,7 +559,7 @@
     @staticmethod
     def checkGroupEqualityByDpid( main, dpid, groupCount, sleep=10):
         main.step(
-                " Check whether the group count of device %s is equal to %s" % ( dpid, groupCount ) )
+                "Check whether the group count of device %s is equal to %s" % ( dpid, groupCount ) )
         count = utilities.retry( main.Cluster.active( 0 ).CLI.checkGroupAddedCount,
                                  main.FALSE,
                                  args=( dpid, groupCount, False, 1),
@@ -547,6 +622,12 @@
                         utilities.assert_equals( expect=expect, actual=pa,
                                                  onpass="IPv6 connectivity successfully tested",
                                                  onfail="IPv6 connectivity failed" )
+                elif main.physicalNet:
+                    pa = main.NetworkBench.pingallHostsUnidirectional( src, dst, acceptableFailed=acceptableFailed, useScapy=True )
+                    utilities.assert_equals( expect=expect, actual=pa,
+                                             onpass="IP connectivity successfully tested",
+                                             onfail="IP connectivity failed" )
+
                 else:
                     pa = main.Network.pingallHostsUnidirectional( src, dst, acceptableFailed=acceptableFailed )
                     utilities.assert_equals( expect=expect, actual=pa,
@@ -564,7 +645,8 @@
                     if ("v4" in hosts[0]):
                         pa = utilities.retry( main.Network.pingallHosts,
                                               main.FALSE if expect else main.TRUE,
-                                              args=(hosts,),
+                                              args=(hosts, ),
+                                              kwargs={ 'ipv6': False },
                                               attempts=retryAttempts,
                                               sleep=sleep )
                         utilities.assert_equals( expect=expect, actual=pa,
@@ -575,13 +657,19 @@
                         utilities.assert_equals( expect=expect, actual=pa,
                                                  onpass="IPv6 connectivity successfully tested",
                                                  onfail="IPv6 connectivity failed" )
+                elif main.physicalNet:
+                    pa = main.Network.pingallHosts( hosts, ipv6=True, useScapy=True )
+                    utilities.assert_equals( expect=expect, actual=pa,
+                                             onpass="IP connectivity successfully tested",
+                                             onfail="IP connectivity failed" )
                 else:
                     pa = main.Network.pingallHosts( hosts )
                     utilities.assert_equals( expect=expect, actual=pa,
                                              onpass="IP connectivity successfully tested",
                                              onfail="IP connectivity failed" )
-            if skipOnFail and pa != expect:
+            if pa != expect:
                 Testcaselib.saveOnosDiagnostics( main )
+            if skipOnFail and pa != expect:
                 Testcaselib.cleanup( main, copyKarafLog=False )
                 main.skipCase()
 
@@ -764,6 +852,8 @@
             if portUp:
                 ctrl.CLI.portstate( dpid=dpid1, port=port1, state='Enable' )
                 ctrl.CLI.portstate( dpid=dpid2, port=port2, state='Enable' )
+                main.log.info(
+                        "Waiting %s seconds for link up to be discovered" % sleep )
                 time.sleep( sleep )
 
             result = ctrl.CLI.checkStatus( numoswitch=switches,
@@ -919,6 +1009,7 @@
 
         for ctrl in main.Cluster.active():
             main.ONOSbench.onosStop( ctrl.ipAddress )
+        Testcaselib.mnDockerTeardown( main )
 
     @staticmethod
     def verifyNodes( main ):
@@ -985,6 +1076,7 @@
                                      onfail="Error killing ONOS instance" )
             main.Cluster.runningNodes[ i ].active = False
         main.Cluster.reset()
+        main.log.debug( "sleeping %i seconds" % ( sleep ) )
         time.sleep( sleep )
 
         if len( nodes ) < main.Cluster.numCtrls:
@@ -1004,6 +1096,7 @@
         else:
             sleep = float( sleep )
         [ main.ONOSbench.onosStart( main.Cluster.runningNodes[ i ].ipAddress ) for i in nodes ]
+        main.log.debug( "sleeping %i seconds" % ( sleep ) )
         time.sleep( sleep )
         for i in nodes:
             isUp = main.ONOSbench.isup( main.Cluster.runningNodes[ i ].ipAddress )
@@ -1135,7 +1228,7 @@
                                                      main.FALSE,
                                                      kwargs={ 'hostList': [ hostName ],
                                                               'prefix': ip,
-                                                              'update': False },
+                                                              'update': True },
                                                      attempts=attempts,
                                                      sleep=sleep )
         utilities.assert_equals( expect=main.TRUE, actual=ipResult,
@@ -1224,7 +1317,16 @@
                     mininetName = mininetNames[ scapyNames.index( scapyName ) ]
                 else:
                     mininetName = None
-                scapyHandle.startHostCli( mininetName )
+                if 'MN_DOCKER' in main.params and main.params['MN_DOCKER']['args']:
+                    scapyHandle.mExecDir = "/tmp"
+                    scapyHandle.hostHome = main.params[ "MN_DOCKER" ][ "home" ]
+                    main.log.debug( "start mn host component in docker" )
+                    scapyHandle.startHostCli( mininetName,
+                                              execDir="/tmp",
+                                              hostHome=main.params[ "MN_DOCKER" ][ "home" ] )
+                else:
+                    main.log.debug( "start mn host component" )
+                    scapyHandle.startHostCli( mininetName )
             else:
                 main.Network.createHostComponent( scapyName )
                 scapyHandle = getattr( main, scapyName )
@@ -1416,6 +1518,7 @@
             main.Cluster.active( 0 ).REST.setNetCfg( json.loads( cfg ),
                                                      subjectClass="ports" )
             # Wait for the host to get RA for setting up default gateway
+            main.log.debug( "sleeping %i seconds" % ( 5 ) )
             time.sleep( 5 )
 
         main.Mininet1.discoverHosts( [ hostName, ] )
@@ -1466,6 +1569,7 @@
             main.Cluster.active( 0 ).REST.setNetCfg( json.loads( cfg ),
                                                      subjectClass="ports" )
             # Wait for the host to get RA for setting up default gateway
+            main.log.debug( "sleeping %i seconds" % ( 5 ) )
             time.sleep( 5 )
 
         main.Mininet1.discoverHosts( [ hostName, ] )
@@ -1479,3 +1583,114 @@
                         vlan = hostName.split( "/" )[ -1 ]
                         del main.expectedHosts[ "onos" ][ hostName ]
                         main.expectedHosts[ "onos" ][ "{}/{}".format( macAddr.upper(), vlan ) ] = ip
+
+    @staticmethod
+    def mnDockerSetup( main ):
+        """
+        Optionally start and setup docker image for mininet
+        """
+        if 'MN_DOCKER' in main.params and main.params['MN_DOCKER']['args']:
+
+            main.log.info( "Creating Mininet Docker" )
+            handle = main.Mininet1.handle
+            main.Mininet1.dockerPrompt = '#'
+
+            confDir = "/tmp/mn_conf/"
+            # Try to ensure the destination exists
+            main.log.info( "Create folder for network config files" )
+            handle.sendline( "mkdir -p %s" % confDir )
+            handle.expect( main.Mininet1.prompt )
+            main.log.debug( handle.before + handle.after )
+            # Make sure permissions are correct
+            handle.sendline( "sudo chown %s:%s %s" % ( main.Mininet1.user_name, main.Mininet1.user_name, confDir ) )
+            handle.sendline( "sudo chmod -R a+rwx %s" % ( confDir ) )
+            handle.expect( main.Mininet1.prompt )
+            main.log.debug( handle.before + handle.after )
+            # Start docker container
+            handle.sendline( "docker run --name trellis_mininet %s %s" % ( main.params[ 'MN_DOCKER' ][ 'args' ], main.params[ 'MN_DOCKER' ][ 'name' ] ) )
+            handle.expect( main.Mininet1.bashPrompt )
+            output = handle.before + handle.after
+            main.log.debug( repr(output) )
+
+            handle.sendline( "docker attach trellis_mininet" )
+            handle.expect( main.Mininet1.dockerPrompt )
+            main.log.debug( handle.before + handle.after )
+            handle.sendline( "sysctl -w net.ipv4.ip_forward=0" )
+            handle.sendline( "sysctl -w net.ipv4.conf.all.forwarding=0" )
+            handle.expect( main.Mininet1.dockerPrompt )
+            main.log.debug( handle.before + handle.after )
+            # We should be good to go
+            main.Mininet1.prompt = main.Mininet1.dockerPrompt
+            main.Mininet1.sudoRequired = False
+
+            # Fow when we create component handles
+            main.Mininet1.mExecDir = "/tmp"
+            main.Mininet1.hostHome = main.params[ "MN_DOCKER" ][ "home" ]
+            main.Mininet1.hostPrompt = "/home/root#"
+
+    @staticmethod
+    def mnDockerTeardown( main ):
+        """
+        Optionally stop and cleanup docker image for mininet
+        """
+
+        if hasattr( main, 'Mininet1' ):
+            if 'MN_DOCKER' in main.params and main.params['MN_DOCKER']['args']:
+                main.log.info( "Deleting Mininet Docker" )
+
+                # Detach from container
+                handle = main.Mininet1.handle
+                try:
+                    handle.sendline( "exit" )  # ctrl-p ctrk-q  to detach from container
+                    main.log.debug( "sleeping %i seconds" % ( 5 ) )
+                    time.sleep(5)
+                    handle.expect( main.Mininet1.dockerPrompt )
+                    main.log.debug( handle.before + handle.after )
+                    main.Mininet1.prompt = main.Mininet1.bashPrompt
+                    handle.expect( main.Mininet1.prompt )
+                    main.log.debug( handle.before + handle.after )
+                    main.Mininet1.sudoRequired = True
+                except Exception as e:
+                    main.log.error( e )
+
+    @staticmethod
+    def setOnosConfig( main ):
+        """
+        Read and Set onos configurations from the params file
+        """
+        main.step( "Set ONOS configurations" )
+        config = main.params.get( 'ONOS_Configuration' )
+        if config:
+            main.log.debug( config )
+            checkResult = main.TRUE
+            for component in config:
+                for setting in config[ component ]:
+                    value = config[ component ][ setting ]
+                    check = main.Cluster.next().setCfg( component, setting, value )
+                    main.log.info( "Value was changed? {}".format( main.TRUE == check ) )
+                    checkResult = check and checkResult
+            utilities.assert_equals( expect=main.TRUE,
+                                     actual=checkResult,
+                                     onpass="Successfully set config",
+                                     onfail="Failed to set config" )
+        else:
+            main.log.warn( "No configurations were specified to be changed after startup" )
+
+    @staticmethod
+    def setOnosLogLevels( main ):
+        """
+        Read and Set onos log levels from the params file
+        """
+        main.step( 'Set logging levels' )
+        logging = True
+        try:
+            logs = main.params.get( 'ONOS_Logging', False )
+            if logs:
+                for namespace, level in logs.items():
+                    for ctrl in main.Cluster.active():
+                        ctrl.CLI.logSet( level, namespace )
+        except AttributeError:
+            logging = False
+        utilities.assert_equals( expect=True, actual=logging,
+                                 onpass="Set log levels",
+                                 onfail="Failed to set log levels" )
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/cfgtranslator.py b/TestON/tests/USECASE/SegmentRouting/dependencies/cfgtranslator.py
index f38603e..5e95efe 100644
--- a/TestON/tests/USECASE/SegmentRouting/dependencies/cfgtranslator.py
+++ b/TestON/tests/USECASE/SegmentRouting/dependencies/cfgtranslator.py
@@ -28,6 +28,7 @@
 
 # Translate configuration JSON file from BMv2 driver to OFDPA-OVS driver.
 def bmv2ToOfdpa( main, cfgFile="" ):
+    didRE = r"device:(?P<swType>bmv2|tofino):(?P<swRole>leaf|spine)(?P<swNum>[1-9][0-9]*)(/(?P<portNum>[0-9]+))?"
     if not cfgFile:
         cfgFile = "%s%s.json" % ( main.configPath + main.forJson,
                                   main.cfgName )
@@ -36,9 +37,9 @@
 
     if 'ports' in netcfg.keys():
         for port in netcfg[ 'ports' ].keys():
-            searchObj = re.search( "device:bmv2:leaf([1-9][0-9]*)/([0-9]+)", port )
+            searchObj = re.search( didRE, port )
             if searchObj:
-                new_port = 'of:' + searchObj.group( 1 ).zfill( 16 ) + '/' + searchObj.group( 2 )
+                new_port = 'of:' + searchObj.group( 'swNum' ).zfill( 16 ) + '/' + searchObj.group( 'portNum' )
                 netcfg[ 'ports' ][ new_port ] = netcfg[ 'ports' ].pop( port )
 
     if 'hosts' in netcfg.keys():
@@ -46,32 +47,31 @@
             if type( hostCfg[ 'basic' ][ 'locations' ] ) is list:
                 new_locations = []
                 for location in hostCfg[ 'basic' ][ 'locations' ]:
-                    searchObj = re.search( "device:bmv2:leaf([1-9][0-9]*)/([0-9]+)", location )
+                    searchObj = re.search( didRE, location )
                     if searchObj:
-                        new_locations.append( 'of:' + searchObj.group( 1 ).zfill( 16 ) + '/' + searchObj.group( 2 ) )
+                        new_locations.append( 'of:' + searchObj.group( 'swNum' ).zfill( 16 ) + '/' + searchObj.group( 'portNum' ) )
                     else:
                         new_locations.append( location )
                 netcfg[ 'hosts' ][ host ][ 'basic' ][ 'locations' ] = new_locations
             else:
                 location = hostCfg[ 'basic' ][ 'locations' ]
-                searchObj = re.search( "device:bmv2:leaf([1-9][0-9]*)/([0-9]+)", location )
+                searchObj = re.search( didRE, location )
                 if searchObj:
-                    new_location = 'of:' + searchObj.group( 1 ).zfill( 16 ) + '/' + searchObj.group( 2 )
+                    new_location = 'of:' + searchObj.group( 'swNum' ).zfill( 16 ) + '/' + searchObj.group( 'portNum' )
                     netcfg[ 'hosts' ][ host ][ 'basic' ][ 'locations' ] = new_location
 
     if 'devices' in netcfg.keys():
         for device in netcfg[ 'devices' ].keys():
-            searchObj = re.search( "device:bmv2:(leaf|spine)([1-9][0-9]*)", device )
+            searchObj = re.search( didRE, device )
             new_device = device
             if searchObj:
-                new_device = 'of:' + searchObj.group( 2 ).zfill( 16 )
+                new_device = 'of:' + searchObj.group( 'swNum' ).zfill( 16 )
                 netcfg[ 'devices' ][ new_device ] = netcfg[ 'devices' ].pop( device )
             if 'pairDeviceId' in netcfg[ 'devices' ][ new_device ][ SR_APP ].keys():
-                searchObj = re.search( "device:bmv2:leaf([1-9][0-9]*)",
-                                       netcfg[ 'devices' ][ new_device ][ SR_APP ][ 'pairDeviceId' ])
+                searchObj = re.search( didRE, netcfg[ 'devices' ][ new_device ][ SR_APP ][ 'pairDeviceId' ])
                 if searchObj:
                     netcfg[ 'devices' ][ new_device ][ SR_APP ][ 'pairDeviceId' ] = 'of:' + \
-                                                                                    searchObj.group( 1 ).zfill( 16 )
+                                                                                    searchObj.group( 'swNum' ).zfill( 16 )
             if 'basic' in netcfg[ 'devices' ][ new_device ].keys():
                 netcfg[ 'devices' ][ new_device ][ 'basic' ].update( { 'driver': 'ofdpa-ovs' } )
 
@@ -79,17 +79,18 @@
         if DHCP_APP_ID in netcfg[ 'apps' ].keys():
             for i, dhcpcfg in enumerate( netcfg[ 'apps' ][ DHCP_APP_ID ][ 'default' ] ):
                 if 'dhcpServerConnectPoint' in dhcpcfg.keys():
-                    searchObj = re.search( "device:bmv2:leaf([1-9][0-9]*)/([0-9]+)",
-                                           dhcpcfg[ 'dhcpServerConnectPoint' ] )
+                    searchObj = re.search( didRE, dhcpcfg[ 'dhcpServerConnectPoint' ] )
                     if searchObj:
                         netcfg[ 'apps' ][ DHCP_APP_ID ][ 'default' ][ i ][ 'dhcpServerConnectPoint' ] = \
-                            'of:' + searchObj.group( 1 ).zfill(16) + '/' + searchObj.group( 2 )
+                            'of:' + searchObj.group( 'swNum' ).zfill(16) + '/' + searchObj.group( 'portNum' )
 
     with open( cfgFile, 'w' ) as cfg:
-        cfg.write( json.dumps( netcfg, indent=4, separators=( ',', ':' ) ) )
+        cfg.write( json.dumps( netcfg, indent=4, separators=( ',', ':' ), sort_keys=True ) )
 
 # Translate configuration JSON file from OFDPA-OVS driver to BMv2 driver.
-def ofdpaToBmv2( main, cfgFile="" ):
+def ofdpaToBmv2( main, switchPrefix="bmv2", cfgFile="" ):
+    didRE= r"device:(?P<swType>bmv2|tofino):(?P<swRole>leaf|spine)(?P<swNum>[1-9][0-9]*)(/(?P<portNum>[0-9]+))?"
+    didRE = r"of:0*(?P<swNum>[1-9][0-9]*)(/(?P<portNum>[0-9]+))?"
     if not cfgFile:
         cfgFile = "%s%s.json" % ( main.configPath + main.forJson,
                                   main.cfgName )
@@ -98,9 +99,9 @@
 
     if 'ports' in netcfg.keys():
         for port in netcfg[ 'ports' ].keys():
-            searchObj = re.search( "of:0*([1-9][0-9]*)/([0-9]+)", port )
+            searchObj = re.search( didRE, port )
             if searchObj:
-                new_port = 'device:bmv2:leaf' + searchObj.group( 1 ) + '/' + searchObj.group( 2 )
+                new_port = 'device:' + switchPrefix + ':leaf' + searchObj.group( 'swNum' ) + '/' + searchObj.group( 'portNum' )
                 netcfg[ 'ports' ][ new_port ] = netcfg[ 'ports' ].pop( port )
 
     if 'hosts' in netcfg.keys():
@@ -108,36 +109,36 @@
             if type( hostCfg[ 'basic' ][ 'locations' ] ) is list:
                 new_locations = []
                 for location in hostCfg[ 'basic' ][ 'locations' ]:
-                    searchObj = re.search( "of:0*([1-9][0-9]*)/([0-9]+)", location )
+                    searchObj = re.search( didRE, location )
                     if searchObj:
-                        new_locations.append( 'device:bmv2:leaf' + searchObj.group( 1 ) + '/' + searchObj.group( 2 ) )
+                        new_locations.append( 'device:' + switchPrefix + ':leaf' + searchObj.group( 'swNum' ) + '/' + searchObj.group( 'portNum' ) )
                     else:
                         new_locations.append( location )
                 netcfg[ 'hosts' ][ host ][ 'basic' ][ 'locations' ] = new_locations
             else:
                 location = hostCfg[ 'basic' ][ 'locations' ]
-                searchObj = re.search( "of:0*([1-9][0-9]*)/([0-9]+)", location )
+                searchObj = re.search( didRE, location )
                 if searchObj:
-                    new_location = 'device:bmv2:leaf' + searchObj.group( 1 ) + '/' + searchObj.group( 2 )
+                    new_location = 'device:' + switchPrefix + ':leaf' + searchObj.group( 'swNum' ) + '/' + searchObj.group( 'portNum' )
                     netcfg[ 'hosts' ][ host ][ 'basic' ][ 'locations' ] = new_location
 
     if 'devices' in netcfg.keys():
         for device in netcfg[ 'devices' ].keys():
-            searchObj = re.search( "of:0*([1-9][0-9]*)", device )
+            searchObj = re.search( didRE, device )
             new_device = device
             if searchObj:
                 isLeaf = netcfg[ 'devices' ][ device ][ SR_APP ][ 'isEdgeRouter' ]
                 if isLeaf is True:
-                    new_device = 'device:bmv2:leaf' + searchObj.group( 1 )
+                    new_device = 'device:' + switchPrefix + ':leaf' + searchObj.group( 'swNum' )
                 else:
-                    new_device = 'device:bmv2:spine' + searchObj.group( 1 )
+                    new_device = 'device:' + switchPrefix + ':spine' + searchObj.group( 'swNum' )
                 netcfg[ 'devices' ][ new_device ] = netcfg[ 'devices' ].pop( device )
             if 'pairDeviceId' in netcfg[ 'devices' ][ new_device ][ SR_APP ].keys():
-                searchObj = re.search( "of:0*([1-9][0-9]*)",
+                searchObj = re.search( didRE,
                                        netcfg[ 'devices' ][ new_device ][ SR_APP ][ 'pairDeviceId' ])
                 if searchObj:
-                    netcfg[ 'devices' ][ new_device ][ SR_APP ][ 'pairDeviceId' ] = 'device:bmv2:leaf' + \
-                                                                                    searchObj.group( 1 )
+                    netcfg[ 'devices' ][ new_device ][ SR_APP ][ 'pairDeviceId' ] = 'device:' + switchPrefix + ':leaf' + \
+                                                                                    searchObj.group( 'swNum' )
             if 'basic' in netcfg[ 'devices' ][ new_device ].keys():
                 if 'driver' in netcfg[ 'devices' ][ new_device ][ 'basic' ].keys():
                     del netcfg[ 'devices' ][ new_device ][ 'basic' ][ 'driver' ]
@@ -146,11 +147,11 @@
         if DHCP_APP_ID in netcfg[ 'apps' ].keys():
             for i, dhcpcfg in enumerate( netcfg[ 'apps' ][ DHCP_APP_ID ][ 'default' ] ):
                 if 'dhcpServerConnectPoint' in dhcpcfg.keys():
-                    searchObj = re.search( "of:0*([1-9][0-9]*)/([0-9]+)",
+                    searchObj = re.search( didRE,
                                            dhcpcfg[ 'dhcpServerConnectPoint' ] )
                     if searchObj:
                         netcfg[ 'apps' ][ DHCP_APP_ID ][ 'default' ][ i ][ 'dhcpServerConnectPoint' ] = \
-                            'device:bmv2:leaf' + searchObj.group( 1 ) + '/' + searchObj.group( 2 )
+                            'device:' + switchPrefix + ':leaf' + searchObj.group( 'swNum' ) + '/' + searchObj.group( 'portNum' )
 
     with open( cfgFile, 'w' ) as cfg:
-        cfg.write( json.dumps( netcfg, indent=4, separators=( ',', ':' ) ) )
+        cfg.write( json.dumps( netcfg, indent=4, separators=( ',', ':' ), sort_keys=True ) )
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/hagg_fabric.py b/TestON/tests/USECASE/SegmentRouting/dependencies/hagg_fabric.py
index 814b6fb..6e5626e 100644
--- a/TestON/tests/USECASE/SegmentRouting/dependencies/hagg_fabric.py
+++ b/TestON/tests/USECASE/SegmentRouting/dependencies/hagg_fabric.py
@@ -15,6 +15,7 @@
 from trellislib import DhcpServer, TaggedRoutedHost, DualHomedRoutedHost, DualHomedTaggedRoutedHost, DhcpClient, Dhcp6Client, DhcpServer, Dhcp6Server, TrellisHost
 
 from bmv2 import ONOSBmv2Switch
+from stratum import StratumBmv2Switch
 
 # Parse command line options and dump results
 def parseOptions():
@@ -31,7 +32,7 @@
     parser.add_option( '--onos-ip', dest='onosIp', type='str', default='',
                        help='IP address list of ONOS instances, separated by comma(,). Overrides --onos option' )
     parser.add_option( '--switch', dest='switch', type='str', default='ovs',
-                       help='Switch type: ovs, bmv2 (with fabric.p4)' )
+                       help='Switch type: ovs, bmv2 (with fabric.p4), stratum' )
 
     ( options, args ) = parser.parse_args()
     return options, args
@@ -42,7 +43,8 @@
 
 SWITCH_TO_PARAMS_DICT = {
     "ovs": dict(cls=OVSSwitch),
-    "bmv2": dict(cls=ONOSBmv2Switch, pipeconf=FABRIC_PIPECONF)
+    "bmv2": dict(cls=ONOSBmv2Switch, pipeconf=FABRIC_PIPECONF),
+    "stratum": dict(cls=StratumBmv2Switch, pipeconf=FABRIC_PIPECONF, loglevel='debug')
 }
 if opts.switch not in SWITCH_TO_PARAMS_DICT:
     raise Exception("Unknown switch type '%s'" % opts.switch)
@@ -261,7 +263,7 @@
                                              dpid = "00000000000%s" % (ls + 1),
                                              **SWITCH_PARAMS )
 
-        # connecting leaf and spines, leafs 1-5 have double links
+        # connecting leafs 2-5 and spines 101 and 102 with double links
         for s in range(2):
             spine_switch = self.spines[s]
 
@@ -275,7 +277,7 @@
         self.addLink(self.leafs[1], self.leafs[2], **linkopts)
         self.addLink(self.leafs[3], self.leafs[4], **linkopts)
 
-        # build second fabric with single links
+        # build second fabric with single links, spines 103 and 104 and leafs 1 and 6
         for s in range(2, 4):
             spine_switch = self.spines[s]
 
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/trellis_fabric.py b/TestON/tests/USECASE/SegmentRouting/dependencies/trellis_fabric.py
index 8668f83..7556d58 100644
--- a/TestON/tests/USECASE/SegmentRouting/dependencies/trellis_fabric.py
+++ b/TestON/tests/USECASE/SegmentRouting/dependencies/trellis_fabric.py
@@ -365,7 +365,7 @@
         self.addLink(r1, rh1)
 
         # External IPv6 Host behind r1
-        rh1v6 = self.addHost('rh1v6', cls=TrellisHost, ips=['2000::9902/120'], gateway='2000::9901')
+        rh1v6 = self.addHost('rh1v6', cls=TrellisHost, ips=['2000::9902/120'], gateway='2000::9901', ipv6=True )
         self.addLink(r1, rh1v6)
 
         # DHCP server
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/trellislib.py b/TestON/tests/USECASE/SegmentRouting/dependencies/trellislib.py
index ebf6910..e02df4c 100644
--- a/TestON/tests/USECASE/SegmentRouting/dependencies/trellislib.py
+++ b/TestON/tests/USECASE/SegmentRouting/dependencies/trellislib.py
@@ -9,6 +9,7 @@
 sys.path.append('..')
 from mininet.node import Host
 from routinglib import RoutedHost, RoutedHost6, Router
+from stratum import NoOffloadHost
 
 class TaggedRoutedHost(RoutedHost):
     """Host that can be configured with multiple IP addresses."""
@@ -24,6 +25,7 @@
         intf = self.defaultIntf()
         self.vlanIntf = "%s.%s" % (intf, self.vlan)
         self.cmd('ip -4 addr flush dev %s' % intf)
+        self.cmd('sysctl -w net.ipv4.ip_forward=0')
         self.cmd('ip link add link %s name %s type vlan id %s' % (intf, self.vlanIntf, self.vlan))
         self.cmd('ip link set up %s' % self.vlanIntf)
 
@@ -38,7 +40,7 @@
         self.cmd('ip link remove link %s' % self.vlanIntf)
         super(TaggedRoutedHost, self).terminate()
 
-class DualHomedRoutedHost(Host):
+class DualHomedRoutedHost(NoOffloadHost):
     def __init__(self, name, ips, gateway, *args, **kwargs):
         super(DualHomedRoutedHost, self).__init__(name, **kwargs)
         self.bond0 = None
@@ -72,6 +74,7 @@
         self.cmd('ip link set %s master %s' % (intf2.name, self.bond0))
         self.cmd('ip addr flush dev %s' % intf1.name)
         self.cmd('ip addr flush dev %s' % intf2.name)
+        self.cmd('sysctl -w net.ipv4.ip_forward=0')
         self.cmd('ip link set %s up' % self.bond0)
         # NOTE: Issues with bonded intfs in mn data structures. Either only show bonded intf
         #       or create a custom class to handle bonded infs??
@@ -100,6 +103,7 @@
         default_intf = self.defaultIntf()
         self.vlanIntf = "%s.%s" % (default_intf, self.vlan)
         self.cmd('ip -4 addr flush dev %s' % default_intf)
+        self.cmd('sysctl -w net.ipv4.ip_forward=0')
         self.cmd('ip link add link %s name %s type vlan id %s' % (default_intf, self.vlanIntf, self.vlan))
         self.cmd('ip link set up %s' % self.vlanIntf)
 
@@ -123,6 +127,7 @@
     def config(self, **kwargs):
         super(DhcpClient, self).config(**kwargs)
         self.cmd('ip addr flush dev %s' % self.defaultIntf())
+        self.cmd('sysctl -w net.ipv4.ip_forward=0')
         self.cmd('dhclient -q -4 -nw -pf %s -lf %s %s' % (self.pidFile, self.leaseFile, self.defaultIntf()))
 
     def terminate(self, **kwargs):
@@ -139,6 +144,7 @@
     def config(self, **kwargs):
         super(Dhcp6Client, self).config(**kwargs)
         self.cmd('ip -4 addr flush dev %s' % self.defaultIntf())
+        self.cmd('sysctl -w net.ipv4.ip_forward=0')
         self.cmd('dhclient -q -6 -nw -pf %s -lf %s %s' % (self.pidFile, self.leaseFile, self.defaultIntf()))
 
     def terminate(self, **kwargs):
@@ -214,6 +220,7 @@
         super(TaggedDhcpClient, self).config(**kwargs)
         self.vlanIntf = "%s.%s" % (self.defaultIntf(), self.vlan)
         self.cmd('ip addr flush dev %s' % self.defaultIntf())
+        self.cmd('sysctl -w net.ipv4.ip_forward=0')
         self.cmd('ip link add link %s name %s type vlan id %s' % (self.defaultIntf(), self.vlanIntf, self.vlan))
         self.cmd('ip link set up %s' % self.vlanIntf)
         self.cmd('dhclient -q -4 -nw -pf %s %s' % (self.pidFile, self.vlanIntf))
@@ -267,6 +274,7 @@
         self.cmd('ip link set %s master %s' % (intf2.name, self.bond0))
         self.cmd('ip addr flush dev %s' % intf1.name)
         self.cmd('ip addr flush dev %s' % intf2.name)
+        self.cmd('sysctl -w net.ipv4.ip_forward=0')
         self.cmd('ip link set %s up' % self.bond0)
         # NOTE: Issues with bonded intfs in mn data structures. Either only show bonded intf
         #       or create a custom class to handle bonded infs??
@@ -284,7 +292,7 @@
         self.cmd('rm -rf %s' % self.pidFile)
         super(DualHomedDhcpClient, self).terminate()
 
-class TrellisHost(Host):
+class TrellisHost(NoOffloadHost):
     def __init__(self, name, ips=[], gateway="", dualHomed=False, vlan=None, dhcpClient=False, dhcpServer=False, ipv6=False, *args, **kwargs):
         super(TrellisHost, self).__init__(name, *args, **kwargs)
         self.dualHomed = dualHomed
@@ -313,6 +321,10 @@
             self.bondIntfs( self.intfs[0], self.intfs[1] )
 
         self.cmd('ip %s addr flush dev %s' % ("-4" if self.ipv6 else "", self.defaultIntf()))
+        self.cmd('sysctl -w net.ipv4.ip_forward=0')
+
+        if not self.ipv6:
+            self.cmd('sysctl -w net.ipv6.conf.all.disable_ipv6=1')
 
         if self.vlan:
             # Setup vlan interface
diff --git a/TestON/tests/dependencies/Cluster.py b/TestON/tests/dependencies/Cluster.py
index 7e850ba..9ed9256 100644
--- a/TestON/tests/dependencies/Cluster.py
+++ b/TestON/tests/dependencies/Cluster.py
@@ -676,10 +676,14 @@
         # multiplier is somewhat arbitrary, but the idea is the logs would have
         # been compacted before this many segments are written
 
-        maxSize = float( segmentSize ) * float( multiplier )
-        ret = True
-        for n in self.runningNodes:
-            # Partition logs
-            ret = ret and n.server.folderSize( "/opt/atomix/data/raft/partitions/*/*.log",
-                                               size=maxSize, unit=units, ignoreRoot=False )
-        return ret
+        try:
+            maxSize = float( segmentSize ) * float( multiplier )
+            ret = True
+            for n in self.runningNodes:
+                # Partition logs
+                ret = ret and n.server.folderSize( "/opt/atomix/data/raft/partitions/*/*.log",
+                                                   size=maxSize, unit=units, ignoreRoot=False )
+            return ret
+        except Exception as e:
+            main.log.error( e )
+            main.log.error( repr( e ) )
diff --git a/TestON/tests/dependencies/ONOSSetup.py b/TestON/tests/dependencies/ONOSSetup.py
index 8371e0b..0a00fd7 100644
--- a/TestON/tests/dependencies/ONOSSetup.py
+++ b/TestON/tests/dependencies/ONOSSetup.py
@@ -19,6 +19,7 @@
     along with TestON.  If not, see <http://www.gnu.org/licenses/>.
 """
 import re
+import os
 
 
 class ONOSSetup:
@@ -605,6 +606,12 @@
             else:
                 main.log.warn( "No apps were specified to be checked after startup" )
 
+        externalAppsResult = main.TRUE
+        if main.params.get( 'EXTERNAL_APPS' ):
+            for app, url in main.params[ 'EXTERNAL_APPS' ].iteritems():
+                path, fileName = os.path.split( url )
+                main.ONOSbench.onosApp( main.Cluster.controllers[0].ipAddress, "install!", fileName )
+
         return killResult and cellResult and packageResult and uninstallResult and \
                installResult and secureSshResult and onosServiceResult and onosCliResult and \
                onosNodesResult and onosAppsResult