Newer
Older
"""
Mininet runner
author: Brandon Heller (brandonh@stanford.edu)
"""
from optparse import OptionParser
try:
from ripcord.dctopo import TreeTopo, FatTreeTopo, VL2Topo
from mininet.net import Mininet, init
from mininet.node import KernelSwitch, Host, Controller, ControllerParams, NOX
from mininet.node import RemoteController, UserSwitch, OVSKernelSwitch
from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
# built in topologies, created only when run
TOPODEF = 'minimal'
TOPOS = { 'minimal': ( lambda: SingleSwitchTopo( k=2 ) ),
'reversed': ( lambda: SingleSwitchReversedTopo( k=2 ) ),
'single4': ( lambda: SingleSwitchTopo( k=4 ) ),
'single100': ( lambda: SingleSwitchTopo( k=100 ) ),
'linear2': ( lambda: LinearTopo( k=2 ) ),
'linear100': ( lambda: LinearTopo( k=100 ) ) }
if USERIPCORD:
TOPOSRIPCORD = {
'tree16': ( lambda: TreeTopo( depth=3, fanout=4 ) ),
'tree64': ( lambda: TreeTopo( depth=4, fanout=4 ) ),
'tree1024': ( lambda: TreeTopo( depth=3, fanout=32 ) ),
'fattree4': ( lambda: FatTreeTopo( k=4 ) ),
'fattree6': ( lambda: FatTreeTopo( k=6 ) ),
'vl2': ( lambda: VL2Topo( da=4, di=4 ) ),
'vl2reduced': ( lambda: VL2Topo( da=4, di=4, edgeDown=1 ) ) }
TOPOS.update( TOPOSRIPCORD )
SWITCHDEF = 'kernel'
SWITCHES = { 'kernel': KernelSwitch,
HOSTDEF = 'process'
HOSTS = { 'process': Host }
# a and b are the name and inNamespace params.
CONTROLLERS = { 'ref': Controller,
'nox_dump': lambda a, b: NOX( a, b, 'packetdump' ),
'nox_pysw': lambda a, b: NOX( a, b, 'pyswitch' ),
'remote': lambda a, b: None,
TESTS = [ 'cli', 'build', 'pingAll', 'pingPair', 'iperf', 'all',
'iperfUdp' ]
def addDictOption( opts, choicesDict, default, name, helpStr=None ):
"""Convenience function to add choices dicts to OptionParser.
opts: OptionParser instance
choicesDict: dictionary of valid choices, must include default
default: default choice key
name: long option name
help: string"""
if default not in choicesDict:
raise Exception( 'Invalid default %s for choices dict: %s' %
( default, name ) )
if not helpStr:
helpStr = '[' + ' '.join( choicesDict.keys() ) + ']'
opts.add_option( '--' + name,
type='choice',
choices=choicesDict.keys(),
class MininetRunner( object ):
"Build, setup, and run Mininet."
self.setup()
self.begin()
def parseArgs( self ):
"""Parse command-line args and return options object.
returns: opts parse options dict"""
addDictOption( opts, TOPOS, TOPODEF, 'topo' )
addDictOption( opts, SWITCHES, SWITCHDEF, 'switch' )
addDictOption( opts, HOSTS, HOSTDEF, 'host' )
addDictOption( opts, CONTROLLERS, CONTROLLERDEF, 'controller' )
opts.add_option( '--custom', type='string', default=None,
help='read custom mininet from current dir' )
opts.add_option( '--test', type='choice', choices=TESTS,
default=TESTS[ 0 ],
help='[' + ' '.join( TESTS ) + ']' )
opts.add_option( '--xterms', '-x', action='store_true',
default=False, help='spawn xterms for each node' )
opts.add_option( '--mac', action='store_true',
default=False, help='set MACs equal to DPIDs' )
opts.add_option( '--arp', action='store_true',
default=False, help='set all-pairs ARP entries' )
opts.add_option( '--verbosity', '-v', type='choice',
choices=LEVELS.keys(), default = 'info',
help = '[' + ' '.join( LEVELS.keys() ) + ']' )
opts.add_option( '--ip', type='string', default='127.0.0.1',
help='[ip address as a dotted decimal string for a'
'remote controller]' )
opts.add_option( '--port', type='string', default=6633,
help='[port integer for a listening remote'
' controller]' )
opts.add_option( '--inNamespace', action='store_true',
default=False, help='sw and ctrl in namespace?' )
self.options = opts.parse_args()[ 0 ]
def setup( self ):
"Setup and validate environment."
lg.setLogLevel( self.options.verbosity )
# validate environment setup
init()
if ( self.options.controller == 'ref' and
( ( 'fattree' in self.options.topo ) or
( 'vl2' in self.options.topo ) ) ):
raise Exception( 'multipath topos require multipath-capable '
'controller.' )
if not os.path.isfile( self.options.custom ):
raise Exception( 'could not find custom file: %s' %
self.options.custom )
def begin( self ):
"Create and run mininet."
topo = TOPOS[ self.options.topo ]() # build topology object
switch = SWITCHES[ self.options.switch ]
host = HOSTS[ self.options.host ]
controller = CONTROLLERS[ self.options.controller ]
if self.options.controller == 'remote':
controller = lambda a, b: RemoteController( a, b,
ipAddress=self.options.ip,
port=self.options.port )
controllerParams = ControllerParams( 0x0a000000, 8 ) # 10.0.0.0/8
inNamespace = self.options.inNamespace
mac = self.options.mac
arp = self.options.arp
mn = None
if not self.options.custom:
mn = Mininet( topo, switch, host, controller, controllerParams,
inNamespace=inNamespace,
xterms=xterms, autoSetMacs=mac,
autoStaticArp=arp )
else:
globals_ = {}
locals_ = {}
execfile( self.options.custom, globals_, locals_ )
raise Exception( 'could not find mn var in custom file' )
test = self.options.test
if test != 'build':
if test == 'cli':
elif test == 'all':
mn.start()
mn.ping()
mn.iperf()
elapsed = float( time.time() - start )
print ( 'completed in %0.3f seconds' % elapsed )
if __name__ == "__main__":