115 lines
3.4 KiB
Python
Executable File
115 lines
3.4 KiB
Python
Executable File
#!/usr/bin/python
|
|
|
|
"""
|
|
Create a tree network and run udpbwtest.c on it, attempting to
|
|
saturate global bandwidth by sending constant all-to-all
|
|
udp traffic. This should be something of a stress test.
|
|
|
|
We should also make a tcp version. :D
|
|
|
|
In addition to trying to saturate global bandwidth in
|
|
various Mininet configurations, this example:
|
|
|
|
- uses a topology, TreeTopo, from mininet.topolib
|
|
- starts up a custom test program, udpbwtest, on each host
|
|
- dynamically monitors the output of a set of hosts
|
|
|
|
"""
|
|
|
|
import os
|
|
import re
|
|
import sys
|
|
from time import time
|
|
|
|
flush = sys.stdout.flush
|
|
|
|
from mininet.log import lg
|
|
from mininet.net import init, Mininet
|
|
from mininet.node import KernelSwitch
|
|
from mininet.topolib import TreeTopo
|
|
from mininet.util import quietRun
|
|
|
|
# bwtest support
|
|
|
|
def parsebwtest( line,
|
|
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 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 udpbwtest( net, seconds ):
|
|
"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 = net.monitor( hosts )
|
|
quitTime = time() + seconds
|
|
while time() < quitTime:
|
|
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 - times[ 0 ] , results[ t ] )
|
|
print
|
|
|
|
# pylint: enable-msg=E1101
|
|
|
|
if __name__ == '__main__':
|
|
lg.setLogLevel( 'info' )
|
|
if not os.path.exists( './udpbwtest' ):
|
|
raise Exception( 'Could not find udpbwtest in current directory.' )
|
|
network = Mininet( TreeTopo( depth=2, fanout=2 ), switch=KernelSwitch )
|
|
network.start()
|
|
udpbwtest( network, seconds=10 )
|
|
network.stop()
|