Statistics
| Branch: | Tag: | Revision:

mininet / bin / mn @ 83097ff9

History | View | Annotate | Download (7.25 KB)

1
#!/usr/bin/env python
2

    
3
"""
4
Mininet runner
5
author: Brandon Heller (brandonh@stanford.edu)
6
"""
7

    
8
from optparse import OptionParser
9
import os.path
10
import time
11

    
12
try:
13
    from ripcord.dctopo import TreeTopo, FatTreeTopo, VL2Topo
14
    USERIPCORD = True
15
except ImportError:
16
    USERIPCORD = False
17

    
18
from mininet.log import lg, LEVELS
19
from mininet.net import Mininet, init
20
from mininet.node import KernelSwitch, Host, Controller, ControllerParams, NOX
21
from mininet.node import RemoteController, UserSwitch, OVSKernelSwitch
22
from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
23

    
24
# built in topologies, created only when run
25
TOPODEF = 'minimal'
26
TOPOS = { 'minimal': ( lambda: SingleSwitchTopo( k=2 ) ),
27
         'reversed': ( lambda: SingleSwitchReversedTopo( k=2 ) ),
28
         'single4': ( lambda: SingleSwitchTopo( k=4 ) ),
29
         'single100': ( lambda: SingleSwitchTopo( k=100 ) ),
30
         'linear2': ( lambda: LinearTopo( k=2 ) ),
31
         'linear100': ( lambda: LinearTopo( k=100 ) ) }
32
if USERIPCORD:
33
    TOPOSRIPCORD = {
34
         'tree16': ( lambda: TreeTopo( depth=3, fanout=4 ) ),
35
         'tree64': ( lambda: TreeTopo( depth=4, fanout=4 ) ),
36
         'tree1024': ( lambda: TreeTopo( depth=3, fanout=32 ) ),
37
         'fattree4': ( lambda: FatTreeTopo( k=4 ) ),
38
         'fattree6': ( lambda: FatTreeTopo( k=6 ) ),
39
         'vl2': ( lambda: VL2Topo( da=4, di=4 ) ),
40
         'vl2reduced': ( lambda: VL2Topo( da=4, di=4, edgeDown=1 ) ) }
41
    TOPOS.update( TOPOSRIPCORD )
42

    
43
SWITCHDEF = 'kernel'
44
SWITCHES = { 'kernel': KernelSwitch,
45
            'user': UserSwitch,
46
            'ovsk': OVSKernelSwitch }
47

    
48
HOSTDEF = 'process'
49
HOSTS = { 'process': Host }
50

    
51
CONTROLLERDEF = 'ref'
52
# a and b are the name and inNamespace params.
53
CONTROLLERS = { 'ref': Controller,
54
               'nox_dump': lambda a, b: NOX( a, b, 'packetdump' ),
55
               'nox_pysw': lambda a, b: NOX( a, b, 'pyswitch' ),
56
               'remote': lambda a, b: None,
57
               'none': lambda a, b: None }
58

    
59
# optional tests to run
60
TESTS = [ 'cli', 'build', 'pingAll', 'pingPair', 'iperf', 'all',
61
    'iperfUdp' ]
62

    
63

    
64
def addDictOption( opts, choicesDict, default, name, helpStr=None ):
65
    """Convenience function to add choices dicts to OptionParser.
66
       opts: OptionParser instance
67
       choicesDict: dictionary of valid choices, must include default
68
       default: default choice key
69
       name: long option name
70
       help: string"""
71
    if default not in choicesDict:
72
        raise Exception( 'Invalid  default %s for choices dict: %s' %
73
                        ( default, name ) )
74
    if not helpStr:
75
        helpStr = '[' + ' '.join( choicesDict.keys() ) + ']'
76
    opts.add_option( '--' + name,
77
                    type='choice',
78
                    choices=choicesDict.keys(),
79
                    default = default,
80
                    help = helpStr )
81

    
82

    
83
class MininetRunner( object ):
84
    "Build, setup, and run Mininet."
85

    
86
    def __init__( self ):
87
        "Init."
88
        self.options = None
89

    
90
        self.parseArgs()
91
        self.setup()
92
        self.begin()
93

    
94
    def parseArgs( self ):
95
        """Parse command-line args and return options object.
96
           returns: opts parse options dict"""
97
        opts = OptionParser()
98
        addDictOption( opts, TOPOS, TOPODEF, 'topo' )
99
        addDictOption( opts, SWITCHES, SWITCHDEF, 'switch' )
100
        addDictOption( opts, HOSTS, HOSTDEF, 'host' )
101
        addDictOption( opts, CONTROLLERS, CONTROLLERDEF, 'controller' )
102

    
103
        opts.add_option( '--custom', type='string', default=None,
104
                        help='read custom mininet from current dir' )
105
        opts.add_option( '--test', type='choice', choices=TESTS,
106
                        default=TESTS[ 0 ],
107
                        help='[' + ' '.join( TESTS ) + ']' )
108
        opts.add_option( '--xterms', '-x', action='store_true',
109
                        default=False, help='spawn xterms for each node' )
110
        opts.add_option( '--mac', action='store_true',
111
                        default=False, help='set MACs equal to DPIDs' )
112
        opts.add_option( '--arp', action='store_true',
113
                        default=False, help='set all-pairs ARP entries' )
114
        opts.add_option( '--verbosity', '-v', type='choice',
115
                        choices=LEVELS.keys(), default = 'info',
116
                        help = '[' + ' '.join( LEVELS.keys() ) + ']' )
117
        opts.add_option( '--ip', type='string', default='127.0.0.1',
118
                        help='[ip address as a dotted decimal string for a'
119
                        'remote controller]' )
120
        opts.add_option( '--port', type='string', default=6633,
121
                        help='[port integer for a listening remote'
122
                        ' controller]' )
123
        opts.add_option( '--inNamespace', action='store_true',
124
                        default=False, help='sw and ctrl in namespace?' )
125
        self.options = opts.parse_args()[ 0 ]
126

    
127
    def setup( self ):
128
        "Setup and validate environment."
129

    
130
        # set logging verbosity
131
        lg.setLogLevel( self.options.verbosity )
132

    
133
        # validate environment setup
134
        init()
135

    
136
        # check for invalid combinations
137
        if ( self.options.controller == 'ref' and
138
            ( ( 'fattree' in self.options.topo ) or
139
              ( 'vl2' in self.options.topo ) ) ):
140
            raise Exception( 'multipath topos require multipath-capable '
141
                            'controller.' )
142

    
143
        if self.options.custom:
144
            if not os.path.isfile( self.options.custom ):
145
                raise Exception( 'could not find custom file: %s' %
146
                    self.options.custom )
147

    
148
    def begin( self ):
149
        "Create and run mininet."
150

    
151
        start = time.time()
152

    
153
        topo = TOPOS[ self.options.topo ]() # build topology object
154
        switch = SWITCHES[ self.options.switch ]
155
        host = HOSTS[ self.options.host ]
156
        controller = CONTROLLERS[ self.options.controller ]
157
        if self.options.controller == 'remote':
158
            controller = lambda a, b: RemoteController( a, b,
159
                             ipAddress=self.options.ip,
160
                             port=self.options.port )
161

    
162
        controllerParams = ControllerParams( 0x0a000000, 8 ) # 10.0.0.0/8
163
        inNamespace = self.options.inNamespace
164
        xterms = self.options.xterms
165
        mac = self.options.mac
166
        arp = self.options.arp
167
        mn = None
168
        if not self.options.custom:
169
            mn = Mininet( topo, switch, host, controller, controllerParams,
170
                         inNamespace=inNamespace,
171
                         xterms=xterms, autoSetMacs=mac,
172
                         autoStaticArp=arp )
173
        else:
174
            globals_ = {}
175
            locals_ = {}
176
            execfile( self.options.custom, globals_, locals_ )
177
            if 'mn' not in locals_:
178
                raise Exception( 'could not find mn var in custom file' )
179
            else:
180
                mn = locals_[ 'mn' ]
181

    
182
        test = self.options.test
183
        if test != 'build':
184
            if test == 'cli':
185
                mn.interact()
186
            elif test == 'all':
187
                mn.start()
188
                mn.ping()
189
                mn.iperf()
190
                mn.stop()
191
            else:
192
                mn.run( test )
193

    
194
        elapsed = float( time.time() - start )
195
        print ( 'completed in %0.3f seconds' % elapsed )
196

    
197

    
198
if __name__ == "__main__":
199
    MininetRunner()