From 7e643d36c0dd3e8395a3619a0d03fc52ae9e4015 Mon Sep 17 00:00:00 2001 From: Bob Lantz Date: Mon, 25 Oct 2010 21:53:10 -0700 Subject: [PATCH] Removed udpbwgraph - not ready for prime time. --- examples/udpbwgraph.py | 309 ----------------------------------------- examples/udpbwtest.c | 199 -------------------------- examples/udpbwtest.py | 114 --------------- 3 files changed, 622 deletions(-) delete mode 100755 examples/udpbwgraph.py delete mode 100644 examples/udpbwtest.c delete mode 100755 examples/udpbwtest.py diff --git a/examples/udpbwgraph.py b/examples/udpbwgraph.py deleted file mode 100755 index 278da73..0000000 --- a/examples/udpbwgraph.py +++ /dev/null @@ -1,309 +0,0 @@ -#!/usr/bin/python - -""" -udpbwgraph: Plot network bandwidth over time - -Bob Lantz -3/27/10 -""" - -import re - -from Tkinter import Frame, Label, Button, Scrollbar, OptionMenu, Canvas -from Tkinter import StringVar - -from mininet.log import setLogLevel -from mininet.net import Mininet -from mininet.node import KernelSwitch, UserSwitch, OVSKernelSwitch -from mininet.node import Controller, NOX -from mininet.topolib import TreeTopo -from mininet.util import quietRun - -# bwtest support - -class Graph( Frame ): - - "Graph that we can add bars to over time." - - def __init__( self, master=None, - bg = 'white', - gheight=200, gwidth=500, - barwidth=10, - ymax=3.5,): - - Frame.__init__( self, master ) - - self.bg = bg - self.gheight = gheight - self.gwidth = gwidth - self.barwidth = barwidth - self.ymax = float( ymax ) - self.xpos = 0 - - # Create everything - self.title, self.graph, self.scale = self.createWidgets() - self.updateScrollRegions() - self.yview( 'moveto', '1.0' ) - - def createScale( self ): - "Create a and return a new canvas with scale markers." - height = float( self.gheight ) - width = 25 - ymax = self.ymax - scale = Canvas( self, width=width, height=height, background=self.bg ) - fill = 'red' - # Draw scale line - scale.create_line( width - 1, height, width - 1, 0, fill=fill ) - # Draw ticks and numbers - for y in range( 0, int( ymax + 1 ) ): - ypos = height * ( 1 - float( y ) / ymax ) - scale.create_line( width, ypos, width - 10, ypos, fill=fill ) - scale.create_text( 10, ypos, text=str( y ), fill=fill ) - - return scale - - def updateScrollRegions( self ): - "Update graph and scale scroll regions." - ofs = 20 - height = self.gheight + ofs - self.graph.configure( scrollregion=( 0, -ofs, - self.xpos * self.barwidth, height ) ) - self.scale.configure( scrollregion=( 0, -ofs, 0, height ) ) - - def yview( self, *args ): - "Scroll both scale and graph." - self.graph.yview( *args ) - self.scale.yview( *args ) - - def createWidgets( self ): - "Create initial widget set." - - # Objects - title = Label( self, text="Bandwidth (Mb/s)", bg=self.bg ) - width = self.gwidth - height = self.gheight - scale = self.createScale() - graph = Canvas( self, width=width, height=height, background=self.bg) - xbar = Scrollbar( self, orient='horizontal', command=graph.xview ) - ybar = Scrollbar( self, orient='vertical', command=self.yview ) - graph.configure( xscrollcommand=xbar.set, yscrollcommand=ybar.set, - scrollregion=(0, 0, width, height ) ) - scale.configure( yscrollcommand=ybar.set ) - - # Layout - title.grid( row=0, columnspan=3, sticky='new') - scale.grid( row=1, column=0, sticky='nsew' ) - graph.grid( row=1, column=1, sticky='nsew' ) - ybar.grid( row=1, column=2, sticky='ns' ) - xbar.grid( row=2, column=0, columnspan=2, sticky='ew' ) - self.rowconfigure( 1, weight=1 ) - self.columnconfigure( 1, weight=1 ) - return title, graph, scale - - def addBar( self, yval ): - "Add a new bar to our graph." - percent = yval / self.ymax - c = self.graph - x0 = self.xpos * self.barwidth - x1 = x0 + self.barwidth - y0 = self.gheight - y1 = ( 1 - percent ) * self.gheight - c.create_rectangle( x0 , y0, x1, y1, fill='green' ) - self.xpos += 1 - self.updateScrollRegions() - self.graph.xview( 'moveto', '1.0' ) - - def test( self ): - "Add a bar for testing purposes." - ms = 1000 - if self.xpos < 10: - self.addBar( self.xpos / 10 * self.ymax ) - self.after( ms, self.test ) - - def setTitle( self, text ): - "Set graph title" - self.title.configure( text=text, font='Helvetica 9 bold' ) - - -class Controls( Frame ): - - "Handy controls for configuring test." - - switches = { - 'Kernel Switch': KernelSwitch, - 'User Switch': UserSwitch, - 'Open vSwitch': OVSKernelSwitch - } - - controllers = { - 'Reference Controller': Controller, - 'NOX': NOX - } - - def __init__( self, master, startFn, stopFn, quitFn ): - - Frame.__init__( self, master ) - - # Option menus - opts = { 'font': 'Geneva 7 bold' } - self.switch = self.optionMenu( self.switches, - KernelSwitch, opts ) - self.controller = self.optionMenu( self.controllers, - Controller, opts) - - # Spacer - pk = { 'fill': 'x' } - Label( self, **opts ).pack( **pk ) - - # Buttons - self.start = Button( self, text='Start', command=startFn, **opts ) - self.stop = Button( self, text='Stop', command=stopFn, **opts ) - self.quit = Button( self, text='Quit', command=quitFn, **opts ) - for button in ( self.start, self.stop, self.quit ): - button.pack( **pk ) - - def optionMenu( self, menuItems, initval, opts ): - "Add a new option menu. Returns function to get value." - var = StringVar() - var.set( findKey( menuItems, initval ) ) - menu = OptionMenu( self, var, *menuItems ) - menu.config( **opts ) - menu.pack( fill='x' ) - return lambda: menuItems[ var.get() ] - -def parsebwtest( line, - r=re.compile( r'(\d+) s: in ([\d\.]+) MB/s, out ([\d\.]+) MB/s' ) ): - "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 - - -class UdpBwTest( Frame ): - "Test and plot UDP bandwidth over time" - - def __init__( self, topo, master=None ): - "Start up and monitor udpbwtest on each of our hosts." - - Frame.__init__( self, master ) - - self.controls = Controls( self, self.start, self.stop, self.quit ) - self.graph = Graph( self ) - - # Layout - self.controls.pack( side='left', expand=False, fill='y' ) - self.graph.pack( side='right', expand=True, fill='both' ) - self.pack( expand=True, fill='both' ) - - self.topo = topo - self.net = None - self.hosts = [] - self.hostCount = 0 - self.output = None - self.results = {} - self.running = False - - def start( self ): - "Start test." - - if self.running: - return - - switch = self.controls.switch() - controller = self.controls.controller() - - self.net = Mininet( self.topo, switch=switch, - controller=controller ) - self.hosts = self.net.hosts - self.hostCount = len( self.hosts ) - - print "*** Starting network" - self.net.start() - - print "*** Starting udpbwtest on hosts" - hosts = self.hosts - for host in hosts: - ips = [ h.IP() for h in hosts if h != host ] - host.cmdPrint( './udpbwtest ' + ' '.join( ips ) + ' &' ) - - print "*** Monitoring hosts" - self.output = self.net.monitor( hosts, timeoutms=1 ) - self.results = {} - self.running = True - self.updateGraph() - - # Pylint isn't smart enough to understand iterator.next() - # pylint: disable-msg=E1101 - - def updateGraph( self ): - "Graph input bandwidth." - - print "updateGraph" - - if not self.running: - return - - while True: - host, line = self.output.next() - if host is None or len( line ) == 0: - break - seconds, inbw, outbw = parsebwtest( line ) - if seconds is None: - break - result = self.results.get( seconds, [] ) + [ - ( host, inbw, outbw ) ] - self.results[ seconds ] = result - if len( result ) == self.hostCount: - # Calculate total and update graph - # We report input bandwidth, i.e. packets that made it - totalin = 0 - for host, inbw, outbw in result: - totalin += inbw - self.graph.addBar( totalin * 8.0 / 1000.0 ) - print totalin - # Fileevent might be better, but for now we just poll every 500ms - self.graph.after( 500, self.updateGraph ) - - def stop( self ): - "Stop test." - - print "*** Stopping udpbwtest processes" - # We *really* don't want these things hanging around! - quietRun( 'killall -9 udpbwtest' ) - - if not self.running: - return - - print "*** Stopping network" - self.running = False - self.net.stop() - - def quit( self ): - "Quit app." - self.stop() - Frame.quit( self ) - - # pylint: enable-msg=E1101 - -# Useful utilities - -def findKey( d, value ): - "Find some key where d[ key ] == value." - return [ key for key, val in d.items() if val == value ][ 0 ] - -def assign( obj, **kwargs): - "Set a bunch of fields in an object." - for name, value in kwargs.items(): - setattr( obj, name, value ) - -class Object( object ): - "Generic object you can stuff junk into." - def __init__( self, **kwargs ): - assign( self, **kwargs ) - -if __name__ == '__main__': - setLogLevel( 'info' ) - app = UdpBwTest( topo=TreeTopo( depth=2, fanout=2 ) ) - app.mainloop() diff --git a/examples/udpbwtest.c b/examples/udpbwtest.c deleted file mode 100644 index f080cf3..0000000 --- a/examples/udpbwtest.c +++ /dev/null @@ -1,199 +0,0 @@ -/* udpbwtest: a simple bandwidth test - * - * To test all-to-all communication, we simply open up a - * UDP socket and repeat the following: - * - * 1. Send a packet to a random host if possible - * 2. Receive a packet if possible - * 3. Periodically report our I/O bandwidth - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { Port=12345 }; - -/* Handy utility functions */ - -int bindAddr( int fd, long addr, u_short port ) { - /* Easy interface to bind */ - struct sockaddr_in sa; - bzero( &sa, sizeof( sa ) ); - sa.sin_family = AF_INET; - sa.sin_addr.s_addr = htonl( addr ); - sa.sin_port = htons( port ); - return bind( fd, ( struct sockaddr * )&sa, sizeof( sa ) ); -} - -int udpSocket( u_short port ) { - /* Easy interface to making a UDP socket */ - int fd = socket( AF_INET, SOCK_DGRAM, 0 ); - if ( fd < 0 ) { return fd; } - int err = bindAddr( fd, INADDR_ANY, port ); - if ( err < 0 ) { return err; } - return fd; -} - -ssize_t sendBytes( int sock, char *outbuf, size_t bufsize, - struct in_addr *addr, u_short port ) { - /* Simpler sendto */ - struct sockaddr_in sa; - int err; - bzero( &sa, sizeof( sa ) ); - sa.sin_family = AF_INET; - sa.sin_addr = *addr; - sa.sin_port = htons( port ); - err = sendto( sock, outbuf, bufsize, 0, (const struct sockaddr *) &sa, - sizeof( sa ) ); - if ( err < 0 ) { perror( "sendto:" ); } - return err; -} - -ssize_t recvBytes( int sock, char *inbuf, size_t bufsize, - struct in_addr *addr) { - /* Simpler recvfrom */ - struct sockaddr_in sa; - socklen_t saLen = sizeof( sa ); - ssize_t len; - len = recvfrom( sock, inbuf, bufsize, 0, (struct sockaddr *) &sa, &saLen ); - if ( len >= 0 ) { - assert( saLen == sizeof( sa ) ); - *addr = sa.sin_addr; - } - else { perror( "recvfrom:" ); } - return len; -} - -int readable( int fd ) { - /* Poll a single file descriptor for reading */ - struct pollfd fds = { fd, POLLIN, POLLIN }; - int result = poll( &fds, 1, 0 ); - /* True if there is one readable descriptor */ - return ( result == 1 ); -} - -int writable( int fd ) { - /* Poll a single file descriptor for writing */ - struct pollfd fds = { fd, POLLOUT, POLLOUT }; - int result = poll( &fds, 1, 0 ); - /* True if there is one writable descriptor */ - return ( result == 1 ); -} - -int poll1( int fd, int flags, int ms ) { - /* Call poll on a single descriptor */ - struct pollfd fds[] = { { fd, flags, 0 } }; - return poll( fds, 1, ms ); -} - -int waitReadable( int fd, int ms ) { return poll1( fd, POLLIN, ms ); } -int waitWritable( int fd, int ms ) { return poll1( fd, POLLIN, ms ); } -int waitReadableOrWritable( int fd, int ms ) { - return poll1( fd, POLLIN | POLLOUT, ms ); -} - -/* Timer support */ - -int alarm = 0; -void handleAlarm( int sig) { alarm = 1; } - -void startTimer( int seconds) { - struct itimerval v; - v.it_interval.tv_sec = seconds; - v.it_interval.tv_usec = 0; - v.it_value = v.it_interval; - signal( SIGALRM, handleAlarm ); - setitimer( ITIMER_REAL, &v, 0 ); -} - -void startOneSecondTimer() { startTimer( 1 ); } - -void stopTimer() { - struct itimerval v; - bzero( &v, sizeof v ); - setitimer( ITIMER_REAL, &v, 0 ); -} - -/* Actual program */ - -void bwtest( int sock, struct in_addr *hosts, int hostCount ) { - - /* Test our bandwidth, by receiving whatever we get, and sending - * randomly to a set of hosts */ - - char outbuf[ 1024 ]; - char inbuf[ 1024 ]; - time_t seconds = time( 0 ); - uint64_t b, bytes; - uint64_t inbytes = 0, outbytes = 0; - int i; - - for ( i = 0; i < sizeof( outbuf ); i++ ) { outbuf[ i ] = i % 255; } - - while ( 1 ) { - size_t addr_len; - struct in_addr addr = hosts[ random() % hostCount ]; - /* Wait until we have something to do. */ - waitReadableOrWritable( sock, 0 ); - /* Receive some bytes */ - for ( b = 0; b < 10 && readable( sock ); b += 1 ) { - bytes = recvBytes( sock, inbuf, sizeof( inbuf ), &addr ); - inbytes += bytes; - } - /* Send some bytes */ - for ( b = 0; b < 10 && writable(sock); b += 1 ) { - bytes = sendBytes( sock, outbuf, sizeof( outbuf ), - &addr, Port ); - outbytes += bytes; - } - /* Periodically report bandwidth */ - if ( alarm ) { - alarm = 0; - seconds++; - printf("%d s: in %.2f Mbps, out %.2f Mbps\n", - seconds, 8.0*inbytes/1e6, 8.0*outbytes/1e6 ); fflush( stdout ); - inbytes = outbytes = 0; - } - } -} - -int main( int argc, char *argv[] ) { - - struct in_addr start, *hosts, addr; - int count, sock, i; - - if ( argc < 2 ) { - fprintf( stderr, "usage: %s host...\n", argv[ 0 ] ); - exit( 1 ); - } - - count = argc - 1; - hosts = (struct in_addr *) malloc( count * sizeof( struct in_addr ) ); - if ( hosts == NULL ) { perror( "malloc:" ); exit( 1 ); } - - for ( i = 0; i < count; i++ ) - inet_aton( argv[ i + 1 ], &hosts[ i ] ); - - sock = udpSocket( Port ); - if ( sock < 0 ) { perror( "udpSocket:" ); exit( 1 ); } - - startOneSecondTimer(); - - bwtest( sock, hosts, count ); /* Never returns for now... */ - - stopTimer(); - -} - - - diff --git a/examples/udpbwtest.py b/examples/udpbwtest.py deleted file mode 100755 index bbeaf68..0000000 --- a/examples/udpbwtest.py +++ /dev/null @@ -1,114 +0,0 @@ -#!/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 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\.]+) MB/s, out ([\d\.]+) MB/s' ) ): - "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 (MB/s)\tavg in/out (MB/s)" - -# 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=1, fanout=8 ), switch=KernelSwitch ) - network.start() - udpbwtest( network, seconds=10 ) - network.stop()