Statistics
| Branch: | Tag: | Revision:

mininet / examples / udpbwtest.py @ 7ba9e055

History | View | Annotate | Download (4.37 KB)

1
#!/usr/bin/python
2

    
3
"""
4
Create a tree network and run udpbwtest.c on it, attempting to
5
saturate global bandwidth by sending constant all-to-all
6
udp traffic. This should be something of a stress test.
7

8
We should also make a tcp version. :D
9

10
In addition to trying to saturate global bandwidth in
11
various Mininet configurations, this example:
12

13
- uses a topology, TreeTopo, from mininet.topolib
14
- starts up a custom test program, udpbwtest, on each host
15
- dynamically monitors the output of a set of hosts
16

17
"""
18

    
19
import os
20
import re
21
import select
22
import sys
23
from time import time
24

    
25
flush = sys.stdout.flush
26

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

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

    
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 buf:
39
        return None, buf
40
    pos = buf.find( '\n' )
41
    line = buf[ 0 : pos ]
42
    rest = buf[ pos + 1: ]
43
    return line, rest
44

    
45
def monitor( hosts, seconds ):
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, ''
63

    
64
# bwtest support
65

    
66
def parsebwtest( line,
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

    
75
def printTotalHeader():
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

    
101
def udpbwtest( net, seconds ):
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 - times[ 0 ] , results[ t ] )
134
    print
135

    
136
# pylint: enable-msg=E1101
137

    
138
if __name__ == '__main__':
139
    lg.setLogLevel( 'info' )
140
    if not os.path.exists( './udpbwtest' ):
141
        raise Exception( 'Could not find udpbwtest in current directory.' )
142
    init()
143
    network = Mininet( TreeTopo( depth=2, fanout=2 ), switch=KernelSwitch )
144
    network.start()
145
    udpbwtest( network, seconds=10 )
146
    network.stop()