diff --git a/examples/udpbwtest.c b/examples/udpbwtest.c
new file mode 100644
index 0000000000000000000000000000000000000000..13af68b8525e353efd00efacc5be92baf98e6a46
--- /dev/null
+++ b/examples/udpbwtest.c
@@ -0,0 +1,200 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <strings.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <assert.h>
+#include <sys/time.h>
+#include <poll.h>
+#include <signal.h>
+
+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
new file mode 100755
index 0000000000000000000000000000000000000000..4d67cb470fd88260ce0b6e3ed4bff4eaa550508e
--- /dev/null
+++ b/examples/udpbwtest.py
@@ -0,0 +1,101 @@
+#!/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
+"""
+
+import select, sys, time, re
+from mininet import init, TreeNet, Cli, flush, 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 monitor( hosts, seconds ):
+   "Monitor a set of hosts and yield their output."
+   poller = select.poll()
+   Node = hosts[ 0 ] # so we can call class method
+   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, ''
+
+# 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 )
+   
+def printTotalHeader():
+   print
+   print "time(s)\thosts\ttotal in/out (Mbps)\tavg in/out (Mbps)"
+
+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( controllers, switches, hosts, seconds ):
+   "Start up and monitor udpbwtest on each of our 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
+      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 
+     
+if __name__ == '__main__':
+   init()
+   network = TreeNet( depth=2, fanout=8, kernel=True )
+   def test( c, s, h ): return udpbwtest( c, s, h, seconds=10 )
+   network.run( test )
+   
\ No newline at end of file