Revision 80be5642

View differences:

bin/mnclean
4 4
Mininet Cleanup
5 5
author: Bob Lantz (rlantz@cs.stanford.edu)
6 6

  
7
Unfortunately, Mininet and OpenFlow don't always clean up
8
properly after themselves. Until they do (or until cleanup
9
functionality is integrated into the python code), this
10
script may be used to get rid of unwanted garbage. It may
11
also get rid of 'false positives', but hopefully nothing
12
irreplaceable!
7
Unfortunately, Mininet and OpenFlow (and the Linux kernel)
8
don't always clean up properly after themselves. Until they do
9
(or until cleanup functionality is integrated into the Python
10
code), this script may be used to get rid of unwanted garbage.
11
It may also get rid of 'false positives', but hopefully
12
nothing irreplaceable!
13 13
"""
14 14

  
15 15
from subprocess import Popen, PIPE
......
28 28
    zombies = 'controller ofprotocol ofdatapath ping nox_core lt-nox_core '
29 29
    zombies += 'udpbwtest'
30 30
    # Note: real zombie processes can't actually be killed, since they
31
    # are already ( un )dead. Then again,
31
    # are already (un)dead. Then again,
32 32
    # you can't connect to them either, so they're mostly harmless.
33 33
    sh( 'killall -9 ' + zombies + ' 2> /dev/null' )
34 34

  
examples/linearbandwidth.py
1 1
#!/usr/bin/python
2 2

  
3 3
"""
4
Test bandwidth (using iperf) on linear networks of varying size, 
4
Test bandwidth (using iperf) on linear networks of varying size,
5 5
using both kernel and user datapaths.
6 6

  
7 7
We construct a network of N hosts and N-1 switches, connected as follows:
......
9 9
h1 <-> sN+1 <-> sN+2 .. sN+N-1
10 10
       |        |       |
11 11
       h2       h3      hN
12
        
12

  
13 13
Note: by default, the reference controller only supports 16
14 14
switches, so this test WILL NOT WORK unless you have recompiled
15 15
your controller to support 100 switches (or more.)
......
25 25

  
26 26
import sys
27 27
flush = sys.stdout.flush
28
   
28

  
29 29
from mininet.net import init, Mininet
30
from mininet.node import Host, KernelSwitch, UserSwitch
30
from mininet.node import KernelSwitch, UserSwitch
31 31
from mininet.topo import Topo, Node
32 32
from mininet.log import lg
33 33

  
......
35 35
    "Topology for a string of N hosts and N-1 switches."
36 36

  
37 37
    def __init__( self, N ):
38
    
38

  
39 39
        # Add default members to class.
40 40
        super( LinearTestTopo, self ).__init__()
41
        
41

  
42 42
        # Create switch and host nodes
43
        hosts = range( 1, N+1 )
44
        switches = range( N+1, N+N )
45
        for id in hosts:
46
            self._add_node( id, Node( is_switch=False ) )
47
        for id in switches:
48
            self._add_node( id, Node( is_switch=True ) )
49
        
43
        hosts = range( 1, N + 1 )
44
        switches = range( N + 1 , N + N )
45
        for h in hosts:
46
            self.add_node( h, Node( is_switch=False ) )
47
        for s in switches:
48
            self.add_node( s, Node( is_switch=True ) )
49

  
50 50
        # Wire up switches
51 51
        for s in switches[ :-1 ]:
52
            self._add_edge( s, s + 1 )
53
        
52
            self.add_edge( s, s + 1 )
53

  
54 54
        # Wire up hosts
55
        self._add_edge( hosts[ 0 ], switches[ 0 ] )
55
        self.add_edge( hosts[ 0 ], switches[ 0 ] )
56 56
        for h in hosts[ 1: ]:
57
            self._add_edge( h, h+N-1 )
57
            self.add_edge( h, h + N - 1 )
58 58

  
59 59
        # Consider all switches and hosts 'on'
60 60
        self.enable_all()
......
81 81
            src, dst = net.hosts[ 0 ], net.hosts[ n ]
82 82
            print "testing", src.name, "<->", dst.name
83 83
            bandwidth = net.iperf( [ src, dst ] )
84
            print bandwidth ; flush()
84
            print bandwidth
85
            flush()
85 86
            results[ datapath ] += [ ( n, bandwidth ) ]
86 87
        net.stop()
87
      
88

  
88 89
    for datapath in datapaths:
89 90
        print
90 91
        print "*** Linear network results for", datapath, "datapath:"
91 92
        print
92
        result = results[ datapath ]  
93
        result = results[ datapath ]
93 94
        print "SwitchCount\tiperf Results"
94 95
        for switchCount, bandwidth in result:
95
            print switchCount, '\t\t', 
96
            print switchCount, '\t\t',
96 97
            print bandwidth[ 0 ], 'server, ', bandwidth[ 1 ], 'client'
97 98
        print
98 99
    print
99
      
100

  
100 101
if __name__ == '__main__':
101 102
    lg.setLogLevel( 'info' )
102 103
    init()
103 104
    print "*** Running linearBandwidthTest"
104 105
    linearBandwidthTest( [ 1, 10, 20  ]  )
105

  
106
   
examples/scratchnet.py
6 6
but it exposes the configuration details and allows customization.
7 7
"""
8 8

  
9
import logging
10

  
11 9
from mininet.net import init
12 10
from mininet.node import Node
13 11
from mininet.util import createLink
14 12
from mininet.log import lg, info
15 13

  
16
def scratchNet( cname='controller', cargs='ptcp:'):
14
def scratchNet( cname='controller', cargs='ptcp:' ):
15
    "Create network from scratch using kernel switch."
17 16

  
18 17
    info( "*** Creating nodes\n" )
19 18
    controller = Node( 'c0', inNamespace=False )
20 19
    switch = Node( 's0', inNamespace=False )
21 20
    h0 = Node( 'h0' )
22 21
    h1 = Node( 'h1' )
23
    
22

  
24 23
    info( "*** Creating links\n" )
25 24
    createLink( node1=h0, port1=0, node2=switch, port2=0 )
26 25
    createLink( node1=h1, port1=0, node2=switch, port2=1 )
......
30 29
    h1.setIP( h1.intfs[ 0 ], '192.168.123.2', 24 )
31 30
    info( str( h0 ) + '\n' )
32 31
    info( str( h1 ) + '\n' )
33
    
32

  
34 33
    info( "*** Starting network using kernel datapath\n" )
35 34
    controller.cmd( cname + ' ' + cargs + '&' )
36 35
    switch.cmd( 'dpctl deldp nl:0' )
37 36
    switch.cmd( 'dpctl adddp nl:0' )
38 37
    for intf in switch.intfs.values():
39
      switch.cmd( 'dpctl addif nl:0 ' + intf )
40
    switch.cmd( 'ofprotocol nl:0 tcp:localhost &')
41
    
38
        switch.cmd( 'dpctl addif nl:0 ' + intf )
39
    switch.cmd( 'ofprotocol nl:0 tcp:localhost &' )
40

  
42 41
    info( "*** Running test\n" )
43 42
    h0.cmdPrint( 'ping -c1 ' + h1.IP() )
44
    
43

  
45 44
    info( "*** Stopping network\n" )
46
    controller.cmd( 'kill %' + cname)
45
    controller.cmd( 'kill %' + cname )
47 46
    switch.cmd( 'dpctl deldp nl:0' )
48 47
    switch.cmd( 'kill %ofprotocol' )
49 48
    switch.deleteIntfs()
50 49
    info( '\n' )
51
    
50

  
52 51
if __name__ == '__main__':
53 52
    lg.setLogLevel( 'info' )
54 53
    info( '*** Scratch network demo (kernel datapath)\n' )
examples/scratchnetuser.py
5 5
This is more complicated than using the higher-level classes,
6 6
but it exposes the configuration details and allows customization.
7 7

  
8
This version uses the user datapath.
8
This version uses the user datapath and an explicit control network.
9 9
"""
10 10

  
11 11
from mininet.net import init
......
14 14
from mininet.log import lg, info
15 15

  
16 16
def scratchNetUser( cname='controller', cargs='ptcp:' ):
17
    # Create Network
17
    "Create network from scratch using user switch."
18

  
18 19
    # It's not strictly necessary for the controller and switches
19 20
    # to be in separate namespaces. For performance, they probably
20 21
    # should be in the root namespace. However, it's interesting to
......
32 33
    info( '*** Configuring control network\n' )
33 34
    controller.setIP( controller.intfs[ 0 ], '10.0.123.1', 24 )
34 35
    switch.setIP( switch.intfs[ 0 ], '10.0.123.2', 24 )
35
    
36

  
36 37
    info( '*** Configuring hosts\n' )
37 38
    h0.setIP( h0.intfs[ 0 ], '192.168.123.1', 24 )
38 39
    h1.setIP( h1.intfs[ 0 ], '192.168.123.2', 24 )
39
    
40

  
40 41
    info( '*** Network state:\n' )
41 42
    for node in controller, switch, h0, h1:
42 43
        info( str( node ) + '\n' )
43
        
44

  
44 45
    info( '*** Starting controller and user datapath\n' )
45 46
    controller.cmd( cname + ' ' + cargs + '&' )
46 47
    switch.cmd( 'ifconfig lo 127.0.0.1' )
......
57 58
    switch.cmd( 'kill %ofprotocol' )
58 59
    switch.deleteIntfs()
59 60
    info( '\n' )
60
        
61

  
61 62
if __name__ == '__main__':
62 63
    lg.setLogLevel( 'info' )
63 64
    info( '*** Scratch network demo (user datapath)\n' )
64
    init()   
65
    init()
65 66
    scratchNetUser()
examples/sshd.py
27 27
    "Convenience function for creating tree networks."
28 28
    topo = TreeTopo( depth, fanout )
29 29
    return Mininet( topo, **kwargs )
30
   
30

  
31 31
def connectToRootNS( network, switch, ip, prefixLen, routes ):
32
   """Connect hosts to root namespace via switch. Starts network.
32
    """Connect hosts to root namespace via switch. Starts network.
33 33
      network: Mininet() network object
34 34
      switch: switch to connect to root namespace
35 35
      ip: IP address for root namespace node
36 36
      prefixLen: IP address prefix length (e.g. 8, 16, 24)
37 37
      routes: host networks to route to"""
38
   # Create a node in root namespace and link to switch 0
39
   root = Node( 'root', inNamespace=False )
40
   port = max( switch.ports.values() ) + 1
41
   createLink( root, 0, switch, port )
42
   root.setIP( root.intfs[ 0 ], ip, prefixLen )
43
   # Start network that now includes link to root namespace
44
   network.start()
45
   intf = root.intfs[ 0 ]
46
   # Add routes from root ns to hosts
47
   for net in routes:
48
      root.cmd( 'route add -net ' + net + ' dev ' + intf )
38
    # Create a node in root namespace and link to switch 0
39
    root = Node( 'root', inNamespace=False )
40
    port = max( switch.ports.values() ) + 1
41
    createLink( root, 0, switch, port )
42
    root.setIP( root.intfs[ 0 ], ip, prefixLen )
43
    # Start network that now includes link to root namespace
44
    network.start()
45
    intf = root.intfs[ 0 ]
46
    # Add routes from root ns to hosts
47
    for route in routes:
48
        root.cmd( 'route add -net ' + route + ' dev ' + intf )
49 49

  
50 50
def sshd( network, cmd='/usr/sbin/sshd', opts='-D' ):
51
   "Start a network, connect it to root ns, and run sshd on all hosts."
52
   switch = network.switches[ 0 ] # switch to use
53
   ip = '10.123.123.1' # our IP address on host network
54
   routes = [ '10.0.0.0/8' ] # host networks to route to
55
   connectToRootNS( network, switch, ip, 8, routes )
56
   for host in network.hosts: host.cmd( cmd + ' ' + opts + '&' )
57
   print
58
   print "*** Hosts are running sshd at the following addresses:"
59
   print
60
   for host in network.hosts: print host.name, host.IP()
61
   print
62
   print "*** Type 'exit' or control-D to shut down network"
63
   CLI( network )
64
   for host in network.hosts: host.cmd( 'kill %' + cmd )
65
   network.stop()
66
   
51
    "Start a network, connect it to root ns, and run sshd on all hosts."
52
    switch = network.switches[ 0 ] # switch to use
53
    ip = '10.123.123.1' # our IP address on host network
54
    routes = [ '10.0.0.0/8' ] # host networks to route to
55
    connectToRootNS( network, switch, ip, 8, routes )
56
    for host in network.hosts:
57
        host.cmd( cmd + ' ' + opts + '&' )
58
    print
59
    print "*** Hosts are running sshd at the following addresses:"
60
    print
61
    for host in network.hosts:
62
        print host.name, host.IP()
63
    print
64
    print "*** Type 'exit' or control-D to shut down network"
65
    CLI( network )
66
    for host in network.hosts:
67
        host.cmd( 'kill %' + cmd )
68
    network.stop()
69

  
67 70
if __name__ == '__main__':
68
   lg.setLogLevel( 'info')
69
   init()
70
   network = TreeNet( depth=1, fanout=4, switch=KernelSwitch )
71
   sshd( network )
71
    lg.setLogLevel( 'info')
72
    init()
73
    net = TreeNet( depth=1, fanout=4, switch=KernelSwitch )
74
    sshd( net )
examples/udpbwtest.py
20 20
import re
21 21
import select
22 22
import sys
23
import time
23
from time import time
24 24

  
25 25
flush = sys.stdout.flush
26 26

  
27
from mininet.log import lg   
27
from mininet.log import lg
28 28
from mininet.net import init, Mininet
29
from mininet.node import Host, KernelSwitch
29
from mininet.node import KernelSwitch
30 30
from mininet.topolib import TreeTopo
31 31
from mininet.util import quietRun
32 32

  
33 33
# Some useful stuff: buffered readline and host monitoring
34 34

  
35
def readline( host, buffer ):
36
   "Read a line from a host, buffering with buffer."
37
   buffer += host.read( 1024 )
38
   if '\n' not in buffer: return None, buffer
39
   pos = buffer.find( '\n' )
40
   line = buffer[ 0 : pos ]
41
   rest = buffer[ pos + 1 :]
42
   return line, rest
35
def readline( host, buf ):
36
    "Read a line from a host, buffering with buffer."
37
    buf += host.read( 1024 )
38
    if '\n' not in buffer:
39
        return None, buffer
40
    pos = buf.find( '\n' )
41
    line = buf[ 0 : pos ]
42
    rest = buf[ pos + 1: ]
43
    return line, rest
43 44

  
44 45
def monitor( hosts, seconds ):
45
   "Monitor a set of hosts and yield their output."
46
   poller = select.poll()
47
   Node = hosts[ 0 ] # so we can call class method fdToNode
48
   buffers = {}
49
   for host in hosts:
50
      poller.register( host.stdout )
51
      buffers[ host ] = ''
52
   quitTime = time.time() + seconds
53
   while time.time() < quitTime:
54
      ready = poller.poll()
55
      for fd, event in ready: 
56
         host = Node.fdToNode( fd )
57
         line, buffers[ host ] = readline( host, buffers[ host ] )
58
         if line: yield host, line
59
   yield None, ''
46
    "Monitor a set of hosts and yield their output."
47
    poller = select.poll()
48
    Node = hosts[ 0 ] # so we can call class method fdToNode
49
    buffers = {}
50
    for host in hosts:
51
        poller.register( host.stdout )
52
        buffers[ host ] = ''
53
    quitTime = time() + seconds
54
    while time() < quitTime:
55
        ready = poller.poll()
56
        for fd, event in ready:
57
            host = Node.fdToNode( fd )
58
            if event & select.POLLIN:
59
                line, buffers[ host ] = readline( host, buffers[ host ] )
60
                if line:
61
                    yield host, line
62
    yield None, ''
60 63

  
61 64
# bwtest support
62 65

  
63 66
def parsebwtest( line,
64
   r=re.compile( r'(\d+) s: in ([\d\.]+) Mbps, out ([\d\.]+) Mbps' ) ):
65
   match = r.match( line )
66
   return match.group( 1, 2, 3 ) if match else ( None, None, None )
67
   
67
    r=re.compile( r'(\d+) s: in ([\d\.]+) Mbps, out ([\d\.]+) Mbps' ) ):
68
    "Parse udpbwtest.c output, returning seconds, inbw, outbw."
69
    match = r.match( line )
70
    if match:
71
        seconds, inbw, outbw = match.group( 1, 2, 3 )
72
        return int( seconds ), float( inbw ), float( outbw )
73
    return None, None, None
74

  
68 75
def printTotalHeader():
69
   print
70
   print "time(s)\thosts\ttotal in/out (Mbps)\tavg in/out (Mbps)"
71

  
72
def printTotal( time=None, result=None ):
73
   intotal = outtotal = 0.0
74
   count = len( result )
75
   for host, inbw, outbw in result:
76
      intotal += inbw
77
      outtotal += outbw
78
   inavg = intotal / count if count > 0 else 0
79
   outavg = outtotal / count if count > 0 else 0   
80
   print '%d\t%d\t%.2f/%.2f\t\t%.2f/%.2f' % ( time, count, intotal, outtotal,
81
      inavg, outavg )
82
   
76
    "Print header for bandwidth stats."
77
    print
78
    print "time(s)\thosts\ttotal in/out (Mbps)\tavg in/out (Mbps)"
79

  
80
# Annoyingly, pylint isn't smart enough to notice
81
# when an unused variable is an iteration tuple
82
# pylint: disable-msg=W0612
83

  
84
def printTotal( seconds=None, result=None ):
85
    "Compute and print total bandwidth for given results set."
86
    intotal = outtotal = 0.0
87
    count = len( result )
88
    for host, inbw, outbw in result:
89
        intotal += inbw
90
        outtotal += outbw
91
    inavg = intotal / count if count > 0 else 0
92
    outavg = outtotal / count if count > 0 else 0
93
    print '%d\t%d\t%.2f/%.2f\t\t%.2f/%.2f' % ( seconds, count,
94
        intotal, outtotal, inavg, outavg )
95

  
96
# pylint: enable-msg=W0612
97

  
98
# Pylint also isn't smart enough to understand iterator.next()
99
# pylint: disable-msg=E1101
100

  
83 101
def udpbwtest( net, seconds ):
84
   "Start up and monitor udpbwtest on each of our hosts."
85
   hosts, switches = net.hosts, net.switches
86
   hostCount = len( hosts )
87
   print "*** Starting udpbwtest on hosts"
88
   for host in hosts: 
89
      ips = [ h.IP() for h in hosts if h != host ]
90
      print host.name, ; flush()
91
      host.cmd( './udpbwtest ' + ' '.join( ips ) + ' &' )
92
   print
93
   results = {}
94
   print "*** Monitoring hosts"
95
   output = monitor( hosts, seconds )
96
   while True:
97
      host, line = output.next()
98
      if host is None: break
99
      time, inbw, outbw = parsebwtest( line )
100
      if time is not None:
101
         time, inbw, outbw = int( time ), float( inbw ), float( outbw )
102
         result = results.get( time, [] ) + [ ( host, inbw, outbw ) ]
103
         if len( result ) == hostCount: printTotal( time, result )
104
         results[ time ] = result
105
   print "*** Stopping udpbwtest processes"
106
   # We *really* don't want these things hanging around!
107
   quietRun( 'killall -9 udpbwtest' )
108
   print 
109
   print "*** Results:"
110
   printTotalHeader()
111
   times = sorted( results.keys() )
112
   for time in times:
113
      printTotal( time - times[ 0 ] , results[ time ] )
114
   print 
115
     
102
    "Start up and monitor udpbwtest on each of our hosts."
103
    hosts = net.hosts
104
    hostCount = len( hosts )
105
    print "*** Starting udpbwtest on hosts"
106
    for host in hosts:
107
        ips = [ h.IP() for h in hosts if h != host ]
108
        print host.name,
109
        flush()
110
        host.cmd( './udpbwtest ' + ' '.join( ips ) + ' &' )
111
    print
112
    results = {}
113
    print "*** Monitoring hosts"
114
    output = monitor( hosts, seconds )
115
    while True:
116
        host, line = output.next()
117
        if host is None:
118
            break
119
        seconds, inbw, outbw = parsebwtest( line )
120
        if seconds is not None:
121
            result = results.get( seconds, [] ) + [ ( host, inbw, outbw ) ]
122
            if len( result ) == hostCount:
123
                printTotal( seconds, result )
124
            results[ seconds ] = result
125
    print "*** Stopping udpbwtest processes"
126
    # We *really* don't want these things hanging around!
127
    quietRun( 'killall -9 udpbwtest' )
128
    print
129
    print "*** Results:"
130
    printTotalHeader()
131
    times = sorted( results.keys() )
132
    for t in times:
133
        printTotal( t - t[ 0 ] , results[ t ] )
134
    print
135

  
136
# pylint: enable-msg=E1101
137

  
116 138
if __name__ == '__main__':
117 139
    lg.setLogLevel( 'info' )
118 140
    if not os.path.exists( './udpbwtest' ):
mininet/log.py
133 133
       newfn( 'a', 1, 'b' )"""
134 134

  
135 135
    def newfn( *args ):
136
        "Generated function."
136
        "Generated function. Closure-ish."
137 137
        if len( args ) == 1:
138 138
            return fn( *args )
139 139
        args = ' '.join( [ str( arg ) for arg in args ] )
mininet/net.py
49 49

  
50 50
The basic naming scheme is as follows:
51 51

  
52
    Host nodes are named h0-hN
53
    Switch nodes are named s0-sN
52
    Host nodes are named h1-hN
53
    Switch nodes are named s1-sN
54 54
    Controller nodes are named c0-cN
55 55
    Interfaces are named {nodename}-eth0 .. {nodename}-ethN
56 56

  
57
Note: If the network topology is created using mininet.topo, then
58
node numbers are unique among hosts and switches (e.g. we have
59
h1..hN and SN..SN+M) and also correspond to their default IP addresses
60
of 10.x.y.z/8 where x.y.z is the base-256 representation of N for
61
hN. This mapping allows easy determination of a node's IP
62
address from its name, e.g. h1 -> 10.0.0.1, h257 -> 10.0.1.1.
63

  
57 64
Currently we wrap the entire network in a 'mininet' object, which
58 65
constructs a simulated network based on a network topology created
59
using a topology object (e.g. LinearTopo) from topo.py and a Controller
60
node which the switches will connect to.  Several
61
configuration options are provided for functions such as
66
using a topology object (e.g. LinearTopo) from mininet.topo or
67
mininet.topolib, and a Controller which the switches will connect
68
to. Several configuration options are provided for functions such as
62 69
automatically setting MAC addresses, populating the ARP table, or
63 70
even running a set of xterms to allow direct interaction with nodes.
64 71

  
65
After the mininet is created, it can be started using start(), and a variety
66
of useful tasks maybe performed, including basic connectivity and
67
bandwidth tests and running the mininet CLI.
72
After the network is created, it can be started using start(), and a
73
variety of useful tasks maybe performed, including basic connectivity
74
and bandwidth tests and running the mininet CLI.
68 75

  
69 76
Once the network is up and running, test code can easily get access
70
to host and switch objects, which can then be used
71
for arbitrary experiments, typically involving running a series of
72
commands on the hosts.
77
to host and switch objects which can then be used for arbitrary
78
experiments, typically involving running a series of commands on the
79
hosts.
73 80

  
74 81
After all desired tests or activities have been completed, the stop()
75 82
method may be called to shut down the network.
......
187 194
    #
188 195
    # Notes:
189 196
    #
190
    # 1. If the controller and switches are in the same ( e.g. root )
197
    # 1. If the controller and switches are in the same (e.g. root)
191 198
    #    namespace, they can just use the loopback connection.
192
    #    We may wish to do this for the user datapath as well as the
193
    #    kernel datapath.
194 199
    #
195 200
    # 2. If we can get unix domain sockets to work, we can use them
196 201
    #    instead of an explicit control network.
......
244 249
                exit( 1 )
245 250
        info( '\n' )
246 251

  
247
    def _configHosts( self ):
252
    def configHosts( self ):
248 253
        "Configure a set of hosts."
249 254
        # params were: hosts, ips
250 255
        for host in self.hosts:
......
294 299
            self._configureControlNetwork()
295 300

  
296 301
        info( '*** Configuring hosts\n' )
297
        self._configHosts()
302
        self.configHosts()
298 303

  
299 304
        if self.xterms:
300 305
            self.startXterms()
mininet/node.py
33 33
    arbitrary OpenFlow-compatible controller, and which is not
34 34
    created or managed by mininet.
35 35

  
36
Future enhancements:
37

  
38
- Possibly make Node, Switch and Controller more abstract so that
39
  they can be used for both local and remote nodes
40

  
41
- Create proxy objects for remote nodes (Mininet: Cluster Edition)
36 42
"""
37 43

  
38 44
import os
mininet/topo.py
98 98
        self.ports = {} # ports[src][dst] is port on src that connects to dst
99 99
        self.id_gen = NodeID # class used to generate dpid
100 100

  
101
    def _add_node(self, dpid, node):
101
    def add_node(self, dpid, node):
102 102
        '''Add Node to graph.
103 103

  
104 104
        @param dpid dpid
......
107 107
        self.g.add_node(dpid)
108 108
        self.node_info[dpid] = node
109 109

  
110
    def _add_edge(self, src, dst, edge = None):
110
    def add_edge(self, src, dst, edge = None):
111 111
        '''Add edge (Node, Node) to graph.
112 112

  
113 113
        @param src src dpid
......
119 119
        if not edge:
120 120
            edge = Edge()
121 121
        self.edge_info[(src, dst)] = edge
122
        self._add_port(src, dst)
122
        self.add_port(src, dst)
123 123

  
124
    def _add_port(self, src, dst):
124
    def add_port(self, src, dst):
125 125
        '''Generate port mapping for new edge.
126 126

  
127 127
        @param src source switch DPID
......
329 329

  
330 330
        self.k = k
331 331

  
332
        self._add_node(1, Node())
332
        self.add_node(1, Node())
333 333
        hosts = range(2, k + 2)
334 334
        for h in hosts:
335
            self._add_node(h, Node(is_switch = False))
336
            self._add_edge(h, 1, Edge())
335
            self.add_node(h, Node(is_switch = False))
336
            self.add_edge(h, 1, Edge())
337 337

  
338 338
        if enable_all:
339 339
            self.enable_all()
......
388 388
        switches = range(1, k + 1)
389 389
        for s in switches:
390 390
            h = s + k
391
            self._add_node(s, Node())
392
            self._add_node(h, Node(is_switch = False))
393
            self._add_edge(s, h, Edge())
391
            self.add_node(s, Node())
392
            self.add_node(h, Node(is_switch = False))
393
            self.add_edge(s, h, Edge())
394 394
        for s in switches:
395 395
            if s != k:
396
                self._add_edge(s, s + 1, Edge())
396
                self.add_edge(s, s + 1, Edge())
397 397

  
398 398
        if enable_all:
399 399
            self.enable_all()
mininet/topolib.py
20 20
           returns: last node added"""
21 21
        me = n
22 22
        isSwitch = depth > 0
23
        self._add_node( me, Node( is_switch=isSwitch ) )
23
        self.add_node( me, Node( is_switch=isSwitch ) )
24 24
        if isSwitch:
25 25
            for i in range( 0, fanout ):
26 26
                child = n + 1
27
                self._add_edge( me, child )
27
                self.add_edge( me, child )
28 28
                n = self.addTree( child, depth-1, fanout )
29 29
        return n
30 30

  
mininet/util.py
141 141
    return _colonHex( mac, 6 )
142 142

  
143 143
def ipStr( ip ):
144
    """Generate IP address string
144
    """Generate IP address string from an unsigned int
145 145
       ip: unsigned int of form x << 16 | y << 8 | z
146 146
       returns: ip address string 10.x.y.z """
147 147
    hi = ( ip & 0xff0000 ) >> 16

Also available in: Unified diff