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:
@@ -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.
|
||||||
|
|||||||
@@ -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
@@ -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 )
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 )
|
|
||||||
@@ -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
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user