From 80be5642743e818d357fae30c820bf88866a4ace Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Mon, 8 Mar 2010 15:32:41 -0800 Subject: [PATCH] Removed underscores for public Node methods. Minor cleanup & comments. --- bin/mnclean | 14 +-- examples/linearbandwidth.py | 47 +++++----- examples/scratchnet.py | 21 +++-- examples/scratchnetuser.py | 15 ++-- examples/sshd.py | 69 ++++++++------- examples/udpbwtest.py | 172 ++++++++++++++++++++---------------- mininet/log.py | 2 +- mininet/net.py | 37 ++++---- mininet/node.py | 6 ++ mininet/topo.py | 22 ++--- mininet/topolib.py | 4 +- mininet/util.py | 2 +- 12 files changed, 223 insertions(+), 188 deletions(-) diff --git a/bin/mnclean b/bin/mnclean index ff041cf..e80c63b 100755 --- a/bin/mnclean +++ b/bin/mnclean @@ -4,12 +4,12 @@ Mininet Cleanup author: Bob Lantz (rlantz@cs.stanford.edu) -Unfortunately, Mininet and OpenFlow don't always clean up -properly after themselves. Until they do (or until cleanup -functionality is integrated into the python code), this -script may be used to get rid of unwanted garbage. It may -also get rid of 'false positives', but hopefully nothing -irreplaceable! +Unfortunately, Mininet and OpenFlow (and the Linux kernel) +don't always clean up properly after themselves. Until they do +(or until cleanup functionality is integrated into the Python +code), this script may be used to get rid of unwanted garbage. +It may also get rid of 'false positives', but hopefully +nothing irreplaceable! """ from subprocess import Popen, PIPE @@ -28,7 +28,7 @@ def cleanup(): zombies = 'controller ofprotocol ofdatapath ping nox_core lt-nox_core ' zombies += 'udpbwtest' # Note: real zombie processes can't actually be killed, since they - # are already ( un )dead. Then again, + # are already (un)dead. Then again, # you can't connect to them either, so they're mostly harmless. sh( 'killall -9 ' + zombies + ' 2> /dev/null' ) diff --git a/examples/linearbandwidth.py b/examples/linearbandwidth.py index 424fc3e..887e0a2 100755 --- a/examples/linearbandwidth.py +++ b/examples/linearbandwidth.py @@ -1,7 +1,7 @@ #!/usr/bin/python """ -Test bandwidth (using iperf) on linear networks of varying size, +Test bandwidth (using iperf) on linear networks of varying size, using both kernel and user datapaths. We construct a network of N hosts and N-1 switches, connected as follows: @@ -9,7 +9,7 @@ We construct a network of N hosts and N-1 switches, connected as follows: h1 <-> sN+1 <-> sN+2 .. sN+N-1 | | | h2 h3 hN - + Note: by default, the reference controller only supports 16 switches, so this test WILL NOT WORK unless you have recompiled your controller to support 100 switches (or more.) @@ -25,9 +25,9 @@ of switches, this example demonstrates: import sys flush = sys.stdout.flush - + from mininet.net import init, Mininet -from mininet.node import Host, KernelSwitch, UserSwitch +from mininet.node import KernelSwitch, UserSwitch from mininet.topo import Topo, Node from mininet.log import lg @@ -35,26 +35,26 @@ class LinearTestTopo( Topo ): "Topology for a string of N hosts and N-1 switches." def __init__( self, N ): - + # Add default members to class. super( LinearTestTopo, self ).__init__() - + # Create switch and host nodes - hosts = range( 1, N+1 ) - switches = range( N+1, N+N ) - for id in hosts: - self._add_node( id, Node( is_switch=False ) ) - for id in switches: - self._add_node( id, Node( is_switch=True ) ) - + hosts = range( 1, N + 1 ) + switches = range( N + 1 , N + N ) + for h in hosts: + self.add_node( h, Node( is_switch=False ) ) + for s in switches: + self.add_node( s, Node( is_switch=True ) ) + # Wire up switches for s in switches[ :-1 ]: - self._add_edge( s, s + 1 ) - + self.add_edge( s, s + 1 ) + # Wire up hosts - self._add_edge( hosts[ 0 ], switches[ 0 ] ) + self.add_edge( hosts[ 0 ], switches[ 0 ] ) for h in hosts[ 1: ]: - self._add_edge( h, h+N-1 ) + self.add_edge( h, h + N - 1 ) # Consider all switches and hosts 'on' self.enable_all() @@ -81,26 +81,25 @@ def linearBandwidthTest( lengths ): src, dst = net.hosts[ 0 ], net.hosts[ n ] print "testing", src.name, "<->", dst.name bandwidth = net.iperf( [ src, dst ] ) - print bandwidth ; flush() + print bandwidth + flush() results[ datapath ] += [ ( n, bandwidth ) ] net.stop() - + for datapath in datapaths: print print "*** Linear network results for", datapath, "datapath:" print - result = results[ datapath ] + result = results[ datapath ] print "SwitchCount\tiperf Results" for switchCount, bandwidth in result: - print switchCount, '\t\t', + print switchCount, '\t\t', print bandwidth[ 0 ], 'server, ', bandwidth[ 1 ], 'client' print print - + if __name__ == '__main__': lg.setLogLevel( 'info' ) init() print "*** Running linearBandwidthTest" linearBandwidthTest( [ 1, 10, 20 ] ) - - diff --git a/examples/scratchnet.py b/examples/scratchnet.py index 43f070d..cbb3269 100755 --- a/examples/scratchnet.py +++ b/examples/scratchnet.py @@ -6,21 +6,20 @@ This is more complicated than using the higher-level classes, but it exposes the configuration details and allows customization. """ -import logging - from mininet.net import init from mininet.node import Node from mininet.util import createLink from mininet.log import lg, info -def scratchNet( cname='controller', cargs='ptcp:'): +def scratchNet( cname='controller', cargs='ptcp:' ): + "Create network from scratch using kernel switch." info( "*** Creating nodes\n" ) controller = Node( 'c0', inNamespace=False ) switch = Node( 's0', inNamespace=False ) h0 = Node( 'h0' ) h1 = Node( 'h1' ) - + info( "*** Creating links\n" ) createLink( node1=h0, port1=0, node2=switch, port2=0 ) createLink( node1=h1, port1=0, node2=switch, port2=1 ) @@ -30,25 +29,25 @@ def scratchNet( cname='controller', cargs='ptcp:'): h1.setIP( h1.intfs[ 0 ], '192.168.123.2', 24 ) info( str( h0 ) + '\n' ) info( str( h1 ) + '\n' ) - + info( "*** Starting network using kernel datapath\n" ) controller.cmd( cname + ' ' + cargs + '&' ) switch.cmd( 'dpctl deldp nl:0' ) switch.cmd( 'dpctl adddp nl:0' ) for intf in switch.intfs.values(): - switch.cmd( 'dpctl addif nl:0 ' + intf ) - switch.cmd( 'ofprotocol nl:0 tcp:localhost &') - + switch.cmd( 'dpctl addif nl:0 ' + intf ) + switch.cmd( 'ofprotocol nl:0 tcp:localhost &' ) + info( "*** Running test\n" ) h0.cmdPrint( 'ping -c1 ' + h1.IP() ) - + info( "*** Stopping network\n" ) - controller.cmd( 'kill %' + cname) + controller.cmd( 'kill %' + cname ) switch.cmd( 'dpctl deldp nl:0' ) switch.cmd( 'kill %ofprotocol' ) switch.deleteIntfs() info( '\n' ) - + if __name__ == '__main__': lg.setLogLevel( 'info' ) info( '*** Scratch network demo (kernel datapath)\n' ) diff --git a/examples/scratchnetuser.py b/examples/scratchnetuser.py index 792017f..1304508 100755 --- a/examples/scratchnetuser.py +++ b/examples/scratchnetuser.py @@ -5,7 +5,7 @@ Build a simple network from scratch, using mininet primitives. This is more complicated than using the higher-level classes, but it exposes the configuration details and allows customization. -This version uses the user datapath. +This version uses the user datapath and an explicit control network. """ from mininet.net import init @@ -14,7 +14,8 @@ from mininet.util import createLink from mininet.log import lg, info def scratchNetUser( cname='controller', cargs='ptcp:' ): - # Create Network + "Create network from scratch using user switch." + # It's not strictly necessary for the controller and switches # to be in separate namespaces. For performance, they probably # should be in the root namespace. However, it's interesting to @@ -32,15 +33,15 @@ def scratchNetUser( cname='controller', cargs='ptcp:' ): info( '*** Configuring control network\n' ) controller.setIP( controller.intfs[ 0 ], '10.0.123.1', 24 ) switch.setIP( switch.intfs[ 0 ], '10.0.123.2', 24 ) - + info( '*** Configuring hosts\n' ) h0.setIP( h0.intfs[ 0 ], '192.168.123.1', 24 ) h1.setIP( h1.intfs[ 0 ], '192.168.123.2', 24 ) - + info( '*** Network state:\n' ) for node in controller, switch, h0, h1: info( str( node ) + '\n' ) - + info( '*** Starting controller and user datapath\n' ) controller.cmd( cname + ' ' + cargs + '&' ) switch.cmd( 'ifconfig lo 127.0.0.1' ) @@ -57,9 +58,9 @@ def scratchNetUser( cname='controller', cargs='ptcp:' ): switch.cmd( 'kill %ofprotocol' ) switch.deleteIntfs() info( '\n' ) - + if __name__ == '__main__': lg.setLogLevel( 'info' ) info( '*** Scratch network demo (user datapath)\n' ) - init() + init() scratchNetUser() diff --git a/examples/sshd.py b/examples/sshd.py index e244b3e..9322684 100755 --- a/examples/sshd.py +++ b/examples/sshd.py @@ -27,45 +27,48 @@ def TreeNet( depth=1, fanout=2, **kwargs ): "Convenience function for creating tree networks." topo = TreeTopo( depth, fanout ) return Mininet( topo, **kwargs ) - + def connectToRootNS( network, switch, ip, prefixLen, routes ): - """Connect hosts to root namespace via switch. Starts network. + """Connect hosts to root namespace via switch. Starts network. network: Mininet() network object switch: switch to connect to root namespace ip: IP address for root namespace node prefixLen: IP address prefix length (e.g. 8, 16, 24) routes: host networks to route to""" - # Create a node in root namespace and link to switch 0 - root = Node( 'root', inNamespace=False ) - port = max( switch.ports.values() ) + 1 - createLink( root, 0, switch, port ) - root.setIP( root.intfs[ 0 ], ip, prefixLen ) - # Start network that now includes link to root namespace - network.start() - intf = root.intfs[ 0 ] - # Add routes from root ns to hosts - for net in routes: - root.cmd( 'route add -net ' + net + ' dev ' + intf ) + # Create a node in root namespace and link to switch 0 + root = Node( 'root', inNamespace=False ) + port = max( switch.ports.values() ) + 1 + createLink( root, 0, switch, port ) + root.setIP( root.intfs[ 0 ], ip, prefixLen ) + # Start network that now includes link to root namespace + network.start() + intf = root.intfs[ 0 ] + # Add routes from root ns to hosts + for route in routes: + root.cmd( 'route add -net ' + route + ' dev ' + intf ) def sshd( network, cmd='/usr/sbin/sshd', opts='-D' ): - "Start a network, connect it to root ns, and run sshd on all hosts." - switch = network.switches[ 0 ] # switch to use - ip = '10.123.123.1' # our IP address on host network - routes = [ '10.0.0.0/8' ] # host networks to route to - connectToRootNS( network, switch, ip, 8, routes ) - for host in network.hosts: host.cmd( cmd + ' ' + opts + '&' ) - print - print "*** Hosts are running sshd at the following addresses:" - print - for host in network.hosts: print host.name, host.IP() - print - print "*** Type 'exit' or control-D to shut down network" - CLI( network ) - for host in network.hosts: host.cmd( 'kill %' + cmd ) - network.stop() - + "Start a network, connect it to root ns, and run sshd on all hosts." + switch = network.switches[ 0 ] # switch to use + ip = '10.123.123.1' # our IP address on host network + routes = [ '10.0.0.0/8' ] # host networks to route to + connectToRootNS( network, switch, ip, 8, routes ) + for host in network.hosts: + host.cmd( cmd + ' ' + opts + '&' ) + print + print "*** Hosts are running sshd at the following addresses:" + print + for host in network.hosts: + print host.name, host.IP() + print + print "*** Type 'exit' or control-D to shut down network" + CLI( network ) + for host in network.hosts: + host.cmd( 'kill %' + cmd ) + network.stop() + if __name__ == '__main__': - lg.setLogLevel( 'info') - init() - network = TreeNet( depth=1, fanout=4, switch=KernelSwitch ) - sshd( network ) + lg.setLogLevel( 'info') + init() + net = TreeNet( depth=1, fanout=4, switch=KernelSwitch ) + sshd( net ) diff --git a/examples/udpbwtest.py b/examples/udpbwtest.py index 6baec85..74dcda5 100755 --- a/examples/udpbwtest.py +++ b/examples/udpbwtest.py @@ -20,99 +20,121 @@ import os import re import select import sys -import time +from time import time flush = sys.stdout.flush -from mininet.log import lg +from mininet.log import lg from mininet.net import init, Mininet -from mininet.node import Host, KernelSwitch +from mininet.node import KernelSwitch from mininet.topolib import TreeTopo from mininet.util import quietRun # Some useful stuff: buffered readline and host monitoring -def readline( host, buffer ): - "Read a line from a host, buffering with buffer." - buffer += host.read( 1024 ) - if '\n' not in buffer: return None, buffer - pos = buffer.find( '\n' ) - line = buffer[ 0 : pos ] - rest = buffer[ pos + 1 :] - return line, rest +def readline( host, buf ): + "Read a line from a host, buffering with buffer." + buf += host.read( 1024 ) + if '\n' not in buffer: + return None, buffer + pos = buf.find( '\n' ) + line = buf[ 0 : pos ] + rest = buf[ pos + 1: ] + return line, rest def monitor( hosts, seconds ): - "Monitor a set of hosts and yield their output." - poller = select.poll() - Node = hosts[ 0 ] # so we can call class method fdToNode - buffers = {} - for host in hosts: - poller.register( host.stdout ) - buffers[ host ] = '' - quitTime = time.time() + seconds - while time.time() < quitTime: - ready = poller.poll() - for fd, event in ready: - host = Node.fdToNode( fd ) - line, buffers[ host ] = readline( host, buffers[ host ] ) - if line: yield host, line - yield None, '' + "Monitor a set of hosts and yield their output." + poller = select.poll() + Node = hosts[ 0 ] # so we can call class method fdToNode + buffers = {} + for host in hosts: + poller.register( host.stdout ) + buffers[ host ] = '' + quitTime = time() + seconds + while time() < quitTime: + ready = poller.poll() + for fd, event in ready: + host = Node.fdToNode( fd ) + if event & select.POLLIN: + line, buffers[ host ] = readline( host, buffers[ host ] ) + if line: + yield host, line + yield None, '' # bwtest support def parsebwtest( line, - r=re.compile( r'(\d+) s: in ([\d\.]+) Mbps, out ([\d\.]+) Mbps' ) ): - match = r.match( line ) - return match.group( 1, 2, 3 ) if match else ( None, None, None ) - + r=re.compile( r'(\d+) s: in ([\d\.]+) Mbps, out ([\d\.]+) Mbps' ) ): + "Parse udpbwtest.c output, returning seconds, inbw, outbw." + match = r.match( line ) + if match: + seconds, inbw, outbw = match.group( 1, 2, 3 ) + return int( seconds ), float( inbw ), float( outbw ) + return None, None, None + def printTotalHeader(): - print - print "time(s)\thosts\ttotal in/out (Mbps)\tavg in/out (Mbps)" + "Print header for bandwidth stats." + print + print "time(s)\thosts\ttotal in/out (Mbps)\tavg in/out (Mbps)" + +# Annoyingly, pylint isn't smart enough to notice +# when an unused variable is an iteration tuple +# pylint: disable-msg=W0612 + +def printTotal( seconds=None, result=None ): + "Compute and print total bandwidth for given results set." + intotal = outtotal = 0.0 + count = len( result ) + for host, inbw, outbw in result: + intotal += inbw + outtotal += outbw + inavg = intotal / count if count > 0 else 0 + outavg = outtotal / count if count > 0 else 0 + print '%d\t%d\t%.2f/%.2f\t\t%.2f/%.2f' % ( seconds, count, + intotal, outtotal, inavg, outavg ) + +# pylint: enable-msg=W0612 + +# Pylint also isn't smart enough to understand iterator.next() +# pylint: disable-msg=E1101 -def printTotal( time=None, result=None ): - intotal = outtotal = 0.0 - count = len( result ) - for host, inbw, outbw in result: - intotal += inbw - outtotal += outbw - inavg = intotal / count if count > 0 else 0 - outavg = outtotal / count if count > 0 else 0 - print '%d\t%d\t%.2f/%.2f\t\t%.2f/%.2f' % ( time, count, intotal, outtotal, - inavg, outavg ) - def udpbwtest( net, seconds ): - "Start up and monitor udpbwtest on each of our hosts." - hosts, switches = net.hosts, net.switches - hostCount = len( hosts ) - print "*** Starting udpbwtest on hosts" - for host in hosts: - ips = [ h.IP() for h in hosts if h != host ] - print host.name, ; flush() - host.cmd( './udpbwtest ' + ' '.join( ips ) + ' &' ) - print - results = {} - print "*** Monitoring hosts" - output = monitor( hosts, seconds ) - while True: - host, line = output.next() - if host is None: break - time, inbw, outbw = parsebwtest( line ) - if time is not None: - time, inbw, outbw = int( time ), float( inbw ), float( outbw ) - result = results.get( time, [] ) + [ ( host, inbw, outbw ) ] - if len( result ) == hostCount: printTotal( time, result ) - results[ time ] = result - print "*** Stopping udpbwtest processes" - # We *really* don't want these things hanging around! - quietRun( 'killall -9 udpbwtest' ) - print - print "*** Results:" - printTotalHeader() - times = sorted( results.keys() ) - for time in times: - printTotal( time - times[ 0 ] , results[ time ] ) - print - + "Start up and monitor udpbwtest on each of our hosts." + hosts = net.hosts + hostCount = len( hosts ) + print "*** Starting udpbwtest on hosts" + for host in hosts: + ips = [ h.IP() for h in hosts if h != host ] + print host.name, + flush() + host.cmd( './udpbwtest ' + ' '.join( ips ) + ' &' ) + print + results = {} + print "*** Monitoring hosts" + output = monitor( hosts, seconds ) + while True: + host, line = output.next() + if host is None: + break + seconds, inbw, outbw = parsebwtest( line ) + if seconds is not None: + result = results.get( seconds, [] ) + [ ( host, inbw, outbw ) ] + if len( result ) == hostCount: + printTotal( seconds, result ) + results[ seconds ] = result + print "*** Stopping udpbwtest processes" + # We *really* don't want these things hanging around! + quietRun( 'killall -9 udpbwtest' ) + print + print "*** Results:" + printTotalHeader() + times = sorted( results.keys() ) + for t in times: + printTotal( t - t[ 0 ] , results[ t ] ) + print + +# pylint: enable-msg=E1101 + if __name__ == '__main__': lg.setLogLevel( 'info' ) if not os.path.exists( './udpbwtest' ): diff --git a/mininet/log.py b/mininet/log.py index a8e53a8..f8ed653 100644 --- a/mininet/log.py +++ b/mininet/log.py @@ -133,7 +133,7 @@ def makeListCompatible( fn ): newfn( 'a', 1, 'b' )""" def newfn( *args ): - "Generated function." + "Generated function. Closure-ish." if len( args ) == 1: return fn( *args ) args = ' '.join( [ str( arg ) for arg in args ] ) diff --git a/mininet/net.py b/mininet/net.py index a454b75..47b0f6c 100755 --- a/mininet/net.py +++ b/mininet/net.py @@ -49,27 +49,34 @@ which interfaces belong to which node. The basic naming scheme is as follows: - Host nodes are named h0-hN - Switch nodes are named s0-sN + Host nodes are named h1-hN + Switch nodes are named s1-sN Controller nodes are named c0-cN Interfaces are named {nodename}-eth0 .. {nodename}-ethN +Note: If the network topology is created using mininet.topo, then +node numbers are unique among hosts and switches (e.g. we have +h1..hN and SN..SN+M) and also correspond to their default IP addresses +of 10.x.y.z/8 where x.y.z is the base-256 representation of N for +hN. This mapping allows easy determination of a node's IP +address from its name, e.g. h1 -> 10.0.0.1, h257 -> 10.0.1.1. + Currently we wrap the entire network in a 'mininet' object, which constructs a simulated network based on a network topology created -using a topology object (e.g. LinearTopo) from topo.py and a Controller -node which the switches will connect to. Several -configuration options are provided for functions such as +using a topology object (e.g. LinearTopo) from mininet.topo or +mininet.topolib, and a Controller which the switches will connect +to. Several configuration options are provided for functions such as automatically setting MAC addresses, populating the ARP table, or even running a set of xterms to allow direct interaction with nodes. -After the mininet is created, it can be started using start(), and a variety -of useful tasks maybe performed, including basic connectivity and -bandwidth tests and running the mininet CLI. +After the network is created, it can be started using start(), and a +variety of useful tasks maybe performed, including basic connectivity +and bandwidth tests and running the mininet CLI. Once the network is up and running, test code can easily get access -to host and switch objects, which can then be used -for arbitrary experiments, typically involving running a series of -commands on the hosts. +to host and switch objects which can then be used for arbitrary +experiments, typically involving running a series of commands on the +hosts. After all desired tests or activities have been completed, the stop() method may be called to shut down the network. @@ -187,10 +194,8 @@ class Mininet( object ): # # Notes: # - # 1. If the controller and switches are in the same ( e.g. root ) + # 1. If the controller and switches are in the same (e.g. root) # namespace, they can just use the loopback connection. - # We may wish to do this for the user datapath as well as the - # kernel datapath. # # 2. If we can get unix domain sockets to work, we can use them # instead of an explicit control network. @@ -244,7 +249,7 @@ class Mininet( object ): exit( 1 ) info( '\n' ) - def _configHosts( self ): + def configHosts( self ): "Configure a set of hosts." # params were: hosts, ips for host in self.hosts: @@ -294,7 +299,7 @@ class Mininet( object ): self._configureControlNetwork() info( '*** Configuring hosts\n' ) - self._configHosts() + self.configHosts() if self.xterms: self.startXterms() diff --git a/mininet/node.py b/mininet/node.py index c6a8879..99fcdfc 100644 --- a/mininet/node.py +++ b/mininet/node.py @@ -33,6 +33,12 @@ RemoteController: a remote controller node, which may use any arbitrary OpenFlow-compatible controller, and which is not created or managed by mininet. +Future enhancements: + +- Possibly make Node, Switch and Controller more abstract so that + they can be used for both local and remote nodes + +- Create proxy objects for remote nodes (Mininet: Cluster Edition) """ import os diff --git a/mininet/topo.py b/mininet/topo.py index 3ff9cb8..49f1604 100644 --- a/mininet/topo.py +++ b/mininet/topo.py @@ -98,7 +98,7 @@ class Topo(object): self.ports = {} # ports[src][dst] is port on src that connects to dst self.id_gen = NodeID # class used to generate dpid - def _add_node(self, dpid, node): + def add_node(self, dpid, node): '''Add Node to graph. @param dpid dpid @@ -107,7 +107,7 @@ class Topo(object): self.g.add_node(dpid) self.node_info[dpid] = node - def _add_edge(self, src, dst, edge = None): + def add_edge(self, src, dst, edge = None): '''Add edge (Node, Node) to graph. @param src src dpid @@ -119,9 +119,9 @@ class Topo(object): if not edge: edge = Edge() self.edge_info[(src, dst)] = edge - self._add_port(src, dst) + self.add_port(src, dst) - def _add_port(self, src, dst): + def add_port(self, src, dst): '''Generate port mapping for new edge. @param src source switch DPID @@ -329,11 +329,11 @@ class SingleSwitchTopo(Topo): self.k = k - self._add_node(1, Node()) + self.add_node(1, Node()) hosts = range(2, k + 2) for h in hosts: - self._add_node(h, Node(is_switch = False)) - self._add_edge(h, 1, Edge()) + self.add_node(h, Node(is_switch = False)) + self.add_edge(h, 1, Edge()) if enable_all: self.enable_all() @@ -388,12 +388,12 @@ class LinearTopo(Topo): switches = range(1, k + 1) for s in switches: h = s + k - self._add_node(s, Node()) - self._add_node(h, Node(is_switch = False)) - self._add_edge(s, h, Edge()) + self.add_node(s, Node()) + self.add_node(h, Node(is_switch = False)) + self.add_edge(s, h, Edge()) for s in switches: if s != k: - self._add_edge(s, s + 1, Edge()) + self.add_edge(s, s + 1, Edge()) if enable_all: self.enable_all() diff --git a/mininet/topolib.py b/mininet/topolib.py index ad01267..098556f 100644 --- a/mininet/topolib.py +++ b/mininet/topolib.py @@ -20,11 +20,11 @@ class TreeTopo( Topo ): returns: last node added""" me = n isSwitch = depth > 0 - self._add_node( me, Node( is_switch=isSwitch ) ) + self.add_node( me, Node( is_switch=isSwitch ) ) if isSwitch: for i in range( 0, fanout ): child = n + 1 - self._add_edge( me, child ) + self.add_edge( me, child ) n = self.addTree( child, depth-1, fanout ) return n diff --git a/mininet/util.py b/mininet/util.py index 3bec7f5..366e653 100644 --- a/mininet/util.py +++ b/mininet/util.py @@ -141,7 +141,7 @@ def macColonHex( mac ): return _colonHex( mac, 6 ) def ipStr( ip ): - """Generate IP address string + """Generate IP address string from an unsigned int ip: unsigned int of form x << 16 | y << 8 | z returns: ip address string 10.x.y.z """ hi = ( ip & 0xff0000 ) >> 16