From 98332cb616169114a348c5add117455b900d2751 Mon Sep 17 00:00:00 2001 From: Bob Lantz <rlantz@cs.stanford.edu> Date: Mon, 14 Dec 2009 13:22:03 -0800 Subject: [PATCH] Tweaks to documentation files and sshd and xterms examples. Added scratchnetuser. --- INSTALL | 7 ++++--- README | 15 ++++++++----- examples/scratchnetuser.py | 43 ++++++++++++++++++++++++++++++++++++++ examples/sshd.py | 19 +++++++++-------- examples/xterms.py | 20 ++++++++---------- mininet.py | 9 +++++--- 6 files changed, 82 insertions(+), 31 deletions(-) create mode 100755 examples/scratchnetuser.py diff --git a/INSTALL b/INSTALL index bec17810..2f2ce4d7 100644 --- a/INSTALL +++ b/INSTALL @@ -14,9 +14,10 @@ Preliminary Mininet Installation/Configuration Notes sudo ln -s /home/openflow/mininet/netns /usr/local/bin/netns Installation is simplest with a distribution that includes a kernel - which supports the CLONE_NETNS unshare flag by default. Debian 5.0+ - does; Ubuntu doesn't. If your kernel doesn't support it, you will need - to build and install a kernel that does! + which supports the CLONE_NETNS unshare flag by default. Debian 5.0+ does + (e.g. current debian-testing release); Ubuntu doesn't. If your kernel + doesn't support it, you will need to build and install a kernel that + does! - Mininet should probably be run either on a machine with no other important processes, or on a virtual machine diff --git a/README b/README index 88b9e2d1..59c19c14 100644 --- a/README +++ b/README @@ -21,7 +21,7 @@ creation of OpenFlow networks of varying sizes and topologies. In order to run Mininet, you must have: * A Linux 2.6.26 or greater kernel compiled with network namespace support - enabled. (Debian 5.0 or greater should work) + enabled. (debian-testing seems to have such a kernel.) * The OpenFlow reference implementation (either the user or kernel datapath may be used, and the tun or ofdatapath kernel modules must be @@ -48,11 +48,16 @@ Currently mininet includes: - 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 ) + .run( Cli ). It provides useful diagnostic commands, as well as the + ability to send a command to a node. For example, + + mininet> h11 ifconfig -a + + tells host h11 to run the command 'ifconfig -a' -- A 'cleanup' script to get rid of junk (interfaces, processes, etc.) - which might be left around by mininet. Try this if things stop - working! +- A 'cleanup' script to get rid of junk (interfaces, processes, files in + /tmp, etc.) which might be left around by mininet. Try this if things + stop working! - Examples (in examples/ directory) to help you get started. diff --git a/examples/scratchnetuser.py b/examples/scratchnetuser.py new file mode 100755 index 00000000..8aab551d --- /dev/null +++ b/examples/scratchnetuser.py @@ -0,0 +1,43 @@ +#!/usr/bin/python + +""" +Build a simple network from scratch, using mininet primitives. +This is more complicated than using the higher-level classes, +but it exposes the configuration details and allows cusomization. + +This version uses the user datapath. +""" + +from mininet import init, Node, createLink + +def scratchNet( cname='controller', cargs='ptcp:'): + # Create Network + controller = Node( 'c0' ) + switch = Node( 's0') + h0 = Node( 'h0' ) + h1 = Node( 'h1' ) + createLink( controller, switch ) + createLink( h0, switch ) + createLink( h1, switch ) + # Configure control network + controller.setIP( controller.intfs[ 0 ], '10.0.123.1', '/24' ) + switch.setIP( switch.intfs[ 0 ], '10.0.123.2', '/24' ) + # Configure hosts + h0.setIP( h0.intfs[ 0 ], '192.168.123.1', '/24' ) + h1.setIP( h1.intfs[ 0 ], '192.168.123.2', '/24' ) + # Start network using user datapath + controller.cmdPrint( cname + ' ' + cargs + '&' ) + switch.cmdPrint( 'ifconfig lo 127.0.0.1' ) + switch.cmdPrint( 'ofdatapath -i ' + ','.join( switch.intfs[ 1: ]) + + ' ptcp: &' ) + switch.cmdPrint( 'ofprotocol tcp:' + controller.IP() + ' tcp:localhost &' ) + # Run test + h0.cmdPrint( 'ping -c1 ' + h1.IP() ) + # Stop network + controller.cmdPrint( 'kill %' + cname) + switch.cmdPrint( 'kill %ofdatapath' ) + switch.cmdPrint( 'kill %ofprotocol' ) + +if __name__ == '__main__': + init() + scratchNet() diff --git a/examples/sshd.py b/examples/sshd.py index 0b02e843..0df92314 100755 --- a/examples/sshd.py +++ b/examples/sshd.py @@ -1,7 +1,7 @@ #!/usr/bin/python """ -Create a network and start sshd(8) on the hosts. +Create a network and start sshd(8) on each host. While something like rshd(8) would be lighter and faster, (and perfectly adequate on an in-machine network) @@ -36,15 +36,10 @@ def connectToRootNS( network, switch ): for net in routes: root.cmdPrint( 'route add -net ' + net + ' dev ' + intf ) -def startServers( network, server ): - "Start network, and servers on each host." +def sshd( network ): + "Start a network, connect it to root ns, and run sshd on all hosts." connectToRootNS( network, network.switches[ 0 ] ) - for host in network.hosts: host.cmdPrint( server ) - -if __name__ == '__main__': - init() - network = TreeNet( depth=1, fanout=4, kernel=True ) - startServers( network, '/usr/sbin/sshd' ) + for host in network.hosts: host.cmd( 'sshd -D &' ) print print "*** Hosts are running sshd at the following addresses:" print @@ -52,4 +47,10 @@ def startServers( network, server ): print print "*** Press return to shut down network: ", readline() + for host in network.hosts: host.cmd( 'kill %sshd') network.stop() + +if __name__ == '__main__': + init() + network = TreeNet( depth=1, fanout=4, kernel=True ) + sshd( network ) \ No newline at end of file diff --git a/examples/xterms.py b/examples/xterms.py index 6e2e0761..0b0483ad 100755 --- a/examples/xterms.py +++ b/examples/xterms.py @@ -7,15 +7,18 @@ import os, re from subprocess import Popen -from mininet import init, TreeNet, Cli, quietRun +from mininet import init, TreeNet, quietRun def makeXterm( node, title ): "Run screen on a node, and hook up an xterm." - node.cmdPrint( 'screen -dmS ' + node.name ) title += ': ' + node.name if not node.inNamespace: title += ' (root)' - cmd = [ 'xterm', '-title', title ] - cmd += [ '-e', 'screen', '-D', '-RR', '-S', node.name ] + cmd = [ 'xterm', '-title', title, '-e' ] + if not node.execed: + node.cmdPrint( 'screen -dmS ' + node.name ) + cmd += [ 'screen', '-D', '-RR', '-S', node.name ] + else: + cmd += [ 'sh', '-c', 'exec tail -f /tmp/' + node.name + '*.log' ] return Popen( cmd ) def cleanUpScreens(): @@ -28,16 +31,11 @@ def cleanUpScreens(): quietRun( 'screen -S ' + m.group( 1 ) + ' -X kill' ) def makeXterms( nodes, title ): - terms = [] - for node in nodes: - if not node.execed: - terms += [ makeXterm( node, title ) ] - return terms + return [ makeXterm( node, title) for node in nodes] def xterms( controllers, switches, hosts ): cleanUpScreens() - terms = [] - terms += makeXterms( controllers, 'controller' ) + terms = makeXterms( controllers, 'controller' ) terms += makeXterms( switches, 'switch' ) terms += makeXterms( hosts, 'host' ) # Wait for xterms to exit diff --git a/mininet.py b/mininet.py index 44625d03..bbe41e80 100755 --- a/mininet.py +++ b/mininet.py @@ -136,6 +136,7 @@ def write( self, data ): os.write( self.stdin.fileno(), data ) def terminate( self ): self.cleanup() os.kill( self.pid, signal.SIGKILL ) + def stop( self ): self.terminate() def waitReadable( self ): self.pollOut.poll() def sendCmd( self, cmd ): """Send a command, followed by a command to echo a sentinel, @@ -198,7 +199,7 @@ def newIntf( self ): return intfName def setIP( self, intf, ip, bits ): "Set an interface's IP address." - result = self.cmd( [ 'ifconfig', intf, ip + bits, 'up' ] ) + result = self.cmdPrint( [ 'ifconfig', intf, ip + bits, 'up' ] ) self.ips[ intf ] = ip return result def setHostRoute( self, ip, intf ): @@ -246,11 +247,13 @@ def __init__( self, name, kernel=True ): def start( self, controller='controller', args='ptcp:' ): "Start <controller> <args> on controller, logging to /tmp/cN.log" cout = '/tmp/' + self.name + '.log' - self.cmdPrint( controller + ' ' + args + + self.cmdPrint( 'exec ' + controller + ' ' + args + ' 1> ' + cout + ' 2> ' + cout + ' &' ) + self.execed = True def stop( self, controller='controller' ): "Stop controller cprog on controller" - self.cmd( "kill %" + controller ) + self.terminate() + # self.cmd( "kill %" + controller ) class Switch( Node ): """A Switch is a Node that is running (or has execed) -- GitLab