diff --git a/bin/mn b/bin/mn
index 75166b76ab244436e85e7e825f4d5359cdbe519a..fbe1f05bbfb08888e5069eeb65ba754a9867f504 100755
--- a/bin/mn
+++ b/bin/mn
@@ -25,11 +25,13 @@ from mininet.cli import CLI
 from mininet.log import lg, LEVELS, info, debug, error
 from mininet.net import Mininet, MininetWithControlNet, VERSION
 from mininet.node import ( Host, CPULimitedHost, Controller, OVSController,
-                           NOX, RemoteController, UserSwitch, OVSKernelSwitch,
+                           NOX, RemoteController, DefaultController,
+                           UserSwitch, OVSSwitch,
                            OVSLegacyKernelSwitch, IVSSwitch )
+from mininet.nodelib import LinuxBridge
 from mininet.link import Link, TCLink
 from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
-from mininet.topolib import TreeTopo
+from mininet.topolib import TreeTopo, TorusTopo
 from mininet.util import custom, customConstructor
 from mininet.util import buildTopo
 
@@ -40,24 +42,29 @@ TOPOS = { 'minimal': lambda: SingleSwitchTopo( k=2 ),
           'linear': LinearTopo,
           'reversed': SingleSwitchReversedTopo,
           'single': SingleSwitchTopo,
-          'tree': TreeTopo }
+          'tree': TreeTopo,
+          'torus': TorusTopo }
 
 SWITCHDEF = 'ovsk'
 SWITCHES = { 'user': UserSwitch,
-             'ovsk': OVSKernelSwitch,
+             'ovs':  OVSSwitch,
+             # Keep ovsk for compatibility with 2.0
+             'ovsk': OVSSwitch,
              'ovsl': OVSLegacyKernelSwitch,
-             'ivs': IVSSwitch }
+             'ivs': IVSSwitch,
+             'lxbr': LinuxBridge }
 
 HOSTDEF = 'proc'
 HOSTS = { 'proc': Host,
           'rt': custom( CPULimitedHost, sched='rt' ),
           'cfs': custom( CPULimitedHost, sched='cfs' ) }
 
-CONTROLLERDEF = 'ovsc'
+CONTROLLERDEF = 'default'
 CONTROLLERS = { 'ref': Controller,
                 'ovsc': OVSController,
                 'nox': NOX,
                 'remote': RemoteController,
+                'default': DefaultController,
                 'none': lambda name: None }
 
 LINKDEF = 'default'
@@ -261,12 +268,14 @@ class MininetRunner( object ):
         if test == 'none':
             pass
         elif test == 'all':
+            mn.waitConnected()
             mn.start()
             mn.ping()
             mn.iperf()
         elif test == 'cli':
             CLI( mn )
         elif test != 'build':
+            mn.waitConnected()
             getattr( mn, test )()
 
         if self.options.post:
diff --git a/examples/linearbandwidth.py b/examples/linearbandwidth.py
index 3fd06c757db8730d10ccee8345ebd9de458f0ce9..dee5490cf28a34376a7cc93bb8a92be181badc36 100755
--- a/examples/linearbandwidth.py
+++ b/examples/linearbandwidth.py
@@ -24,7 +24,7 @@
 """
 
 from mininet.net import Mininet
-from mininet.node import UserSwitch, OVSKernelSwitch
+from mininet.node import UserSwitch, OVSKernelSwitch, Controller
 from mininet.topo import Topo
 from mininet.log import lg
 from mininet.util import irange
@@ -76,7 +76,7 @@ def linearBandwidthTest( lengths ):
         print "*** testing", datapath, "datapath"
         Switch = switches[ datapath ]
         results[ datapath ] = []
-        net = Mininet( topo=topo, switch=Switch )
+        net = Mininet( topo=topo, switch=Switch, controller=Controller, waitConnected=True )
         net.start()
         print "*** testing basic connectivity"
         for n in lengths:
diff --git a/mininet/net.py b/mininet/net.py
index 135807bd2258a7be5618caa105c223456eaca41a..4224b974dacef4b24a20cb77f99a5cc09f1e9685 100755
--- a/mininet/net.py
+++ b/mininet/net.py
@@ -90,12 +90,13 @@
 import re
 import select
 import signal
+import copy
 from time import sleep
 from itertools import chain, groupby
 
 from mininet.cli import CLI
-from mininet.log import info, error, debug, output
-from mininet.node import Host, OVSKernelSwitch, Controller
+from mininet.log import info, error, debug, output, warn
+from mininet.node import Host, OVSKernelSwitch, DefaultController, Controller
 from mininet.link import Link, Intf
 from mininet.util import quietRun, fixLimits, numCores, ensureRoot
 from mininet.util import macColonHex, ipStr, ipParse, netParse, ipAdd
@@ -109,11 +110,11 @@ class Mininet( object ):
     "Network emulation with hosts spawned in network namespaces."
 
     def __init__( self, topo=None, switch=OVSKernelSwitch, host=Host,
-                  controller=Controller, link=Link, intf=Intf,
+                  controller=DefaultController, link=Link, intf=Intf,
                   build=True, xterms=False, cleanup=False, ipBase='10.0.0.0/8',
                   inNamespace=False,
                   autoSetMacs=False, autoStaticArp=False, autoPinCpus=False,
-                  listenPort=None ):
+                  listenPort=None, waitConnected=False ):
         """Create Mininet object.
            topo: Topo (topology) object or None
            switch: default Switch class
@@ -149,6 +150,7 @@ def __init__( self, topo=None, switch=OVSKernelSwitch, host=Host,
         self.numCores = numCores()
         self.nextCore = 0  # next core for pinning hosts to CPUs
         self.listenPort = listenPort
+        self.waitConn = waitConnected
 
         self.hosts = []
         self.switches = []
@@ -166,6 +168,37 @@ def __init__( self, topo=None, switch=OVSKernelSwitch, host=Host,
         if topo and build:
             self.build()
 
+
+    def waitConnected( self, timeout=None, delay=.5 ):
+        """wait for each switch to connect to a controller,
+           up to 5 seconds
+           timeout: time to wait, or None to wait indefinitely
+           delay: seconds to sleep per iteration
+           returns: True if all switches are connected"""
+        info( '*** Waiting for switches to connect\n' )
+        time = 0
+        remaining = list( self.switches )
+        while True:
+            for switch in tuple( remaining ):
+                if switch.connected():
+                    info( '%s ' % switch )
+                    remaining.remove( switch )
+            if not remaining:
+                info( '\n' )
+                return True
+            if time > timeout and timeout is not None:
+                break
+            sleep( delay )
+            time += delay
+        warn( 'Timed out after %d seconds\n' % time )
+        for switch in remaining:
+            if not switch.connected():
+                warn( 'Warning: %s is not connected to a controller\n'
+                      % switch.name )
+            else:
+                remaining.remove( switch )
+        return not remaining
+
     def addHost( self, name, cls=None, **params ):
         """Add host.
            name: name of host to add
@@ -216,7 +249,7 @@ def addController( self, name='c0', controller=None, **params ):
         if not controller:
             controller = self.controller
         # Construct new controller if one is not given
-        if isinstance(name, Controller):
+        if isinstance( name, Controller ):
             controller_new = name
             # Pylint thinks controller is a str()
             # pylint: disable=E1103
@@ -225,7 +258,7 @@ def addController( self, name='c0', controller=None, **params ):
         else:
             controller_new = controller( name, **params )
         # Add new controller to net
-        if controller_new:  # allow controller-less setups
+        if controller_new: # allow controller-less setups
             self.controllers.append( controller_new )
             self.nameToNode[ name ] = controller_new
         return controller_new
@@ -327,7 +360,11 @@ def buildFromTopo( self, topo=None ):
             if type( classes ) is not list:
                 classes = [ classes ]
             for i, cls in enumerate( classes ):
-                self.addController( 'c%d' % i, cls )
+                # Allow Controller objects because nobody understands currying
+                if isinstance( cls, Controller ):
+                    self.addController( cls )
+                else:
+                    self.addController( 'c%d' % i, cls )
 
         info( '*** Adding hosts:\n' )
         for hostName in topo.hosts():
@@ -408,9 +445,16 @@ def start( self ):
             info( switch.name + ' ')
             switch.start( self.controllers )
         info( '\n' )
+        if self.waitConn:
+            self.waitConnected()
 
     def stop( self ):
         "Stop the controller(s), switches and hosts"
+        info( '*** Stopping %i controllers\n' % len( self.controllers ) )
+        for controller in self.controllers:
+            info( controller.name + ' ' )
+            controller.stop()
+        info( '\n' )
         if self.terms:
             info( '*** Stopping %i terms\n' % len( self.terms ) )
             self.stopXterms()
@@ -426,11 +470,6 @@ def stop( self ):
         for host in self.hosts:
             info( host.name + ' ' )
             host.terminate()
-        info( '\n' )
-        info( '*** Stopping %i controllers\n' % len( self.controllers ) )
-        for controller in self.controllers:
-            info( controller.name + ' ' )
-            controller.stop()
         info( '\n*** Done\n' )
 
     def run( self, test, *args, **kwargs ):
@@ -623,7 +662,7 @@ def _parseIperf( iperfOutput ):
 
     # XXX This should be cleaned up
 
-    def iperf( self, hosts=None, l4Type='TCP', udpBw='10M' ):
+    def iperf( self, hosts=None, l4Type='TCP', udpBw='10M', format=None ):
         """Run iperf between two hosts.
            hosts: list of hosts; if None, uses opposite hosts
            l4Type: string, one of [ TCP, UDP ]
@@ -646,6 +685,8 @@ def iperf( self, hosts=None, l4Type='TCP', udpBw='10M' ):
             bwArgs = '-b ' + udpBw + ' '
         elif l4Type != 'TCP':
             raise Exception( 'Unexpected l4 type: %s' % l4Type )
+        if format:
+          iperfArgs += '-f %s ' %format
         server.sendCmd( iperfArgs + '-s', printPid=True )
         servout = ''
         while server.lastPid is None:
@@ -653,7 +694,7 @@ def iperf( self, hosts=None, l4Type='TCP', udpBw='10M' ):
         if l4Type == 'TCP':
             while 'Connected' not in client.cmd(
                     'sh -c "echo A | telnet -e A %s 5001"' % server.IP()):
-                output('waiting for iperf to start up...')
+                info( 'Waiting for iperf to start up...' )
                 sleep(.5)
         cliout = client.cmd( iperfArgs + '-t 5 -c ' + server.IP() + ' ' +
                              bwArgs )
diff --git a/mininet/node.py b/mininet/node.py
index 568d9863216904fcf5a2e8a45fc8cae52ecfdeb4..d9052fab7e6f1a8a5134044edc6f869e08e2a05a 100644
--- a/mininet/node.py
+++ b/mininet/node.py
@@ -1277,13 +1277,19 @@ def __repr__( self ):
         return '<%s %s: %s:%s pid=%s> ' % (
             self.__class__.__name__, self.name,
             self.IP(), self.port, self.pid )
-
+    @classmethod
+    def isAvailable( self ):
+        return quietRun( 'which controller' )
 
 class OVSController( Controller ):
     "Open vSwitch controller"
     def __init__( self, name, command='ovs-controller', **kwargs ):
+        if quietRun( 'which test-controller' ):
+            command = 'test-controller'
         Controller.__init__( self, name, command=command, **kwargs )
-
+    @classmethod
+    def isAvailable( self ):
+        return quietRun( 'which ovs-controller' ) or quietRun( 'which test-controller' )
 
 class NOX( Controller ):
     "Controller to run a NOX application."
@@ -1338,3 +1344,10 @@ def checkListening( self ):
         if 'Connected' not in listening:
             warn( "Unable to contact the remote controller"
                   " at %s:%d\n" % ( self.ip, self.port ) )
+
+
+def DefaultController( name, order=[ Controller, OVSController ], **kwargs ):
+    "find any controller that is available and run it"
+    for controller in order:
+        if controller.isAvailable():
+            return controller( name, **kwargs )
diff --git a/mininet/nodelib.py b/mininet/nodelib.py
new file mode 100644
index 0000000000000000000000000000000000000000..2eb80465cd005c28c9a2aaa86aa920b2cc04c02a
--- /dev/null
+++ b/mininet/nodelib.py
@@ -0,0 +1,51 @@
+"""
+Node Library for Mininet
+
+This contains additional Node types which you may find to be useful
+"""
+
+from mininet.net import Mininet
+from mininet.topo import Topo
+from mininet.node import Switch
+from mininet.log import setLogLevel, info
+
+
+class LinuxBridge( Switch ):
+    "Linux Bridge (with optional spanning tree)"
+
+    nextPrio = 100  # next bridge priority for spanning tree
+
+    def __init__( self, name, stp=False, prio=None, **kwargs ):
+        """stp: use spanning tree protocol? (default False)
+           prio: optional explicit bridge priority for STP"""
+        self.stp = stp
+        if prio:
+            self.prio = prio
+        else:
+            self.prio = LinuxBridge.nextPrio
+            LinuxBridge.nextPrio += 1
+        Switch.__init__( self, name, **kwargs )
+
+    def connected( self ):
+        "Are we forwarding yet?"
+        if self.stp:
+            return 'forwarding' in self.cmd( 'brctl showstp', self )
+        else:
+            return True
+    
+    def start( self, controllers ):
+        self.cmd( 'ifconfig', self, 'down' )
+        self.cmd( 'brctl delbr', self )
+        self.cmd( 'brctl addbr', self )
+        if self.stp:
+            self.cmd( 'brctl setbridgeprio', self.prio )
+            self.cmd( 'brctl stp', self, 'on' )
+        for i in self.intfList():
+            if self.name in i.name:
+                self.cmd( 'brctl addif', self, i )
+        self.cmd( 'ifconfig', self, 'up' )
+
+    def stop( self ):
+        self.cmd( 'ifconfig', self, 'down' )
+        self.cmd( 'brctl delbr', self )
+
diff --git a/mininet/test/test_hifi.py b/mininet/test/test_hifi.py
index 20ee03167b648f59f7ea94b8f37400ee0d375670..c888e29620a4edfd4aea6468feff43be11c44ba8 100755
--- a/mininet/test/test_hifi.py
+++ b/mininet/test/test_hifi.py
@@ -55,6 +55,9 @@ def assertWithinTolerance(self, measured, expected, tolerance_frac):
         """
         self.assertGreaterEqual( float(measured),
                                  float(expected) * tolerance_frac )
+        self.assertLessEqual( float( measured ),
+                                 float(expected) + (1-tolerance_frac)
+                                 * float( expected ) )
 
     def testCPULimits( self ):
         "Verify topology creation with CPU limits set for both schedulers."
@@ -68,19 +71,20 @@ def testCPULimits( self ):
         mn.start()
         results = mn.runCpuLimitTest( cpu=CPU_FRACTION )
         mn.stop()
-        for cpu in results:
-            self.assertWithinTolerance( cpu, CPU_FRACTION, CPU_TOLERANCE )
+        for pct in results:
+            #divide cpu by 100 to convert from percentage to fraction
+            self.assertWithinTolerance( pct/100, CPU_FRACTION, CPU_TOLERANCE )
 
     def testLinkBandwidth( self ):
         "Verify that link bandwidths are accurate within a bound."
-        BW = 5  # Mbps
+        BW = .5  # Mbps
         BW_TOLERANCE = 0.8  # BW fraction below which test should fail
         # Verify ability to create limited-link topo first;
         lopts = { 'bw': BW, 'use_htb': True }
         # Also verify correctness of limit limitng within a bound.
         mn = Mininet( SingleSwitchOptionsTopo( n=N, lopts=lopts ),
                       link=TCLink, switch=self.switchClass )
-        bw_strs = mn.run( mn.iperf )
+        bw_strs = mn.run( mn.iperf, format='m' )
         for bw_str in bw_strs:
             bw = float( bw_str.split(' ')[0] )
             self.assertWithinTolerance( bw, BW, BW_TOLERANCE )
@@ -91,7 +95,7 @@ def testLinkDelay( self ):
         DELAY_TOLERANCE = 0.8  # Delay fraction below which test should fail
         lopts = { 'delay': '%sms' % DELAY_MS, 'use_htb': True }
         mn = Mininet( SingleSwitchOptionsTopo( n=N, lopts=lopts ),
-                      link=TCLink, switch=self.switchClass )
+                      link=TCLink, switch=self.switchClass, autoStaticArp=True )
         ping_delays = mn.run( mn.pingFull )
         test_outputs = ping_delays[0]
         # Ignore unused variables below
@@ -102,9 +106,10 @@ def testLinkDelay( self ):
         # pylint: enable-msg=W0612
         for rttval in [rttmin, rttavg, rttmax]:
             # Multiply delay by 4 to cover there & back on two links
-            self.assertWithinTolerance( rttval, DELAY_MS * 4.0,
+            self.assertWithinTolerance( rttval, DELAY_MS * 4.0, 
                                         DELAY_TOLERANCE)
 
+
     def testLinkLoss( self ):
         "Verify that we see packet drops with a high configured loss rate."
         LOSS_PERCENT = 99
diff --git a/mininet/test/test_nets.py b/mininet/test/test_nets.py
index 159ba348c46831fe4e48f020f07bbd79d40d4744..330e9a88a6c69e336f95467bf99e2b9bb9b31e69 100755
--- a/mininet/test/test_nets.py
+++ b/mininet/test/test_nets.py
@@ -66,7 +66,7 @@ class testLinearCommon( object ):
 
     def testLinear5( self ):
         "Ping test on a 5-switch topology"
-        mn = Mininet( LinearTopo( k=5 ), self.switchClass, Host, Controller )
+        mn = Mininet( LinearTopo( k=5 ), self.switchClass, Host, Controller, waitConnected=True )
         dropped = mn.run( mn.ping )
         self.assertEqual( dropped, 0 )
 
diff --git a/mininet/topo.py b/mininet/topo.py
index f9c421fbc8f57dc72e0850ae72ebd9cab99ee41c..de5ba8a7a37d63cfd5795aec907f32cfb33420bf 100644
--- a/mininet/topo.py
+++ b/mininet/topo.py
@@ -48,18 +48,25 @@ def __getitem__( self, node ):
 class Topo(object):
     "Data center network representation for structured multi-trees."
 
-    def __init__(self, hopts=None, sopts=None, lopts=None):
-        """Topo object:
+    def __init__(self, *args, **params):
+        """Topo object. 
+           Optional named parameters:
            hinfo: default host options
            sopts: default switch options
-           lopts: default link options"""
+           lopts: default link options
+           calls build()"""
         self.g = MultiGraph()
         self.node_info = {}
         self.link_info = {}  # (src, dst) tuples hash to EdgeInfo objects
-        self.hopts = {} if hopts is None else hopts
-        self.sopts = {} if sopts is None else sopts
-        self.lopts = {} if lopts is None else lopts
+        self.hopts = params.pop( 'hopts', {} )
+        self.sopts = params.pop( 'sopts', {} )
+        self.lopts = params.pop( 'lopts', {} )
         self.ports = {}  # ports[src][dst] is port on src that connects to dst
+        self.build( *args, **params )
+
+    def build( self, *args, **params ):
+        "Override this method to build your topology."
+        pass
 
     def addNode(self, name, **opts):
         """Add Node to graph.
diff --git a/mininet/topolib.py b/mininet/topolib.py
index 63ba36deb3d51e5a246545e7bfe8782ed4a3848e..8e3b3a4b6a33caabebaba7ddcfde5e581ea9197e 100644
--- a/mininet/topolib.py
+++ b/mininet/topolib.py
@@ -34,3 +34,37 @@ def TreeNet( depth=1, fanout=2, **kwargs ):
     "Convenience function for creating tree networks."
     topo = TreeTopo( depth, fanout )
     return Mininet( topo, **kwargs )
+
+
+class TorusTopo( Topo ):
+    """2-D Torus topology
+       WARNING: this topology has LOOPS and WILL NOT WORK
+       with the default controller or any Ethernet bridge
+       without STP turned on! It can be used with STP, e.g.:
+       # mn --topo torus,3,3 --switch lxbr,stp=1 --test pingall"""
+    def __init__( self, x, y, *args, **kwargs ):
+        Topo.__init__( self, *args, **kwargs )
+        if x < 3 or y < 3:
+            raise Exception( 'Please use 3x3 or greater for compatibility '
+                            'with 2.1' )
+        hosts, switches, dpid = {}, {}, 0
+        # Create and wire interior
+        for i in range( 0, x ):
+            for j in range( 0, y ):
+                loc = '%dx%d' % ( i + 1, j + 1 )
+                # dpid cannot be zero for OVS
+                dpid = ( i + 1 ) * 256 + ( j + 1 )
+                switch = switches[ i, j ] = self.addSwitch( 's' + loc, dpid='%016x' % dpid )
+                host = hosts[ i, j ] = self.addHost( 'h' + loc )
+                self.addLink( host, switch )
+        # Connect switches
+        for i in range( 0, x ):
+            for j in range( 0, y ):
+                sw1 = switches[ i, j ]
+                sw2 = switches[ i, ( j + 1 ) % y ]
+                sw3 = switches[ ( i + 1 ) % x, j ]
+                self.addLink( sw1, sw2 )
+                self.addLink( sw1, sw3 )
+
+    
+
diff --git a/util/vm/build.py b/util/vm/build.py
index be809eced8ef4c2982e048ef8526a3cef16ba462..ad454f0ddfbd3df163202cd352ebad1f480a3abc 100755
--- a/util/vm/build.py
+++ b/util/vm/build.py
@@ -89,6 +89,12 @@
     'trusty64server':
     'http://mirrors.kernel.org/ubuntu-releases/14.04/'
     'ubuntu-14.04-server-amd64.iso',
+    'utopic32server':
+    'http://mirrors.kernel.org/ubuntu-releases/14.10/'
+    'ubuntu-14.10-server-i386.iso',
+    'utopic64server':
+    'http://mirrors.kernel.org/ubuntu-releases/14.10/'
+    'ubuntu-14.10-server-amd64.iso',
 }