Statistics
| Branch: | Tag: | Revision:

mininet / bin / mn @ 80a8fa62

History | View | Annotate | Download (7.26 KB)

1 a6b47322 Brandon Heller
#!/usr/bin/env python
2
'''Mininet runner
3
4
@author Brandon Heller (brandonh@stanford.edu)
5
'''
6
7
from optparse import OptionParser
8 3031d31e Brandon Heller
import os.path
9 a6b47322 Brandon Heller
import time
10
11 433a7cc8 Brandon Heller
try:
12
    from ripcord.dctopo import TreeTopo, FatTreeTopo, VL2Topo
13
    USE_RIPCORD = True
14
except ImportError:
15
    USE_RIPCORD = False
16 a6b47322 Brandon Heller
17 0df8b195 Bob Lantz
from mininet.log import lg, LEVELS
18 a6b47322 Brandon Heller
from mininet.net import Mininet, init
19 1bb4412f Brandon Heller
from mininet.node import KernelSwitch, Host, Controller, ControllerParams, NOX
20 f7c2df25 Brandon Heller
from mininet.node import RemoteController, UserSwitch, OVSKernelSwitch
21 6d2cd77b Brandon Heller
from mininet.topo import SingleSwitchTopo, LinearTopo, SingleSwitchReversedTopo
22 a6b47322 Brandon Heller
23
# built in topologies, created only when run
24
TOPO_DEF = 'minimal'
25 723d068c Brandon Heller
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 433a7cc8 Brandon Heller
if USE_RIPCORD:
32
    TOPOS_RIPCORD = {
33 723d068c Brandon Heller
         '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 8e8081c4 Brandon Heller
         'vl2': (lambda: VL2Topo(da = 4, di = 4)),
39
         'vl2reduced': (lambda: VL2Topo(da = 4, di = 4, edge_down = 1))}
40 433a7cc8 Brandon Heller
    TOPOS.update(TOPOS_RIPCORD)
41 a6b47322 Brandon Heller
42
SWITCH_DEF = 'kernel'
43 723d068c Brandon Heller
SWITCHES = {'kernel': KernelSwitch,
44 f7c2df25 Brandon Heller
            'user': UserSwitch,
45
            'ovsk': OVSKernelSwitch}
46 a6b47322 Brandon Heller
47
HOST_DEF = 'process'
48 723d068c Brandon Heller
HOSTS = {'process': Host}
49 a6b47322 Brandon Heller
50
CONTROLLER_DEF = 'ref'
51 16c57ddb Brandon Heller
# a and b are the name and inNamespace params.
52 723d068c Brandon Heller
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 a6b47322 Brandon Heller
58
# optional tests to run
59 0cd489a7 Brandon Heller
TESTS = ['cli', 'build', 'ping_all', 'ping_pair', 'iperf', 'all', 'iperf_udp']
60 a6b47322 Brandon Heller
61 723d068c Brandon Heller
62 a6b47322 Brandon Heller
def add_dict_option(opts, choices_dict, default, name, help_str = None):
63
    '''Convenience function to add choices dicts to OptionParser.
64 723d068c Brandon Heller
65 a6b47322 Brandon Heller
    @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 723d068c Brandon Heller
90 a6b47322 Brandon Heller
        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 723d068c Brandon Heller
97 a6b47322 Brandon Heller
        @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 3031d31e Brandon Heller
        opts.add_option('--custom', type = 'string', default = None,
106
                        help = 'read custom mininet from current dir')
107 a6b47322 Brandon Heller
        opts.add_option('--test', type = 'choice', choices = TESTS,
108
                        default = TESTS[0],
109
                        help = '[' + ' '.join(TESTS) + ']')
110 8a034f4f Brandon Heller
        opts.add_option('--xterms', '-x', action = 'store_true',
111 a6b47322 Brandon Heller
                        default = False, help = 'spawn xterms for each node')
112 376bcba4 Brandon Heller
        opts.add_option('--mac', action = 'store_true',
113 54037995 Brandon Heller
                        default = False, help = 'set MACs equal to DPIDs')
114 376bcba4 Brandon Heller
        opts.add_option('--arp', action = 'store_true',
115
                        default = False, help = 'set all-pairs ARP entries')
116 a6b47322 Brandon Heller
        opts.add_option('--verbosity', '-v', type = 'choice',
117
                        choices = LEVELS.keys(), default = 'info',
118
                        help = '[' + ' '.join(LEVELS.keys()) + ']')
119 ee007363 Brandon Heller
        opts.add_option('--ip', type = 'string', default = '127.0.0.1',
120 60d9ead6 David Erickson
                        help = '[ip address as a dotted decimal string for a'
121
                        'remote controller]')
122 ee007363 Brandon Heller
        opts.add_option('--port', type = 'string', default = 6633,
123 60d9ead6 David Erickson
                        help = '[port integer for a listening remote'
124
                        ' controller]')
125 ca58c896 Brandon Heller
        opts.add_option('--in_namespace', action = 'store_true',
126
                        default = False, help = 'sw and ctrl in namespace?')
127 a6b47322 Brandon Heller
        self.options = opts.parse_args()[0]
128
129
    def setup(self):
130
        '''Setup and validate environment.'''
131
132
        # set logging verbosity
133 80a8fa62 Bob Lantz
        lg.setLogLevel(self.options.verbosity)
134 a6b47322 Brandon Heller
135
        # validate environment setup
136
        init()
137
138 83086439 Brandon Heller
        # check for invalid combinations
139 433a7cc8 Brandon Heller
        if self.options.controller == 'ref' and \
140
            (('fattree' in self.options.topo) or ('vl2' in self.options.topo)):
141 83086439 Brandon Heller
            raise Exception('multipath topos require multipath-capable '
142
                            'controller.')
143
144 3031d31e Brandon Heller
        if self.options.custom:
145
            if not os.path.isfile(self.options.custom):
146 799242c6 Bob Lantz
                raise Exception('could not find custom file: %s' %
147
                    self.options.custom)
148 3031d31e Brandon Heller
149 a6b47322 Brandon Heller
    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 60d9ead6 David Erickson
        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 a6b47322 Brandon Heller
163
        controller_params = ControllerParams(0x0a000000, 8) # 10.0.0.0/8
164 ca58c896 Brandon Heller
        in_namespace = self.options.in_namespace
165 8a034f4f Brandon Heller
        xterms = self.options.xterms
166 376bcba4 Brandon Heller
        mac = self.options.mac
167
        arp = self.options.arp
168 3031d31e Brandon Heller
        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 a6b47322 Brandon Heller
183 eeb9cb3c Brandon Heller
        test = self.options.test
184
        if test != 'build':
185
            if test == 'cli':
186 a6b47322 Brandon Heller
                mn.interact()
187 83086439 Brandon Heller
            elif test == 'all':
188
                mn.start()
189
                mn.ping()
190
                mn.iperf()
191 a6b47322 Brandon Heller
                mn.stop()
192
            else:
193 eeb9cb3c Brandon Heller
                mn.run(test)
194 a6b47322 Brandon Heller
195
        elapsed = float(time.time() - start)
196
        print ('completed in %0.3f seconds' % elapsed)
197
198
199
if __name__ == "__main__":
200 83086439 Brandon Heller
    MininetRunner()