Munged mn and mnclean into mininet style.

This commit is contained in:
Bob Lantz
2010-02-08 15:42:31 -08:00
parent 7c371cf32a
commit 8895862acf
2 changed files with 130 additions and 133 deletions
Executable → Regular
+50 -51
View File
@@ -1,8 +1,9 @@
#!/usr/bin/env python #!/usr/bin/env python
'''Mininet runner
@author Brandon Heller (brandonh@stanford.edu) """
''' Mininet runner
author: Brandon Heller (brandonh@stanford.edu)
"""
from optparse import OptionParser from optparse import OptionParser
import os.path import os.path
@@ -10,9 +11,9 @@ import time
try: try:
from ripcord.dctopo import TreeTopo, FatTreeTopo, VL2Topo from ripcord.dctopo import TreeTopo, FatTreeTopo, VL2Topo
USE_RIPCORD = True USERIPCORD = True
except ImportError: except ImportError:
USE_RIPCORD = False USERIPCORD = False
from mininet.log import lg, LEVELS from mininet.log import lg, LEVELS
from mininet.net import Mininet, init from mininet.net import Mininet, init
@@ -21,33 +22,33 @@ from mininet.node import RemoteController, UserSwitch, OVSKernelSwitch
from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
# built in topologies, created only when run # built in topologies, created only when run
TOPO_DEF = 'minimal' TOPODEF = 'minimal'
TOPOS = { 'minimal': ( lambda: SingleSwitchTopo( k=2 ) ), TOPOS = { 'minimal': ( lambda: SingleSwitchTopo( k=2 ) ),
'reversed': ( lambda: SingleSwitchReversedTopo( k=2 ) ), 'reversed': ( lambda: SingleSwitchReversedTopo( k=2 ) ),
'single4': ( lambda: SingleSwitchTopo( k=4 ) ), 'single4': ( lambda: SingleSwitchTopo( k=4 ) ),
'single100': ( lambda: SingleSwitchTopo( k=100 ) ), 'single100': ( lambda: SingleSwitchTopo( k=100 ) ),
'linear2': ( lambda: LinearTopo( k=2 ) ), 'linear2': ( lambda: LinearTopo( k=2 ) ),
'linear100': ( lambda: LinearTopo( k=100 ) ) } 'linear100': ( lambda: LinearTopo( k=100 ) ) }
if USE_RIPCORD: if USERIPCORD:
TOPOS_RIPCORD = { TOPOSRIPCORD = {
'tree16': ( lambda: TreeTopo( depth=3, fanout=4 ) ), 'tree16': ( lambda: TreeTopo( depth=3, fanout=4 ) ),
'tree64': ( lambda: TreeTopo( depth=4, fanout=4 ) ), 'tree64': ( lambda: TreeTopo( depth=4, fanout=4 ) ),
'tree1024': ( lambda: TreeTopo( depth=3, fanout=32 ) ), 'tree1024': ( lambda: TreeTopo( depth=3, fanout=32 ) ),
'fattree4': ( lambda: FatTreeTopo( k=4 ) ), 'fattree4': ( lambda: FatTreeTopo( k=4 ) ),
'fattree6': ( lambda: FatTreeTopo( k=6 ) ), 'fattree6': ( lambda: FatTreeTopo( k=6 ) ),
'vl2': ( lambda: VL2Topo( da=4, di=4 ) ), 'vl2': ( lambda: VL2Topo( da=4, di=4 ) ),
'vl2reduced': (lambda: VL2Topo(da = 4, di = 4, edge_down = 1))} 'vl2reduced': ( lambda: VL2Topo( da=4, di=4, edgeDown=1 ) ) }
TOPOS.update(TOPOS_RIPCORD) TOPOS.update( TOPOSRIPCORD )
SWITCH_DEF = 'kernel' SWITCHDEF = 'kernel'
SWITCHES = { 'kernel': KernelSwitch, SWITCHES = { 'kernel': KernelSwitch,
'user': UserSwitch, 'user': UserSwitch,
'ovsk': OVSKernelSwitch } 'ovsk': OVSKernelSwitch }
HOST_DEF = 'process' HOSTDEF = 'process'
HOSTS = { 'process': Host } HOSTS = { 'process': Host }
CONTROLLER_DEF = 'ref' CONTROLLERDEF = 'ref'
# a and b are the name and inNamespace params. # a and b are the name and inNamespace params.
CONTROLLERS = { 'ref': Controller, CONTROLLERS = { 'ref': Controller,
'nox_dump': lambda a, b: NOX( a, b, 'packetdump' ), 'nox_dump': lambda a, b: NOX( a, b, 'packetdump' ),
@@ -56,51 +57,48 @@ CONTROLLERS = {'ref': Controller,
'none': lambda a, b: None } 'none': lambda a, b: None }
# optional tests to run # optional tests to run
TESTS = ['cli', 'build', 'ping_all', 'ping_pair', 'iperf', 'all', 'iperf_udp'] TESTS = [ 'cli', 'build', 'ping_all', 'ping_pair', 'iperf', 'all',
'iperf_udp' ]
def add_dict_option(opts, choices_dict, default, name, help_str = None): def addDictOption( opts, choicesDict, default, name, helpStr=None ):
'''Convenience function to add choices dicts to OptionParser. """Convenience function to add choices dicts to OptionParser.
opts: OptionParser instance
@param opts OptionParser instance choicesDict: dictionary of valid choices, must include default
@param choices_dict dictionary of valid choices, must include default default: default choice key
@param default default choice key name: long option name
@param name long option name help: string"""
@param help string if default not in choicesDict:
'''
if default not in choices_dict:
raise Exception( 'Invalid default %s for choices dict: %s' % raise Exception( 'Invalid default %s for choices dict: %s' %
( default, name ) ) ( default, name ) )
if not help_str: if not helpStr:
help_str = '[' + ' '.join(choices_dict.keys()) + ']' helpStr = '[' + ' '.join( choicesDict.keys() ) + ']'
opts.add_option( '--' + name, opts.add_option( '--' + name,
type='choice', type='choice',
choices = choices_dict.keys(), choices=choicesDict.keys(),
default = default, default = default,
help = help_str) help = helpStr )
class MininetRunner( object ): class MininetRunner( object ):
'''Build, setup, and run Mininet.''' "Build, setup, and run Mininet."
def __init__( self ): def __init__( self ):
'''Init.''' "Init."
self.options = None self.options = None
self.parse_args() self.parseArgs()
self.setup() self.setup()
self.begin() self.begin()
def parse_args(self): def parseArgs( self ):
'''Parse command-line args and return options object. """Parse command-line args and return options object.
returns: opts parse options dict"""
@return opts parse options dict
'''
opts = OptionParser() opts = OptionParser()
add_dict_option(opts, TOPOS, TOPO_DEF, 'topo') addDictOption( opts, TOPOS, TOPODEF, 'topo' )
add_dict_option(opts, SWITCHES, SWITCH_DEF, 'switch') addDictOption( opts, SWITCHES, SWITCHDEF, 'switch' )
add_dict_option(opts, HOSTS, HOST_DEF, 'host') addDictOption( opts, HOSTS, HOSTDEF, 'host' )
add_dict_option(opts, CONTROLLERS, CONTROLLER_DEF, 'controller') addDictOption( opts, CONTROLLERS, CONTROLLERDEF, 'controller' )
opts.add_option( '--custom', type='string', default=None, opts.add_option( '--custom', type='string', default=None,
help='read custom mininet from current dir' ) help='read custom mininet from current dir' )
@@ -127,7 +125,7 @@ class MininetRunner(object):
self.options = opts.parse_args()[ 0 ] self.options = opts.parse_args()[ 0 ]
def setup( self ): def setup( self ):
'''Setup and validate environment.''' "Setup and validate environment."
# set logging verbosity # set logging verbosity
lg.setLogLevel( self.options.verbosity ) lg.setLogLevel( self.options.verbosity )
@@ -136,8 +134,9 @@ class MininetRunner(object):
init() init()
# check for invalid combinations # check for invalid combinations
if self.options.controller == 'ref' and \ if ( self.options.controller == 'ref' and
(('fattree' in self.options.topo) or ('vl2' in self.options.topo)): ( ( 'fattree' in self.options.topo ) or
( 'vl2' in self.options.topo ) ) ):
raise Exception( 'multipath topos require multipath-capable ' raise Exception( 'multipath topos require multipath-capable '
'controller.' ) 'controller.' )
@@ -147,7 +146,7 @@ class MininetRunner(object):
self.options.custom ) self.options.custom )
def begin( self ): def begin( self ):
'''Create and run mininet.''' "Create and run mininet."
start = time.time() start = time.time()
@@ -157,20 +156,20 @@ class MininetRunner(object):
controller = CONTROLLERS[ self.options.controller ] controller = CONTROLLERS[ self.options.controller ]
if self.options.controller == 'remote': if self.options.controller == 'remote':
controller = lambda a, b: RemoteController( a, b, controller = lambda a, b: RemoteController( a, b,
ip_address = self.options.ip, ipAddress=self.options.ip,
port=self.options.port ) port=self.options.port )
controller_params = ControllerParams(0x0a000000, 8) # 10.0.0.0/8 controllerParams = ControllerParams( 0x0a000000, 8 ) # 10.0.0.0/8
in_namespace = self.options.in_namespace inNamespace = self.options.inNamespace
xterms = self.options.xterms xterms = self.options.xterms
mac = self.options.mac mac = self.options.mac
arp = self.options.arp arp = self.options.arp
mn = None mn = None
if not self.options.custom: if not self.options.custom:
mn = Mininet(topo, switch, host, controller, controller_params, mn = Mininet( topo, switch, host, controller, controllerParams,
in_namespace = in_namespace, inNamespace=inNamespace,
xterms = xterms, auto_set_macs = mac, xterms=xterms, autoSetMacs=mac,
auto_static_arp = arp) autoStaticArp=arp )
else: else:
globals_ = {} globals_ = {}
locals_ = {} locals_ = {}
Executable → Regular
+3 -5
View File
@@ -1,7 +1,8 @@
#!/usr/bin/env python #!/usr/bin/env python
"""Mininet Cleanup
@author Bob Lantz (rlantz@cs.stanford.edu) """
Mininet Cleanup
author: Bob Lantz (rlantz@cs.stanford.edu)
Unfortunately, Mininet and OpenFlow don't always clean up Unfortunately, Mininet and OpenFlow don't always clean up
properly after themselves. Until they do (or until cleanup properly after themselves. Until they do (or until cleanup
@@ -15,17 +16,14 @@ from subprocess import Popen, PIPE
from mininet.xterm import cleanUpScreens from mininet.xterm import cleanUpScreens
def sh( cmd ): def sh( cmd ):
"Print a command and send it to the shell" "Print a command and send it to the shell"
print cmd print cmd
return Popen( [ '/bin/sh', '-c', cmd ], stdout=PIPE ).communicate()[ 0 ] return Popen( [ '/bin/sh', '-c', cmd ], stdout=PIPE ).communicate()[ 0 ]
def cleanup(): def cleanup():
"""Clean up junk which might be left over from old runs; """Clean up junk which might be left over from old runs;
do fast stuff before slow dp and link removal!""" do fast stuff before slow dp and link removal!"""
print "*** Removing excess controllers/ofprotocols/ofdatapaths/pings/noxes" print "*** Removing excess controllers/ofprotocols/ofdatapaths/pings/noxes"
zombies = 'controller ofprotocol ofdatapath ping nox_core lt-nox_core ' zombies = 'controller ofprotocol ofdatapath ping nox_core lt-nox_core '
zombies += 'udpbwtest' zombies += 'udpbwtest'