Removed underscores for public Node methods. Minor cleanup & comments.

This commit is contained in:
Bob Lantz
2010-03-08 15:32:41 -08:00
parent 2626693241
commit 80be564274
12 changed files with 223 additions and 188 deletions
+23 -24
View File
@@ -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 ] )
+10 -11
View File
@@ -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' )
+8 -7
View File
@@ -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()
+36 -33
View File
@@ -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 )
+97 -75
View File
@@ -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' ):