First crack at allowing Controller to be customized.

Network may now be used with custom controllers.
An example of doing this is in nox.py, which instantiates at TreeNet
using a custom Controller, NoxController, that runs nox_core rather
than the reference controller.
This commit is contained in:
Bob Lantz
2009-12-14 20:14:44 -08:00
parent 845dedca32
commit 2f53491343
7 changed files with 54 additions and 70 deletions
+2
View File
@@ -1,6 +1,8 @@
Preliminary Mininet Installation/Configuration Notes Preliminary Mininet Installation/Configuration Notes
--- ---
- This is not (yet) a 'release'; things may be broken.
- Mininet is not currently 'installed.' If you want to install it, - Mininet is not currently 'installed.' If you want to install it,
so that you can 'import mininet', place it somewhere in your so that you can 'import mininet', place it somewhere in your
python path. python path.
+3
View File
@@ -24,6 +24,9 @@ ps ax | egrep -o 'dp[0-9]+' | sed 's/dp/nl:/' | xargs -l1 echo dpctl deldp
echo "Removing junk in /tmp" echo "Removing junk in /tmp"
rm -f /tmp/vconn* /tmp/vlogs* /tmp/*.out /tmp/*.log rm -f /tmp/vconn* /tmp/vlogs* /tmp/*.out /tmp/*.log
echo "Killing nox"
killall lt-nox_core
echo "Removing old screen sessions" echo "Removing old screen sessions"
screen -ls | egrep -o '[0-9]+\.[hsc][0-9]+' | sed 's/\.[hsc][0-9]*//g' | kill -9 screen -ls | egrep -o '[0-9]+\.[hsc][0-9]+' | sed 's/\.[hsc][0-9]*//g' | kill -9
+10 -32
View File
@@ -1,39 +1,17 @@
#!/usr/bin/python #!/usr/bin/python
"Create a network from scratch and use NOX as the controller." "Instantiate a Tree network and use NOX as the controller."
from mininet import init, Controller, Switch, Host, createLink import time
from mininet import init, Controller, TreeNet, Cli
def scratchNet( cname='controller', cargs='ptcp:'): class NoxController( Controller ):
# Create Network def __init__( self, name, **kwargs ):
controller = Node( 'c0', inNamespace=False ) Controller.__init__( self, name,
switch = Node( 's0', inNamespace=False ) controller='nox_core', cargs='-i ptcp pyswitch',
h0 = Node( 'h0' ) cdir='/usr/local/bin', **kwargs)
h1 = Node( 'h1' )
createLink( h0, switch )
createLink( h1, switch )
# 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 kernel datapath
controller.cmdPrint( cname + ' ' + cargs + '&' )
switch.cmdPrint( 'dpctl deldp nl:0' )
switch.cmdPrint( 'dpctl adddp nl:0' )
for intf in switch.intfs:
switch.cmdPrint( 'dpctl addif nl:0 ' + intf )
switch.cmdPrint( 'ofprotocol nl:0 tcp:localhost &')
# Run test
h0.cmdPrint( 'ping -c1 ' + h1.IP() )
# Stop network
controller.cmdPrint( 'kill %' + cname)
switch.cmdPrint( 'dpctl deldp nl:0' )
switch.cmdPrint( 'kill %ofprotocol' )
switch.stop()
controller.stop()
if __name__ == '__main__': if __name__ == '__main__':
init() init()
scratchNet( cname='nox_core', cargs='-i ptcp:' ) network = TreeNet( depth=2, fanout=4, kernel=True, Controller=NoxController)
network.run( Cli )
+1
View File
@@ -7,6 +7,7 @@ While something like rshd(8) would be lighter and faster,
(and perfectly adequate on an in-machine network) (and perfectly adequate on an in-machine network)
the advantage of running sshd is that scripts can work the advantage of running sshd is that scripts can work
unchanged on mininet and hardware. unchanged on mininet and hardware.
""" """
import sys ; readline = sys.stdin.readline import sys ; readline = sys.stdin.readline
-15
View File
@@ -1,15 +0,0 @@
#!/usr/bin/python
"""
Create a 1024-host network, and run the CLI on it.
If this fails because of kernel limits, you may have
to adjust them, e.g. by adding entries to /etc/sysctl.conf
and running sysctl -p.
"""
from mininet import init, TreeNet
if __name__ == '__main__':
init()
network = TreeNet( depth=2, fanout=32, kernel=True )
network.run( Cli )
+2 -2
View File
@@ -6,9 +6,9 @@ from mininet import init, TreeNet, pingTestVerbose
def treePing64(): def treePing64():
results = {} results = {}
datapaths = [ 'kernel', 'user' ] datapaths = [ 'user', 'kernel' ]
print "*** Testing Mininet with kernel and user datapaths" print "*** Testing Mininet with user and kernel datapaths"
for datapath in datapaths: for datapath in datapaths:
k = datapath == 'kernel' k = datapath == 'kernel'
+36 -21
View File
@@ -242,12 +242,18 @@ class Host( Node ):
class Controller( Node ): class Controller( Node ):
"""A Controller is a Node that is running (or has execed) an """A Controller is a Node that is running (or has execed) an
OpenFlow controller.""" OpenFlow controller."""
def __init__( self, name, kernel=True ): def __init__( self, name, kernel=True, controller='controller',
cargs='ptcp:', cdir=None ):
self.controller = controller
self.cargs = cargs
self.cdir = cdir
Node.__init__( self, name, inNamespace=( not kernel ) ) Node.__init__( self, name, inNamespace=( not kernel ) )
def start( self, controller='controller', args='ptcp:' ): def start( self ):
"Start <controller> <args> on controller, logging to /tmp/cN.log" "Start <controller> <args> on controller, logging to /tmp/cN.log"
cout = '/tmp/' + self.name + '.log' cout = '/tmp/' + self.name + '.log'
self.cmdPrint( controller + ' ' + args + if self.cdir is not None:
self.cmdPrint( 'cd ' + self.cdir )
self.cmdPrint( self.controller + ' ' + self.cargs +
' 1> ' + cout + ' 2> ' + cout + ' &' ) ' 1> ' + cout + ' 2> ' + cout + ' &' )
self.execed = False # XXX Until I fix it self.execed = False # XXX Until I fix it
def stop( self, controller='controller' ): def stop( self, controller='controller' ):
@@ -394,10 +400,10 @@ def nameGen( prefix ):
# Note: Instead of routing, we could bridge or use "in-band" control # Note: Instead of routing, we could bridge or use "in-band" control
def configRoutedControlNetwork( controller, switches, def configRoutedControlNetwork( controller, switches,
startAddr=( 10, 123, 0, 1 ) ): ipGen=ipGen, ipStart=( 10, 123, 0, 1 ) ):
"""Configure a routed control network on controller and switches, """Configure a routed control network on controller and switches,
for use with the user datapath.""" for use with the user datapath."""
ips = apply( ipGen, startAddr ) ips = ipGen( ipStart )
cip = ips.next() cip = ips.next()
print controller.name, '<->', print controller.name, '<->',
for switch in switches: for switch in switches:
@@ -426,9 +432,8 @@ def configRoutedControlNetwork( controller, switches,
print "*** Error: control network test failed" print "*** Error: control network test failed"
exit( 1 ) exit( 1 )
def configHosts( hosts, ( a, b, c, d ) ): def configHosts( hosts, ips ):
"Configure a set of hosts, starting at IP address a.b.c.d" "Configure a set of hosts, starting at IP address a.b.c.d"
ips = ipGen( a, b, c, d )
for host in hosts: for host in hosts:
hintf = host.intfs[ 0 ] hintf = host.intfs[ 0 ]
host.setIP( hintf, ips.next(), '/24' ) host.setIP( hintf, ips.next(), '/24' )
@@ -442,8 +447,15 @@ def configHosts( hosts, ( a, b, c, d ) ):
class Network( object ): class Network( object ):
"Network topology (and test driver) base class." "Network topology (and test driver) base class."
def __init__( self, kernel=True, startAddr=( 192, 168, 123, 1) ): def __init__( self,
self.kernel, self.startAddr = kernel, startAddr kernel=True,
Controller=Controller, Switch=Switch,
hostIpGen=ipGen, hostIpStart=( 192, 168, 123, 1 ) ):
print "NETWORK: Controller=", Controller
self.kernel = kernel
self.Controller = Controller
self.Switch = Switch
self.hostIps = apply( hostIpGen, hostIpStart )
# Check for kernel modules # Check for kernel modules
modules = quietRun( 'lsmod' ) modules = quietRun( 'lsmod' )
if not kernel and 'tun' not in modules: if not kernel and 'tun' not in modules:
@@ -456,6 +468,11 @@ class Network( object ):
exit( 1 ) exit( 1 )
# Create network, but don't start things up yet! # Create network, but don't start things up yet!
self.prepareNet() self.prepareNet()
def configureControlNetwork( self ):
configureRoutedControlNetwork( self.controllers[ 0 ],
self.switches)
def configHosts( self ):
configHosts( self.hosts, self.hostIps )
def prepareNet( self ): def prepareNet( self ):
"""Create a network by calling makeNet as follows: """Create a network by calling makeNet as follows:
(switches, hosts ) = makeNet() (switches, hosts ) = makeNet()
@@ -464,21 +481,19 @@ class Network( object ):
if kernel: print "*** Using kernel datapath" if kernel: print "*** Using kernel datapath"
else: print "*** Using user datapath" else: print "*** Using user datapath"
print "*** Creating controller" print "*** Creating controller"
controller = Controller( 'c0', kernel ) self.controller = self.Controller( 'c0', kernel=kernel )
self.controllers = [ self.controller ]
print "*** Creating network" print "*** Creating network"
switches, hosts = self.makeNet( controller ) self.switches, self.hosts = self.makeNet( self.controller )
print print
if not kernel: if not kernel:
print "*** Configuring control network" print "*** Configuring control network"
configRoutedControlNetwork( controller, switches ) self.configureControlNetwork()
print "*** Configuring hosts" print "*** Configuring hosts"
configHosts( hosts, self.startAddr ) self.configHosts()
self.controllers = [ controller ]
self.switches = switches
self.hosts = hosts
def start( self ): def start( self ):
"Start controller and switches" "Start controller and switches"
print "*** Starting reference controller" print "*** Starting controller"
for controller in self.controllers: for controller in self.controllers:
controller.start() controller.start()
print "*** Starting", len( self.switches ), "switches" print "*** Starting", len( self.switches ), "switches"
@@ -524,9 +539,9 @@ def defaultNames( snames=None, hnames=None, dpnames=None ):
class TreeNet( Network ): class TreeNet( Network ):
"A tree-structured network with the specified depth and fanout" "A tree-structured network with the specified depth and fanout"
def __init__( self, depth, fanout, kernel=True): def __init__( self, depth, fanout, **kwargs):
self.depth, self.fanout = depth, fanout self.depth, self.fanout = depth, fanout
Network.__init__( self, kernel ) Network.__init__( self, **kwargs )
def treeNet( self, controller, depth, fanout, kernel=True, snames=None, def treeNet( self, controller, depth, fanout, kernel=True, snames=None,
hnames=None, dpnames=None ): hnames=None, dpnames=None ):
"""Return a tree network of the given depth and fanout as a triple: """Return a tree network of the given depth and fanout as a triple:
@@ -563,9 +578,9 @@ class GridNet( Network ):
"""An N x M grid/mesh network of switches, with hosts at the edges. """An N x M grid/mesh network of switches, with hosts at the edges.
This class also demonstrates creating a somewhat complicated This class also demonstrates creating a somewhat complicated
topology.""" topology."""
def __init__( self, n, m, kernel=True, linear=False ): def __init__( self, n, m, kernel=True, linear=False, **kwargs ):
self.n, self.m, self.linear = n, m, linear and m == 1 self.n, self.m, self.linear = n, m, linear and m == 1
Network.__init__( self, kernel ) Network.__init__( self, kernel, **kwargs )
def makeNet( self, controller ): def makeNet( self, controller ):
snames, hnames, dpnames = defaultNames() snames, hnames, dpnames = defaultNames()
n, m = self.n, self.m n, m = self.n, self.m