From 748e35d50fc14dfc7e09c1789ece1b9c4fcc0a94 Mon Sep 17 00:00:00 2001 From: Bob Lantz <rlantz@cs.stanford.edu> Date: Thu, 10 Dec 2009 23:39:06 -0800 Subject: [PATCH] Working on examples. Added new example to create xterms. Other minor changes. --- README | 42 ++++++++++++++++++++----------------- examples/bigTreePing64.py | 13 ++++++------ examples/linearBandwidth.py | 37 ++++++++++++++++++++------------ examples/treeInteract.py | 14 +++++++++++++ examples/xterms.py | 39 ++++++++++++++++++++++++++++++++++ mininet.py | 15 +++++++++---- 6 files changed, 117 insertions(+), 43 deletions(-) create mode 100755 examples/treeInteract.py create mode 100755 examples/xterms.py diff --git a/README b/README index 4142c922..6e9754a4 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ - Mininet: A Simple Virtual Testbed for OpenFlow - aka + Mininet: A Simple Virtual Testbed for OpenFlow + aka How to Squeeze a 1024-node OpenFlow Network onto your Laptop (Extremely Experimental Development Version 0.1, December 2009) @@ -10,40 +10,44 @@ How to Squeeze a 1024-node OpenFlow Network onto your Laptop Mininet creates simple OpenFlow test networks by using process-based virtualization and network namespaces. -Simulated hosts (as well as switches and controllers with the user datapath) -are created as processes in separate network namespaces. This allows a -complete OpenFlow network to be simulated on top of a single Linux kernel. +Simulated hosts (as well as switches and controllers with the user +datapath) are created as processes in separate network namespaces. This +allows a complete OpenFlow network to be simulated on top of a single +Linux kernel. In order to run Mininet, you must have: * A Linux 2.6.26 or greater kernel compiled with network namespace support - enabled. (Debian-testing should work.) + enabled. (Debian 5.0 or greater should work.) -* The OpenFlow reference implementation (either the user or kernel datapath - may be used, and the tun or ofdatapath kernel modules must be loaded, - respectively) +* The OpenFlow reference implementation (either the user or kernel + datapath may be used, and the tun or ofdatapath kernel modules must be + loaded, respectively) * Python, Bash, etc. * Root privilieges (required for network device access) -* The netns program or equivalent (included as netns.c) +* The netns program or equivalent (included as netns.c) installed + in an appropriate path location. + +* mininet.py installed in an appropriate Python path location. Currently mininet includes: - A simple node infrastructure (Host, Switch, Controller classes) for - creating virtual OpenFlow networks. +- A simple node infrastructure (Host, Switch, Controller classes) for + creating virtual OpenFlow networks. - A simple network infrastructure (class Network and its descendants - TreeNet, GridNet and LinearNet) for creating scalable topologies and - running experiments (using someNetwork.run( test ) ) +- A simple network infrastructure (class Network and its descendants + TreeNet, GridNet and LinearNet) for creating scalable topologies and + running experiments (using someNetwork.run( test ) ) - Some simple tests which can be run by someNetwork.run( test ) +- Some simple tests which can be run using someNetwork.run( test ) - A simple command-line interface which may be invoked on a network - using .run( Cli ) +- A simple command-line interface which may be invoked on a network using + .run( Cli ) - Examples (in examples/ directory) to help you get started. +- Examples (in examples/ directory) to help you get started. Notes and Advice: diff --git a/examples/bigTreePing64.py b/examples/bigTreePing64.py index 2ae71433..27fc9da7 100755 --- a/examples/bigTreePing64.py +++ b/examples/bigTreePing64.py @@ -1,22 +1,21 @@ #!/usr/bin/python +"""Create a tree network of depth 4 and fanout 2, and + test connectivity using pingTest.""" + from mininet import init, TreeNet, iperfTest def bigTreePing64(): - """Create a tree network of depth 4 and fanout 2, and - test connectivity using pingTest.""" - results = {} - + print "*** Testing Mininet with kernel and user datapath" for datapath in [ 'kernel', 'user' ]: k = datapath == 'kernel' results[ datapath ] = [] for switchCount in range( 1, 4 ): - print "*** Creating Linear Network of size", switchCount - network = TreeNet( depth=4, fanout=2, kernel=k ) - testResult = network.run( iperfTest ) + network = TreeNet( depth=4, fanout=4, kernel=k ) + testResult = network.run( pingTest ) results[ datapath ] += testResult print "*** Test results:", results diff --git a/examples/linearBandwidth.py b/examples/linearBandwidth.py index 7c38dee7..bb773bc4 100755 --- a/examples/linearBandwidth.py +++ b/examples/linearBandwidth.py @@ -1,36 +1,47 @@ #!/usr/bin/python +""" +Test bandwidth on a linear network of varying size, using both +the kernel and user datapaths. + +The network looks like: + +h0 <-> s0 <-> s1 .. sN <-> h1 +""" + from mininet import init, LinearNet, iperfTest def linearBandwidthTest(): - """Test bandwidth on a linear network of varying size, using both - the kernel and user datapaths.""" - - print "*** Testing Mininet with kernel and user datapath" - - datapaths = [ 'kernel' ] + + datapaths = [ 'kernel', 'user' ] + switchCounts = [ 1, 20, 40, 60, 80, 100 ] results = {} - + for datapath in datapaths: k = datapath == 'kernel' results[ datapath ] = [] - for switchCount in range( 1, 17, 2 ): - print "*** Creating Linear Network of size", switchCount + for switchCount in switchCounts: + print "*** Creating linear network of size", switchCount network = LinearNet( switchCount, k) bandwidth = network.run( iperfTest ) results[ datapath ] += [ ( switchCount, bandwidth ) ] for datapath in datapaths: print - print "*** Linear network results for", datapath, "datapath" + print "*** Linear network results for", datapath, "datapath:" print result = results[ datapath ] + print "SwitchCount\tiPerf results" for switchCount, bandwidth in result: - print "switchCount:", switchCount, "bandwidth:", bandwidth[ 0 ] - + print switchCount, '\t\t', + print bandwidth[ 0 ], 'server, ', bandwidth[ 1 ], 'client' + print + print + if __name__ == '__main__': init() + print "*** Running linearBandwidthTest" linearBandwidthTest() exit( 1 ) - \ No newline at end of file + diff --git a/examples/treeInteract.py b/examples/treeInteract.py new file mode 100755 index 00000000..ca95f0f2 --- /dev/null +++ b/examples/treeInteract.py @@ -0,0 +1,14 @@ +#!/usr/bin/python + +"""Create a tree network and run the CLI on it.""" + +from mininet import init, TreeNet, Cli + +def treeInteract(): + network = TreeNet( depth=2, fanout=4, kernel=True ) + network.run( Cli ) + +if __name__ == '__main__': + init() + treeInteract() + diff --git a/examples/xterms.py b/examples/xterms.py new file mode 100755 index 00000000..40ef1b0c --- /dev/null +++ b/examples/xterms.py @@ -0,0 +1,39 @@ +#!/usr/bin/python + +"Create a network and run an xterm (connected via screen) on each host." + +import os +from subprocess import Popen +from mininet import init, TreeNet, Cli, quietRun + +def makeXterm( node, title ): + "Run screen on a node, and hook up an xterm." + node.cmdPrint( 'screen -dmS ' + node.name ) + cmd = 'xterm -title ' + title + ':' + node.name + cmd += ' -e screen -D -RR -S ' + node.name + return Popen( cmd.split( ' ' ) ) + +def makeXterms( nodes, title ): + terms = [] + for node in nodes: + if not node.execed: + terms += [ makeXterm( node, title ) ] + return terms + +def xterms( controllers, switches, hosts ): + terms = [] + terms += makeXterms( controllers, 'controller' ) + terms += makeXterms( switches, 'switch' ) + terms += makeXterms( hosts, 'host' ) + # Wait for completion + for term in terms: + os.waitpid( term.pid, 0 ) + +def treeXterms(): + print "Running xterms on", os.environ[ 'DISPLAY' ] + network = TreeNet( depth=2, fanout=4, kernel=True ) + network.run( xterms ) + +if __name__ == '__main__': + init() + treeXterms() diff --git a/mininet.py b/mininet.py index ac942335..22e98529 100755 --- a/mininet.py +++ b/mininet.py @@ -126,10 +126,16 @@ def __init__( self, name, inNamespace=True ): self.ips = {} self.connection = {} self.waiting = False + self.execed = False + def cleanup( self ): + # Help python collect its garbage + self.shell = None # Subshell I/O, commands and control def read( self, max ): return os.read( self.stdout.fileno(), max ) def write( self, data ): os.write( self.stdin.fileno(), data ) - def terminate( self ): os.kill( self.pid, signal.SIGKILL ) + def terminate( self ): + self.cleanup() + os.kill( self.pid, signal.SIGKILL ) def waitReadable( self ): self.pollOut.poll() def sendCmd( self, cmd ): """Send a command, followed by a command to echo a sentinel, @@ -251,7 +257,6 @@ class Switch( Node ): an OpenFlow switch.""" def __init__( self, name, datapath=None ): self.dp = datapath - self.execed = False Node.__init__( self, name, inNamespace=( datapath == None ) ) def startUserDatapath( self, controller ): """Start OpenFlow reference user datapath, @@ -470,10 +475,12 @@ def run( self, test ): print "*** Running test" result = test( [ controller ], switches, hosts ) print "*** Stopping controller" - controller.stop() + controller.stop(); controller.terminate() print "*** Stopping switches" for switch in switches: - switch.stop() + switch.stop() ; switch.terminate() + print "*** Stopping hosts" + for host in hosts: host.terminate() print "*** Test complete" return result def interact( self ): -- GitLab