diff --git a/mininet/net.py b/mininet/net.py
index f995ea47ab7acc81a3d9d354f5ed72b3642d2483..5b16ce0c2e19ed5c0ccc4f9d536fd98d27de0446 100755
--- a/mininet/net.py
+++ b/mininet/net.py
@@ -337,18 +337,18 @@ def addLink( self, node1, node2, port1=None, port2=None,
             paramDict: dictionary of additional link params (optional)
             params: additional link params (optional)
             returns: link object"""
-        mac1 = self.randMac()
-        mac2 = self.randMac()
-        paramDict = {} if paramDict is None else paramDict
-        paramDict.update( params )
         # Ugly: try to ensure that node1 and node2 line up correctly with
-        # other link parameters
-        node1 = self[ paramDict.pop( 'node1', node1.name ) ]
-        node2 = self[ paramDict.pop( 'node2', node2.name ) ]
+        # other link parameters, and allow either nodes or names
+        paramDict = {} if paramDict is None else dict( paramDict )
+        paramDict.update( params )
+        node1 = paramDict.pop( 'node1', node1 )
+        node2 = paramDict.pop( 'node2', node1 )
+        node1 = node1 if type( node1 ) != str else self[ node1 ]
+        node2 = node2 if type( node2 ) != str else self[ node2 ]
         paramDict.setdefault( 'port1', port1 )
         paramDict.setdefault( 'port2', port2 )
-        paramDict.setdefault( 'addr1', mac1 )
-        paramDict.setdefault( 'addr2', mac2 )
+        paramDict.setdefault( 'addr1', self.randMac() )
+        paramDict.setdefault( 'addr2', self.randMac() )
         cls = self.link if cls is None else cls
         link = cls( node1, node2, **paramDict )
         self.links.append( link )
@@ -408,12 +408,10 @@ def buildFromTopo( self, topo=None ):
             info( switchName + ' ' )
 
         info( '\n*** Adding links:\n' )
-        for srcName, dstName in topo.links( sort=True ):
-            src, dst = self.nameToNode[ srcName ], self.nameToNode[ dstName ]
-            params = topo.linkInfo( srcName, dstName )
-            srcPort, dstPort = topo.port( srcName, dstName )
-            self.addLink( src, dst, srcPort, dstPort, paramDict=params )
-            info( '(%s, %s) ' % ( src.name, dst.name ) )
+        for srcName, dstName, params in topo.links(
+                sort=True, withInfo=True ):
+            self.addLink( srcName, dstName, paramDict=params )
+            info( '(%s, %s) ' % ( srcName, dstName ) )
 
         info( '\n' )
 
diff --git a/mininet/topo.py b/mininet/topo.py
index 6650bd2968bb557b72e1f42c30754ba455b7a1dc..a05707eb9eec7a77abcf7e7c5375ab7c31b69b85 100644
--- a/mininet/topo.py
+++ b/mininet/topo.py
@@ -53,22 +53,24 @@ def nodes( self, data=False):
            data: return list of ( node, attrs)"""
         return self.node.items() if data else self.node.keys()
 
-    def edges_iter( self, data=False ):
+    def edges_iter( self, data=False, key=False):
         "Iterator: return graph edges"
         for src, entry in self.edge.iteritems():
             for dst, keys in entry.iteritems():
                 if [ src, dst ] != sorted( [ src, dst ] ):
                     # Skip duplicate edges
                     continue
-                for key, attrs in keys.iteritems():
+                for k, attrs in keys.iteritems():
                     if data:
                         yield( ( src, dst, attrs ) )
+                    elif key:
+                        yield( ( src, dst, k ) )
                     else:
                         yield( ( src, dst ) )
 
-    def edges( self, data=False ):
+    def edges( self, data=False, key=False ):
         "Return list of graph edges"
-        return list( self.edges_iter( data ) )
+        return list( self.edges_iter( data=data, key=key ) )
 
 
     def __getitem__( self, node ):
@@ -88,7 +90,7 @@ def convertTo( self, cls, data=False ):
         return g
 
 
-class Topo(object):
+class Topo( object ):
     "Data center network representation for structured multi-trees."
 
     def __init__( self, *args, **params ):
@@ -146,6 +148,7 @@ def addLink( self, node1, node2, port1=None, port2=None,
             opts = self.lopts
         port1, port2 = self.addPort(node1, node2, port1, port2)
         opts.update( node1=node1, node2=node2, port1=port1, port2=port2 )
+        assert 'node1' in opts
         self.g.add_edge(node1, node2, key, opts )
         return key
 
@@ -172,20 +175,24 @@ def hosts( self, sort=True ):
            returns: list of hosts"""
         return [ n for n in self.nodes( sort ) if not self.isSwitch( n ) ]
 
-    def links( self, sort=True, withKeys=False ):
+    def links( self, sort=True, withInfo=False, withKeys=False ):
         """Return links.
            sort: sort links alphabetically
            withKeys: return key in tuple
            @return links list of ( src, dst [,key ] )"""
         if not sort:
-            return self.g.edges( withKeys )
+            return self.g.edges( data=withInfo, key=withKeys )
         else:
-            if withKeys:
-                links = [ tuple( self.sorted( ( s, d ) ) ) + [ k ]
-                          for s, d, k in self.g.edges( data=True ) ]
+            if withInfo:
+                links = [ tuple( self.sorted( ( s, d ) ) + [ info ] )
+                          for s, d, info in self.g.edges( data=True ) ]
+            elif withKeys:
+                links = [ tuple( self.sorted( ( s, d ) ) + [ key ] )
+                          for s, d, key in self.g.edges( key=True ) ]
             else:
-                links = [ tuple ( self.sorted( e ) ) for e in self.g.edges() ]
-            return sorted( links, key=naturalSeq )
+                links = [ tuple ( self.sorted( e ) )
+                          for e in self.g.edges() ]
+            return self.sorted( links )
 
     # This legacy port management mechanism is clunky and will probably
     # be removed at some point.