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