Skip to content
Snippets Groups Projects
Commit bb941950 authored by Brandon Heller's avatar Brandon Heller
Browse files

Add flexible topology input parsing

Now you can pass a topology name followed by params.  For example, to
create a switch with 3 hosts:

  sudo mn --topo single,3
parent 1a40cd04
No related branches found
No related tags found
No related merge requests found
...@@ -21,15 +21,14 @@ from mininet.net import Mininet, init ...@@ -21,15 +21,14 @@ from mininet.net import Mininet, init
from mininet.node import KernelSwitch, Host, Controller, ControllerParams, NOX from mininet.node import KernelSwitch, Host, Controller, ControllerParams, NOX
from mininet.node import RemoteController, UserSwitch, OVSKernelSwitch from mininet.node import RemoteController, UserSwitch, OVSKernelSwitch
from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
from mininet.util import makeNumeric
# built in topologies, created only when run # built in topologies, created only when run
TOPODEF = 'minimal' TOPODEF = 'minimal'
TOPOS = { 'minimal': ( lambda: SingleSwitchTopo( k=2 ) ), TOPOS = { 'minimal': lambda: SingleSwitchTopo( k=2 ),
'reversed': ( lambda: SingleSwitchReversedTopo( k=2 ) ), 'linear': LinearTopo,
'single4': ( lambda: SingleSwitchTopo( k=4 ) ), 'reversed': SingleSwitchReversedTopo,
'single100': ( lambda: SingleSwitchTopo( k=100 ) ), 'single': SingleSwitchTopo }
'linear2': ( lambda: LinearTopo( k=2 ) ),
'linear100': ( lambda: LinearTopo( k=100 ) ) }
SWITCHDEF = 'kernel' SWITCHDEF = 'kernel'
SWITCHES = { 'kernel': KernelSwitch, SWITCHES = { 'kernel': KernelSwitch,
...@@ -51,6 +50,26 @@ CONTROLLERS = { 'ref': Controller, ...@@ -51,6 +50,26 @@ CONTROLLERS = { 'ref': Controller,
TESTS = [ 'cli', 'build', 'pingAll', 'pingPair', 'iperf', 'all', 'iperfUdp' ] TESTS = [ 'cli', 'build', 'pingAll', 'pingPair', 'iperf', 'all', 'iperfUdp' ]
def buildTopo( topo ):
"Create topology from string with format (object, arg1, arg2,...)."
topo_split = topo.split( ',' )
topo_name = topo_split[ 0 ]
topo_params = topo_split[ 1: ]
# Convert int and float args; removes the need for every topology to
# be flexible with input arg formats.
topo_seq_params = [ s for s in topo_params if '=' not in s ]
topo_seq_params = [ makeNumeric( s ) for s in topo_seq_params ]
topo_kw_params = {}
for s in [ s for s in topo_params if '=' in s ]:
key, val = s.split( '=' )
topo_kw_params[ key ] = makeNumeric( val )
if topo_name not in TOPOS.keys():
raise Exception( 'Invalid topo_name %s' % topo_name )
return TOPOS[ topo_name ]( *topo_seq_params, **topo_kw_params )
def addDictOption( opts, choicesDict, default, name, helpStr=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 opts: OptionParser instance
...@@ -118,11 +137,13 @@ class MininetRunner( object ): ...@@ -118,11 +137,13 @@ class MininetRunner( object ):
raise Exception( 'Custom file name not found' ) raise Exception( 'Custom file name not found' )
opts = OptionParser() opts = OptionParser()
addDictOption( opts, TOPOS, TOPODEF, 'topo' )
addDictOption( opts, SWITCHES, SWITCHDEF, 'switch' ) addDictOption( opts, SWITCHES, SWITCHDEF, 'switch' )
addDictOption( opts, HOSTS, HOSTDEF, 'host' ) addDictOption( opts, HOSTS, HOSTDEF, 'host' )
addDictOption( opts, CONTROLLERS, CONTROLLERDEF, 'controller' ) addDictOption( opts, CONTROLLERS, CONTROLLERDEF, 'controller' )
opts.add_option( '--topo', type='string', default=TOPODEF,
help='[' + ' '.join( TOPOS.keys() ) + '],arg1,arg2,'
'...argN')
opts.add_option( '--custom', type='string', default=None, opts.add_option( '--custom', type='string', default=None,
help='read custom topo and node params from .py file' ) help='read custom topo and node params from .py file' )
opts.add_option( '--test', type='choice', choices=TESTS, opts.add_option( '--test', type='choice', choices=TESTS,
...@@ -165,7 +186,7 @@ class MininetRunner( object ): ...@@ -165,7 +186,7 @@ class MininetRunner( object ):
start = time.time() start = time.time()
topo = TOPOS[ self.options.topo ]() # build topology object topo = buildTopo( self.options.topo )
switch = SWITCHES[ self.options.switch ] switch = SWITCHES[ self.options.switch ]
host = HOSTS[ self.options.host ] host = HOSTS[ self.options.host ]
controller = CONTROLLERS[ self.options.controller ] controller = CONTROLLERS[ self.options.controller ]
......
...@@ -153,3 +153,28 @@ def ipParse( ip ): ...@@ -153,3 +153,28 @@ def ipParse( ip ):
"Parse an IP address and return an unsigned int." "Parse an IP address and return an unsigned int."
args = [ int( arg ) for arg in ip.split( '.' ) ] args = [ int( arg ) for arg in ip.split( '.' ) ]
return ipNum( *args ) return ipNum( *args )
def checkInt( s ):
"Check if input string is an int"
try:
int( s )
return True
except ValueError:
return False
def checkFloat( s ):
"Check if input string is a float"
try:
float( s )
return True
except ValueError:
return False
def makeNumeric( s ):
"Convert string to int or float if numeric."
if checkInt( s ):
return int( s )
elif checkFloat( s ):
return float( s )
else:
return s
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment