Merge OVSBatch into OVSSwitch
Note that we are changing the interface of batchStartup/Shutdown slightly so that the method can choose not to start some of the switches. We might wish to refine this a bit...
This commit is contained in:
@@ -27,7 +27,7 @@ from mininet.net import Mininet, MininetWithControlNet, VERSION
|
||||
from mininet.node import ( Host, CPULimitedHost, Controller, OVSController,
|
||||
RYU, NOX, RemoteController, findController,
|
||||
DefaultController,
|
||||
UserSwitch, OVSSwitch, OVSBridge, OVSBatch,
|
||||
UserSwitch, OVSSwitch, OVSBridge,
|
||||
OVSLegacyKernelSwitch, IVSSwitch )
|
||||
from mininet.nodelib import LinuxBridge
|
||||
from mininet.link import Link, TCLink, OVSLink
|
||||
@@ -62,7 +62,6 @@ SWITCHES = { 'user': UserSwitch,
|
||||
# Keep ovsk for compatibility with 2.0
|
||||
'ovsk': OVSSwitch,
|
||||
'ovsl': OVSLegacyKernelSwitch,
|
||||
'ovsbatch': OVSBatch, # experimental!!'
|
||||
'ivs': IVSSwitch,
|
||||
'lxbr': LinuxBridge,
|
||||
'default': OVSSwitch }
|
||||
|
||||
+11
-1
@@ -280,6 +280,11 @@ class RemoteOVSSwitch( RemoteMixin, OVSSwitch ):
|
||||
|
||||
OVSVersions = {}
|
||||
|
||||
def __init__( self, *args, **kwargs ):
|
||||
# No batch startup yet
|
||||
kwargs.update( batch=False )
|
||||
super( RemoteOVSSwitch, self ).__init__( *args, **kwargs )
|
||||
|
||||
def isOldOVS( self ):
|
||||
"Is remote switch using an old OVS version?"
|
||||
cls = type( self )
|
||||
@@ -292,10 +297,15 @@ class RemoteOVSSwitch( RemoteMixin, OVSSwitch ):
|
||||
return ( StrictVersion( cls.OVSVersions[ self.server ] ) <
|
||||
StrictVersion( '1.10' ) )
|
||||
|
||||
@classmethod
|
||||
def batchStartup( cls, *_args, **_kwargs ):
|
||||
"Not implemented yet"
|
||||
return [] # no switches started
|
||||
|
||||
@classmethod
|
||||
def batchShutdown( cls, *_args, **_kwargs ):
|
||||
"Not implemented yet"
|
||||
return False
|
||||
return [] # no switchest stopped
|
||||
|
||||
|
||||
class RemoteLink( Link ):
|
||||
|
||||
+8
-6
@@ -485,9 +485,11 @@ class Mininet( object ):
|
||||
for swclass, switches in groupby(
|
||||
sorted( self.switches, key=type ), type ):
|
||||
switches = tuple( switches )
|
||||
if ( hasattr( swclass, 'batchStartup' ) and
|
||||
swclass.batchStartup( switches ) ):
|
||||
started.update( { s: s for s in switches } )
|
||||
if hasattr( swclass, 'batchStartup' ):
|
||||
print "STARTING", switches
|
||||
success = swclass.batchStartup( switches )
|
||||
print "STARTED", success
|
||||
started.update( { s: s for s in success } )
|
||||
info( '\n' )
|
||||
if self.waitConn:
|
||||
self.waitConnected()
|
||||
@@ -512,9 +514,9 @@ class Mininet( object ):
|
||||
for swclass, switches in groupby(
|
||||
sorted( self.switches, key=type ), type ):
|
||||
switches = tuple( switches )
|
||||
if ( hasattr( swclass, 'batchShutdown' ) and
|
||||
swclass.batchShutdown( switches ) ):
|
||||
stopped.update( { s: s for s in switches } )
|
||||
if hasattr( swclass, 'batchShutdown' ):
|
||||
success = swclass.batchShutdown( switches )
|
||||
stopped.update( { s: s for s in success } )
|
||||
for switch in self.switches:
|
||||
info( switch.name + ' ' )
|
||||
if switch not in stopped:
|
||||
|
||||
+66
-73
@@ -1059,7 +1059,7 @@ class OVSSwitch( Switch ):
|
||||
|
||||
def __init__( self, name, failMode='secure', datapath='kernel',
|
||||
inband=False, protocols=None,
|
||||
reconnectms=1000, stp=False, **params ):
|
||||
reconnectms=1000, stp=False, batch=True, **params ):
|
||||
"""name: name for switch
|
||||
failMode: controller loss behavior (secure|open)
|
||||
datapath: userspace or kernel mode (kernel|user)
|
||||
@@ -1067,7 +1067,8 @@ class OVSSwitch( Switch ):
|
||||
protocols: use specific OpenFlow version(s) (e.g. OpenFlow13)
|
||||
Unspecified (or old OVS version) uses OVS default
|
||||
reconnectms: max reconnect timeout in ms (0/None for default)
|
||||
stp: enable STP (False, requires failMode=standalone)"""
|
||||
stp: enable STP (False, requires failMode=standalone)
|
||||
batch: enable batch startup (True)"""
|
||||
Switch.__init__( self, name, **params )
|
||||
self.failMode = failMode
|
||||
self.datapath = datapath
|
||||
@@ -1076,6 +1077,8 @@ class OVSSwitch( Switch ):
|
||||
self.reconnectms = reconnectms
|
||||
self.stp = stp
|
||||
self._uuids = [] # controller UUIDs
|
||||
self.batch = batch
|
||||
self.commands = [] # saved commands for batch startup
|
||||
|
||||
@classmethod
|
||||
def setup( cls ):
|
||||
@@ -1105,29 +1108,17 @@ class OVSSwitch( Switch ):
|
||||
return ( StrictVersion( cls.OVSVersion ) <
|
||||
StrictVersion( '1.10' ) )
|
||||
|
||||
@classmethod
|
||||
def batchShutdown( cls, switches ):
|
||||
"Shut down a list of OVS switches"
|
||||
delcmd = 'del-br %s'
|
||||
if not cls.isOldOVS():
|
||||
delcmd = '--if-exists ' + delcmd
|
||||
# First, delete them all from ovsdb
|
||||
quietRun( 'ovs-vsctl ' +
|
||||
' -- '.join( delcmd % s for s in switches ) )
|
||||
# Next, shut down all of the processes
|
||||
pids = ' '.join( str( switch.pid ) for switch in switches )
|
||||
quietRun( 'kill -HUP ' + pids )
|
||||
for switch in switches:
|
||||
switch.shell = None
|
||||
return True
|
||||
|
||||
def dpctl( self, *args ):
|
||||
"Run ovs-ofctl command"
|
||||
return self.cmd( 'ovs-ofctl', args[ 0 ], self, *args[ 1: ] )
|
||||
|
||||
def vsctl( self, *args, **kwargs ):
|
||||
"Run ovs-vsctl command"
|
||||
return self.cmd( 'ovs-vsctl', *args, **kwargs )
|
||||
"Run ovs-vsctl command (or queue for later execution)"
|
||||
if self.batch:
|
||||
cmd = ' '.join( str( arg ).strip() for arg in args )
|
||||
self.commands.append( cmd )
|
||||
else:
|
||||
return self.cmd( 'ovs-vsctl', *args, **kwargs )
|
||||
|
||||
@staticmethod
|
||||
def TCReapply( intf ):
|
||||
@@ -1217,7 +1208,7 @@ class OVSSwitch( Switch ):
|
||||
if self.reconnectms:
|
||||
ccmd += ' max_backoff=%d' % self.reconnectms
|
||||
cargs = ' '.join( ccmd % ( name, target )
|
||||
for name, target in clist )
|
||||
for name, target in clist )
|
||||
# Controller ID list
|
||||
cids = ','.join( '@%s' % name for name, _target in clist )
|
||||
# Try to delete any existing bridges with the same name
|
||||
@@ -1229,10 +1220,43 @@ class OVSSwitch( Switch ):
|
||||
' -- set bridge %s controller=[%s]' % ( self, cids ) +
|
||||
self.bridgeOpts() +
|
||||
intfs )
|
||||
# XXX BROKEN - need to fix this!!
|
||||
# If necessary, restore TC config overwritten by OVS
|
||||
# for intf in self.intfList():
|
||||
# self.TCReapply( intf )
|
||||
if not self.batch:
|
||||
for intf in self.intfList():
|
||||
self.TCReapply( intf )
|
||||
|
||||
# This should be ~ int( quietRun( 'getconf ARG_MAX' ) ),
|
||||
# but the real limit seems to be much lower
|
||||
argmax = 128000
|
||||
|
||||
@classmethod
|
||||
def batchStartup( cls, switches, run=errRun ):
|
||||
"""Batch startup for OVS
|
||||
switches: switches to start up
|
||||
run: function to run commands (errRun)"""
|
||||
info( '...' )
|
||||
cmds = 'ovs-vsctl'
|
||||
for switch in switches:
|
||||
if switch.isOldOVS():
|
||||
# Ideally we'd optimize this also
|
||||
run( 'ovs-vsctl del-br %s' % switch )
|
||||
for cmd in switch.commands:
|
||||
cmd = cmd.strip()
|
||||
# Don't exceed ARG_MAX
|
||||
if len( cmds ) + len( cmd ) >= cls.argmax:
|
||||
run( cmds, shell=True )
|
||||
cmds = 'ovs-vsctl'
|
||||
cmds += ' ' + cmd
|
||||
switch.cmds = []
|
||||
switch.batch = False
|
||||
if cmds:
|
||||
run( cmds, shell=True )
|
||||
# Reapply link config if necessary...
|
||||
for switch in switches:
|
||||
for intf in switch.intfs.itervalues():
|
||||
if isinstance( intf, TCIntf ):
|
||||
intf.config( **intf.params )
|
||||
return switches
|
||||
|
||||
def stop( self, deleteIntfs=True ):
|
||||
"""Terminate OVS switch.
|
||||
@@ -1242,6 +1266,22 @@ class OVSSwitch( Switch ):
|
||||
self.cmd( 'ip link del', self )
|
||||
super( OVSSwitch, self ).stop( deleteIntfs )
|
||||
|
||||
@classmethod
|
||||
def batchShutdown( cls, switches, run=errRun ):
|
||||
"Shut down a list of OVS switches"
|
||||
delcmd = 'del-br %s'
|
||||
if not cls.isOldOVS():
|
||||
delcmd = '--if-exists ' + delcmd
|
||||
# First, delete them all from ovsdb
|
||||
run( 'ovs-vsctl ' +
|
||||
' -- '.join( delcmd % s for s in switches ) )
|
||||
# Next, shut down all of the processes
|
||||
pids = ' '.join( str( switch.pid ) for switch in switches )
|
||||
run( 'kill -HUP ' + pids )
|
||||
for switch in switches:
|
||||
switch.shell = None
|
||||
return switches
|
||||
|
||||
|
||||
OVSKernelSwitch = OVSSwitch
|
||||
|
||||
@@ -1265,54 +1305,6 @@ class OVSBridge( OVSSwitch ):
|
||||
return True
|
||||
|
||||
|
||||
class OVSBatch( OVSSwitch ):
|
||||
"Experiment: batch startup of OVS switches"
|
||||
|
||||
# This should be ~ int( quietRun( 'getconf ARG_MAX' ) ),
|
||||
# but the real limit seems to be much lower
|
||||
argmax = 128000
|
||||
|
||||
def __init__( self, *args, **kwargs ):
|
||||
self.commands = []
|
||||
self.started = False
|
||||
super( OVSBatch, self ).__init__( *args, **kwargs )
|
||||
|
||||
@classmethod
|
||||
def batchStartup( cls, switches ):
|
||||
"Batch startup for OVS"
|
||||
info( '...' )
|
||||
cmds = 'ovs-vsctl'
|
||||
for switch in switches:
|
||||
if cls.isOldOVS():
|
||||
quietRun( 'ovs-vsctl del-br %s' % switch )
|
||||
for cmd in switch.commands:
|
||||
cmd = cmd.strip()
|
||||
# Don't exceed ARG_MAX
|
||||
if len( cmds ) + len( cmd ) >= cls.argmax:
|
||||
errRun( cmds, shell=True )
|
||||
cmds = 'ovs-vsctl'
|
||||
cmds += ' ' + cmd
|
||||
switch.started = True
|
||||
if cmds:
|
||||
errRun( cmds, shell=True )
|
||||
return True
|
||||
|
||||
def vsctl( self, *args, **kwargs ):
|
||||
"Append ovs-vsctl command to list for later execution"
|
||||
if self.started:
|
||||
return super( OVSBatch, self).vsctl( *args, **kwargs )
|
||||
cmd = ' '.join( str( arg ).strip() for arg in args )
|
||||
self.commands.append( cmd )
|
||||
|
||||
def start( self, *args, **kwargs ):
|
||||
super( OVSBatch, self ).start( *args, **kwargs )
|
||||
self.started = True
|
||||
|
||||
def stop( self, *args, **kwargs ):
|
||||
super( OVSBatch, self ).stop( *args, **kwargs )
|
||||
self.started = False
|
||||
|
||||
|
||||
class IVSSwitch( Switch ):
|
||||
"Indigo Virtual Switch"
|
||||
|
||||
@@ -1338,6 +1330,7 @@ class IVSSwitch( Switch ):
|
||||
"Kill each IVS switch, to be waited on later in stop()"
|
||||
for switch in switches:
|
||||
switch.cmd( 'kill %ivs' )
|
||||
return switches
|
||||
|
||||
def start( self, controllers ):
|
||||
"Start up a new IVS switch"
|
||||
@@ -1556,4 +1549,4 @@ def DefaultController( name, controllers=DefaultControllers, **kwargs ):
|
||||
controller = findController( controllers )
|
||||
if not controller:
|
||||
raise Exception( 'Could not find a default OpenFlow controller' )
|
||||
return controller( name, **kwargs )
|
||||
return contr
|
||||
Reference in New Issue
Block a user