Statistics
| Branch: | Tag: | Revision:

mininet / bin / mn @ 80a8fa62

History | View | Annotate | Download (7.26 KB)

1
#!/usr/bin/env python
2
'''Mininet runner
3

    
4
@author Brandon Heller (brandonh@stanford.edu)
5
'''
6

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

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

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

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

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

    
47
HOST_DEF = 'process'
48
HOSTS = {'process': Host}
49

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

    
58
# optional tests to run
59
TESTS = ['cli', 'build', 'ping_all', 'ping_pair', 'iperf', 'all', 'iperf_udp']
60

    
61

    
62
def add_dict_option(opts, choices_dict, default, name, help_str = None):
63
    '''Convenience function to add choices dicts to OptionParser.
64

    
65
    @param opts OptionParser instance
66
    @param choices_dict dictionary of valid choices, must include default
67
    @param default default choice key
68
    @param name long option name
69
    @param help string
70
    '''
71
    if default not in choices_dict:
72
        raise Exception('Invalid  default %s for choices dict: %s' %
73
                        (default, name))
74
    if not help_str:
75
        help_str = '[' + ' '.join(choices_dict.keys()) + ']'
76
    opts.add_option('--' + name,
77
                    type = 'choice',
78
                    choices = choices_dict.keys(),
79
                    default = default,
80
                    help = help_str)
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.parse_args()
91
        self.setup()
92
        self.begin()
93

    
94
    def parse_args(self):
95
        '''Parse command-line args and return options object.
96

    
97
        @return opts parse options dict
98
        '''
99
        opts = OptionParser()
100
        add_dict_option(opts, TOPOS, TOPO_DEF, 'topo')
101
        add_dict_option(opts, SWITCHES, SWITCH_DEF, 'switch')
102
        add_dict_option(opts, HOSTS, HOST_DEF, 'host')
103
        add_dict_option(opts, CONTROLLERS, CONTROLLER_DEF, 'controller')
104

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

    
129
    def setup(self):
130
        '''Setup and validate environment.'''
131

    
132
        # set logging verbosity
133
        lg.setLogLevel(self.options.verbosity)
134

    
135
        # validate environment setup
136
        init()
137

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

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

    
149
    def begin(self):
150
        '''Create and run mininet.'''
151

    
152
        start = time.time()
153

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

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

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

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

    
198

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