Revision 216a4b7c bin/mn

View differences:

bin/mn
20 20
from mininet.cli import CLI
21 21
from mininet.log import lg, LEVELS, info
22 22
from mininet.net import Mininet, init
23
from mininet.node import Host, Controller, ControllerParams, NOX
23
from mininet.node import Host, CPULimitedHost, Controller, NOX
24 24
from mininet.node import RemoteController, UserSwitch, OVSKernelSwitch
25
from mininet.link import Intf, TCIntf
25 26
from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
26 27
from mininet.topolib import TreeTopo
27
from mininet.util import makeNumeric
28
from mininet.util import makeNumeric, custom
29

  
30
def customNode( constructors, argStr ):
31
    "Return custom Node constructor based on argStr"
32
    cname, noargs, kwargs = splitArgs( argStr )
33
    constructor = constructors.get( cname, None )
34
    if noargs:
35
        raise Exception( "please specify keyword  arguments for " + cname )
36
    if not constructor:
37
        raise Exception( "error: %s is unknown - please specify one of %s" %
38
               ( cname, constructors.keys() ) )
39
    def custom( *args, **params ):
40
        params.update( kwargs )
41
        print 'CONSTRUCTOR', constructor, 'ARGS', args, 'PARAMS', params
42
        return constructor( *args, **params )
43
    return custom
28 44

  
29 45
# built in topologies, created only when run
30 46
TOPODEF = 'minimal'
......
38 54
SWITCHES = { 'user': UserSwitch,
39 55
            'ovsk': OVSKernelSwitch }
40 56

  
41
HOSTDEF = 'process'
42
HOSTS = { 'process': Host }
57
HOSTDEF = 'proc'
58
HOSTS = { 'proc': Host,
59
          'rt': custom( CPULimitedHost, sched='rt' ),
60
          'cfs': custom( CPULimitedHost, sched='cfs' ) }
43 61

  
44 62
CONTROLLERDEF = 'ref'
45
# a and b are the name and inNamespace params.
46 63
CONTROLLERS = { 'ref': Controller,
47
               'nox_dump': lambda name: NOX( name, 'packetdump' ),
48
               'nox_pysw': lambda name: NOX( name, 'pyswitch' ),
49
               'remote': lambda name: None,
64
               'nox': NOX, 
65
               'remote': RemoteController,
50 66
               'none': lambda name: None }
51 67

  
68
INTFDEF = 'default'
69
INTFS = { 'default': Intf,
70
          'tc': TCIntf }
71

  
72

  
52 73
# optional tests to run
53 74
TESTS = [ 'cli', 'build', 'pingall', 'pingpair', 'iperf', 'all', 'iperfudp',
54 75
         'none' ]
......
56 77
ALTSPELLING = { 'pingall': 'pingAll', 'pingpair': 'pingPair',
57 78
    'iperfudp': 'iperfUdp', 'iperfUDP': 'iperfUdp', 'prefixlen': 'prefixLen' }
58 79

  
59
def buildTopo( topo ):
60
    "Create topology from string with format (object, arg1, arg2,...)."
61
    topo_split = topo.split( ',' )
62
    topo_name = topo_split[ 0 ]
63
    topo_params = topo_split[ 1: ]
64

  
65
    # Convert int and float args; removes the need for every topology to
66
    # be flexible with input arg formats.
67
    topo_seq_params = [ s for s in topo_params if '=' not in s ]
68
    topo_seq_params = [ makeNumeric( s ) for s in topo_seq_params ]
69
    topo_kw_params = {}
70
    for s in [ p for p in topo_params if '=' in p ]:
80

  
81
def splitArgs( argstr ):
82
    """Split argument string into usable python arguments
83
       argstr: argument string with format fn,arg2,kw1=arg3...
84
       returns: fn, args, kwargs"""
85
    split = argstr.split( ',' )
86
    fn = split[ 0 ]
87
    params = split[ 1: ]
88
    # Convert int and float args; removes the need for function
89
    # to be flexible with input arg formats.
90
    args = [ s for s in params if '=' not in s ]
91
    args = map( makeNumeric, args )
92
    kwargs = {}
93
    for s in [ p for p in params if '=' in p ]:
71 94
        key, val = s.split( '=' )
72
        topo_kw_params[ key ] = makeNumeric( val )
95
        kwargs[ key ] = makeNumeric( val )
96
    return fn, args, kwargs
73 97

  
74
    if topo_name not in TOPOS.keys():
75
        raise Exception( 'Invalid topo_name %s' % topo_name )
76
    return TOPOS[ topo_name ]( *topo_seq_params, **topo_kw_params )
98

  
99
def buildTopo( topoStr ):
100
    "Create topology from string with format (object, arg1, arg2,...)."
101
    topo, args, kwargs = splitArgs( topoStr )
102
    if topo not in TOPOS:
103
        raise Exception( 'Invalid topo name %s' % topo )
104
    return TOPOS[ topo ]( *args, **kwargs )
77 105

  
78 106

  
79 107
def addDictOption( opts, choicesDict, default, name, helpStr=None ):
......
87 115
        raise Exception( 'Invalid  default %s for choices dict: %s' %
88 116
                        ( default, name ) )
89 117
    if not helpStr:
90
        helpStr = '[' + ' '.join( choicesDict.keys() ) + ']'
118
        helpStr = '|'.join( sorted( choicesDict.keys() ) ) + '[,param=value...]'
91 119
    opts.add_option( '--' + name,
92
                    type='choice',
93
                    choices=choicesDict.keys(),
120
                    type='string',
94 121
                    default = default,
95 122
                    help = helpStr )
96 123

  
......
135 162
        """Parse command-line args and return options object.
136 163
           returns: opts parse options dict"""
137 164
        if '--custom' in sys.argv:
138
            print "custom in sys.argv"
139 165
            index = sys.argv.index( '--custom' )
140 166
            if len( sys.argv ) > index + 1:
141 167
                custom = sys.argv[ index + 1 ]
......
147 173
        addDictOption( opts, SWITCHES, SWITCHDEF, 'switch' )
148 174
        addDictOption( opts, HOSTS, HOSTDEF, 'host' )
149 175
        addDictOption( opts, CONTROLLERS, CONTROLLERDEF, 'controller' )
176
        addDictOption( opts, INTFS, INTFDEF, 'intf' )
177
        addDictOption( opts, TOPOS, TOPODEF, 'topo' )
150 178

  
151
        opts.add_option( '--topo', type='string', default=TOPODEF,
152
                        help='[' + ' '.join( TOPOS.keys() ) + '],arg1,arg2,'
153
                        '...argN')
154 179
        opts.add_option( '--clean', '-c', action='store_true',
155 180
                        default=False, help='clean and exit' )
156 181
        opts.add_option( '--custom', type='string', default=None,
157 182
                        help='read custom topo and node params from .py file' )
158 183
        opts.add_option( '--test', type='choice', choices=TESTS,
159 184
                        default=TESTS[ 0 ],
160
                        help='[' + ' '.join( TESTS ) + ']' )
185
                        help='|'.join( TESTS ) )
161 186
        opts.add_option( '--xterms', '-x', action='store_true',
162 187
                        default=False, help='spawn xterms for each node' )
163 188
        opts.add_option( '--mac', action='store_true',
164
                        default=False, help='set MACs equal to DPIDs' )
189
                        default=False, help='automatically set host MACs' )
165 190
        opts.add_option( '--arp', action='store_true',
166 191
                        default=False, help='set all-pairs ARP entries' )
167 192
        opts.add_option( '--verbosity', '-v', type='choice',
168 193
                        choices=LEVELS.keys(), default = 'info',
169
                        help = '[' + ' '.join( LEVELS.keys() ) + ']' )
194
                        help = '|'.join( LEVELS.keys() )  )
170 195
        opts.add_option( '--ip', type='string', default='127.0.0.1',
171
                        help='[ip address as a dotted decimal string for a'
172
                        'remote controller]' )
173
        opts.add_option( '--port', type='int', default=6633,
174
                        help='[port integer for a listening remote'
175
                        ' controller]' )
196
                        help='ip address as a dotted decimal string for a'
197
                        'remote controller' )
176 198
        opts.add_option( '--innamespace', action='store_true',
177 199
                        default=False, help='sw and ctrl in namespace?' )
178 200
        opts.add_option( '--listenport', type='int', default=6634,
179
                        help='[base port for passive switch listening'
180
                        ' controller]' )
201
                         help='base port for passive switch listening' )
181 202
        opts.add_option( '--nolistenport', action='store_true',
182 203
                        default=False, help="don't use passive listening port")
183 204
        opts.add_option( '--pre', type='string', default=None,
184
                        help='[CLI script to run before tests]' )
205
                        help='CLI script to run before tests' )
185 206
        opts.add_option( '--post', type='string', default=None,
186
                        help='[CLI script to run after tests]' )
207
                        help='CLI script to run after tests' )
187 208
        opts.add_option( '--prefixlen', type='int', default=8,
188
                        help='[prefix length (e.g. /8) for automatic '
189
                        'network configuration]' )
209
                        help='prefix length (e.g. /8) for automatic '
210
                        'network configuration' )
190 211

  
191 212
        self.options, self.args = opts.parse_args()
192 213

  
......
214 235
        start = time.time()
215 236

  
216 237
        topo = buildTopo( self.options.topo )
217
        switch = SWITCHES[ self.options.switch ]
218
        host = HOSTS[ self.options.host ]
219
        controller = CONTROLLERS[ self.options.controller ]
220
        if self.options.controller == 'remote':
221
            controller = lambda a: RemoteController( a,
222
                             defaultIP=self.options.ip,
223
                             port=self.options.port )
238
        switch = customNode( SWITCHES,  self.options.switch )
239
        host = customNode( HOSTS, self.options.host )
240
        controller = customNode( CONTROLLERS, self.options.controller )
241
        intf = customNode( INTFS, self.options.intf )
224 242

  
225 243
        if self.validate:
226 244
            self.validate( self.options )
227 245

  
228
        # We should clarify what this is actually for...
229
        # It seems like it should be default values for the
230
        # *data* network, so it may be misnamed.
231
        controllerParams = ControllerParams( '10.0.0.0',
232
            self.options.prefixlen)
233

  
234 246
        inNamespace = self.options.innamespace
235 247
        xterms = self.options.xterms
236 248
        mac = self.options.mac
......
238 250
        listenPort = None
239 251
        if not self.options.nolistenport:
240 252
            listenPort = self.options.listenport
241
        mn = Mininet( topo, switch, host, controller, controllerParams,
242
                     inNamespace=inNamespace,
243
                     xterms=xterms, autoSetMacs=mac,
244
                     autoStaticArp=arp, listenPort=listenPort )
253
        mn = Mininet( topo=topo, 
254
                      switch=switch, host=host, controller=controller, 
255
                      intf=intf,
256
                      inNamespace=inNamespace,
257
                      xterms=xterms, autoSetMacs=mac,
258
                      autoStaticArp=arp, listenPort=listenPort )
245 259

  
246 260
        if self.options.pre:
247 261
            CLI( mn, script=self.options.pre )

Also available in: Unified diff