Merge branch 'of1.0' into testing
Conflicts: bin/mn mininet/cli.py mininet/moduledeps.py mininet/node.py mininet/topo.py util/install.sh
This commit is contained in:
+16
-1
@@ -272,6 +272,20 @@ class CLI( Cmd ):
|
||||
error( 'error reading file %s\n' % args[ 0 ] )
|
||||
self.inputFile = None
|
||||
|
||||
def do_dpctl( self, line ):
|
||||
"Run dpctl command on all switches."
|
||||
args = line.split()
|
||||
if len(args) == 0:
|
||||
error( 'usage: dpctl command [arg1] [arg2] ...\n' )
|
||||
return
|
||||
if not self.mn.listenPort:
|
||||
error( "can't run dpctl w/no passive listening port\n")
|
||||
return
|
||||
for sw in self.mn.switches:
|
||||
output( '*** ' + sw.name + ' ' + ('-' * 72) + '\n' )
|
||||
output( sw.cmd( 'dpctl ' + ' '.join(args) +
|
||||
' tcp:127.0.0.1:%i' % sw.listenPort ) )
|
||||
|
||||
def default( self, line ):
|
||||
"""Called on an input line when the command prefix is not recognized.
|
||||
Overridden to run shell commands when a node is the first CLI argument.
|
||||
@@ -314,7 +328,8 @@ class CLI( Cmd ):
|
||||
while True:
|
||||
try:
|
||||
bothPoller.poll()
|
||||
if self.inputFile:
|
||||
# XXX BL: this doesn't quite do what we want.
|
||||
if False and self.inputFile:
|
||||
key = self.inputFile.read( 1 )
|
||||
if key is not '':
|
||||
node.write(key)
|
||||
|
||||
+11
-9
@@ -37,7 +37,7 @@ def moduleDeps( subtract=None, add=None ):
|
||||
info( '*** Removing ' + mod + '\n' )
|
||||
rmmodOutput = rmmod( mod )
|
||||
if rmmodOutput:
|
||||
error( 'Error removing ' + mod + '\n%s' % rmmodOutput )
|
||||
error( 'Error removing ' + mod + ': "%s">\n' % rmmodOutput )
|
||||
exit( 1 )
|
||||
if mod in lsmod():
|
||||
error( 'Failed to remove ' + mod + '; still there!\n' )
|
||||
@@ -47,20 +47,22 @@ def moduleDeps( subtract=None, add=None ):
|
||||
info( '*** Loading ' + mod + '\n' )
|
||||
modprobeOutput = modprobe( mod )
|
||||
if modprobeOutput:
|
||||
error( 'Error inserting ' + mod + ';\n See INSTALL.\n%s' %
|
||||
modprobeOutput )
|
||||
exit( 1 )
|
||||
error( 'Error inserting ' + mod +
|
||||
' - is it installed and available via modprobe?\n' +
|
||||
'Error was: "%s"\n' % modprobeOutput )
|
||||
if mod not in lsmod():
|
||||
error( 'Failed to insert ' + mod + '\n' )
|
||||
error( 'Failed to insert ' + mod + ' - quitting.\n' )
|
||||
exit( 1 )
|
||||
else:
|
||||
debug( '*** ' + mod + ' already loaded\n' )
|
||||
|
||||
def pathCheck( *args ):
|
||||
|
||||
def pathCheck( *args, **kwargs ):
|
||||
"Make sure each program in *args can be found in $PATH."
|
||||
moduleName = kwargs.get( 'moduleName', 'it' )
|
||||
for arg in args:
|
||||
if not quietRun( 'which ' + arg ):
|
||||
error( 'Cannot find required executable %s -'
|
||||
' is it installed somewhere in your $PATH?\n(%s)\n' %
|
||||
( arg, environ[ 'PATH' ] ) )
|
||||
error( 'Cannot find required executable %s.\n' % arg +
|
||||
'Please make sure that %s is installed ' % moduleName +
|
||||
'and available in your $PATH:\n(%s)\n' % environ[ 'PATH' ] )
|
||||
exit( 1 )
|
||||
|
||||
+20
-10
@@ -94,7 +94,7 @@ from time import sleep
|
||||
|
||||
from mininet.cli import CLI
|
||||
from mininet.log import info, error, debug, output
|
||||
from mininet.node import Host, UserSwitch, KernelSwitch, Controller
|
||||
from mininet.node import Host, UserSwitch, OVSKernelSwitch, Controller
|
||||
from mininet.node import ControllerParams
|
||||
from mininet.util import quietRun, fixLimits
|
||||
from mininet.util import createLink, macColonHex, ipStr, ipParse
|
||||
@@ -103,12 +103,12 @@ from mininet.term import cleanUpScreens, makeTerms
|
||||
class Mininet( object ):
|
||||
"Network emulation with hosts spawned in network namespaces."
|
||||
|
||||
def __init__( self, topo=None, switch=KernelSwitch, host=Host,
|
||||
def __init__( self, topo=None, switch=OVSKernelSwitch, host=Host,
|
||||
controller=Controller,
|
||||
cparams=ControllerParams( '10.0.0.0', 8 ),
|
||||
build=True, xterms=False, cleanup=False,
|
||||
inNamespace=False,
|
||||
autoSetMacs=False, autoStaticArp=False ):
|
||||
autoSetMacs=False, autoStaticArp=False, listenPort=None ):
|
||||
"""Create Mininet object.
|
||||
topo: Topo (topology) object or None
|
||||
switch: Switch class
|
||||
@@ -120,7 +120,9 @@ class Mininet( object ):
|
||||
cleanup: if build now, cleanup before creating?
|
||||
inNamespace: spawn switches and controller in net namespaces?
|
||||
autoSetMacs: set MAC addrs from topo?
|
||||
autoStaticArp: set all-pairs static MAC addrs?"""
|
||||
autoStaticArp: set all-pairs static MAC addrs?
|
||||
listenPort: base listening port to open; will be incremented for
|
||||
each additional switch in the net if inNamespace=False"""
|
||||
self.switch = switch
|
||||
self.host = host
|
||||
self.controller = controller
|
||||
@@ -131,6 +133,7 @@ class Mininet( object ):
|
||||
self.cleanup = cleanup
|
||||
self.autoSetMacs = autoSetMacs
|
||||
self.autoStaticArp = autoStaticArp
|
||||
self.listenPort = listenPort
|
||||
|
||||
self.hosts = []
|
||||
self.switches = []
|
||||
@@ -162,25 +165,32 @@ class Mininet( object ):
|
||||
"""Add switch.
|
||||
name: name of switch to add
|
||||
mac: default MAC address for kernel/OVS switch intf 0
|
||||
returns: added switch"""
|
||||
returns: added switch
|
||||
side effect: increments the listenPort member variable."""
|
||||
if self.switch == UserSwitch:
|
||||
sw = self.switch( name, defaultMAC=mac, defaultIP=ip,
|
||||
inNamespace=self.inNamespace )
|
||||
sw = self.switch( name, listenPort=self.listenPort,
|
||||
defaultMAC=mac, defaultIP=ip, inNamespace=self.inNamespace )
|
||||
else:
|
||||
sw = self.switch( name, defaultMAC=mac, defaultIP=ip, dp=self.dps,
|
||||
sw = self.switch( name, listenPort=self.listenPort,
|
||||
defaultMAC=mac, defaultIP=ip, dp=self.dps,
|
||||
inNamespace=self.inNamespace )
|
||||
if not self.inNamespace and self.listenPort:
|
||||
self.listenPort += 1
|
||||
self.dps += 1
|
||||
self.switches.append( sw )
|
||||
self.nameToNode[ name ] = sw
|
||||
return sw
|
||||
|
||||
def addController( self, name='c0', **kwargs ):
|
||||
def addController( self, name='c0', controller=None, **kwargs ):
|
||||
"""Add controller.
|
||||
controller: Controller class"""
|
||||
controller_new = self.controller( name, **kwargs )
|
||||
if not controller:
|
||||
controller = self.controller
|
||||
controller_new = controller( name, **kwargs )
|
||||
if controller_new: # allow controller-less setups
|
||||
self.controllers.append( controller_new )
|
||||
self.nameToNode[ name ] = controller_new
|
||||
return controller_new
|
||||
|
||||
# Control network support:
|
||||
#
|
||||
|
||||
+33
-18
@@ -200,7 +200,6 @@ class Node( object ):
|
||||
"""Monitor and return the output of a command.
|
||||
Set self.waiting to False if command has completed.
|
||||
timeoutms: timeout in ms or None to wait indefinitely."""
|
||||
assert self.waiting
|
||||
self.waitReadable( timeoutms )
|
||||
data = self.read( 1024 )
|
||||
# Look for PID
|
||||
@@ -434,9 +433,19 @@ class Switch( Node ):
|
||||
|
||||
portBase = SWITCH_PORT_BASE # 0 for OF < 1.0, 1 for OF >= 1.0
|
||||
|
||||
def __init__( self, name, opts='', **kwargs):
|
||||
def __init__( self, name, opts='', listenPort=None, **kwargs):
|
||||
Node.__init__( self, name, **kwargs )
|
||||
self.opts = opts
|
||||
self.listenPort = listenPort
|
||||
if self.listenPort:
|
||||
self.opts += ' --listen=ptcp:%i ' % self.listenPort
|
||||
|
||||
def defaultIntf( self ):
|
||||
"Return interface for HIGHEST port"
|
||||
ports = self.intfs.keys()
|
||||
if ports:
|
||||
intf = self.intfs[ max( ports ) ]
|
||||
return intf
|
||||
|
||||
def sendCmd( self, *cmd, **kwargs ):
|
||||
"""Send command to Node.
|
||||
@@ -455,12 +464,15 @@ class UserSwitch( Switch ):
|
||||
"""Init.
|
||||
name: name for the switch"""
|
||||
Switch.__init__( self, name, **kwargs )
|
||||
pathCheck( 'ofdatapath', 'ofprotocol' )
|
||||
pathCheck( 'ofdatapath', 'ofprotocol',
|
||||
moduleName='the OpenFlow reference user switch (openflow.org)' )
|
||||
|
||||
|
||||
@staticmethod
|
||||
def setup():
|
||||
"Ensure any dependencies are loaded; if not, try to load them."
|
||||
moduleDeps( add=TUN )
|
||||
if not os.path.exists( '/dev/net/tun' ):
|
||||
moduleDeps( add=TUN )
|
||||
|
||||
def start( self, controllers ):
|
||||
"""Start OpenFlow reference user datapath.
|
||||
@@ -478,7 +490,7 @@ class UserSwitch( Switch ):
|
||||
if self.inNamespace:
|
||||
intfs = intfs[ :-1 ]
|
||||
self.cmd( 'ofdatapath -i ' + ','.join( intfs ) +
|
||||
' punix:/tmp/' + self.name + mac_str +
|
||||
' punix:/tmp/' + self.name + mac_str + ' --no-slicing ' +
|
||||
' 1> ' + ofdlog + ' 2> ' + ofdlog + ' &' )
|
||||
self.cmd( 'ofprotocol unix:/tmp/' + self.name +
|
||||
' tcp:%s:%d' % ( controller.IP(), controller.port ) +
|
||||
@@ -511,8 +523,10 @@ class KernelSwitch( Switch ):
|
||||
@staticmethod
|
||||
def setup():
|
||||
"Ensure any dependencies are loaded; if not, try to load them."
|
||||
moduleDeps( subtract = OVS_KMOD, add = OF_KMOD )
|
||||
pathCheck( 'ofprotocol' )
|
||||
pathCheck( 'ofprotocol',
|
||||
moduleName='the OpenFlow reference kernel switch'
|
||||
' (openflow.org) (NOTE: not available in OpenFlow 1.0!)' )
|
||||
moduleDeps( subtract=OVS_KMOD, add=OF_KMOD )
|
||||
|
||||
def start( self, controllers ):
|
||||
"Start up reference kernel datapath."
|
||||
@@ -559,14 +573,15 @@ class OVSKernelSwitch( Switch ):
|
||||
self.intf = self.dp
|
||||
if self.inNamespace:
|
||||
error( "OVSKernelSwitch currently only works"
|
||||
" in the root namespace." )
|
||||
" in the root namespace.\n" )
|
||||
exit( 1 )
|
||||
|
||||
@staticmethod
|
||||
def setup():
|
||||
"Ensure any dependencies are loaded; if not, try to load them."
|
||||
moduleDeps( subtract = OF_KMOD, add = OVS_KMOD )
|
||||
pathCheck( 'ovs-dpctl', 'ovs-openflowd' )
|
||||
pathCheck( 'ovs-dpctl', 'ovs-openflowd',
|
||||
moduleName='Open vSwitch (openvswitch.org)')
|
||||
moduleDeps( subtract=OF_KMOD, add=OVS_KMOD )
|
||||
|
||||
def start( self, controllers ):
|
||||
"Start up kernel datapath."
|
||||
@@ -607,10 +622,10 @@ class Controller( Node ):
|
||||
"""A Controller is a Node that is running (or has execed?) an
|
||||
OpenFlow controller."""
|
||||
|
||||
def __init__( self, name, inNamespace=False, controller='controller',
|
||||
cargs='-v ptcp:', cdir=None, defaultIP="127.0.0.1",
|
||||
def __init__( self, name, inNamespace=False, command='controller',
|
||||
cargs='-v ptcp:%d', cdir=None, defaultIP="127.0.0.1",
|
||||
port=6633 ):
|
||||
self.controller = controller
|
||||
self.command = command
|
||||
self.cargs = cargs
|
||||
self.cdir = cdir
|
||||
self.port = port
|
||||
@@ -620,17 +635,17 @@ class Controller( Node ):
|
||||
def start( self ):
|
||||
"""Start <controller> <args> on controller.
|
||||
Log to /tmp/cN.log"""
|
||||
pathCheck( self.controller )
|
||||
pathCheck( self.command )
|
||||
cout = '/tmp/' + self.name + '.log'
|
||||
if self.cdir is not None:
|
||||
self.cmd( 'cd ' + self.cdir )
|
||||
self.cmd( self.controller + ' ' + self.cargs +
|
||||
self.cmd( self.command + ' ' + self.cargs % self.port +
|
||||
' 1>' + cout + ' 2>' + cout + '&' )
|
||||
self.execed = False
|
||||
|
||||
def stop( self ):
|
||||
"Stop controller."
|
||||
self.cmd( 'kill %' + self.controller )
|
||||
self.cmd( 'kill %' + self.command )
|
||||
self.terminate()
|
||||
|
||||
def IP( self, intf=None ):
|
||||
@@ -668,8 +683,8 @@ class NOX( Controller ):
|
||||
noxCoreDir = os.environ[ 'NOX_CORE_DIR' ]
|
||||
|
||||
Controller.__init__( self, name,
|
||||
controller=noxCoreDir + '/nox_core',
|
||||
cargs='--libdir=/usr/local/lib -v -i ptcp: ' +
|
||||
command=noxCoreDir + '/nox_core',
|
||||
cargs='--libdir=/usr/local/lib -v -i ptcp:%s ' % self.port +
|
||||
' '.join( noxArgs ),
|
||||
cdir=noxCoreDir, **kwargs )
|
||||
|
||||
|
||||
Reference in New Issue
Block a user