Statistics
| Branch: | Tag: | Revision:

mininet / bin / mn_run.py @ 60d9ead6

History | View | Annotate | Download (6.12 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
import time
9
10 433a7cc8 Brandon Heller
try:
11
    from ripcord.dctopo import TreeTopo, FatTreeTopo, VL2Topo
12
    USE_RIPCORD = True
13
except ImportError:
14
    USE_RIPCORD = False
15 a6b47322 Brandon Heller
16
from mininet.logging_mod import lg, set_loglevel, LEVELS
17
from mininet.net import Mininet, init
18 1bb4412f Brandon Heller
from mininet.node import KernelSwitch, Host, Controller, ControllerParams, NOX
19 60d9ead6 David Erickson
from mininet.node import RemoteController
20 433a7cc8 Brandon Heller
from mininet.topo import SingleSwitchTopo, LinearTopo
21 a6b47322 Brandon Heller
22
# built in topologies, created only when run
23
TOPO_DEF = 'minimal'
24 433a7cc8 Brandon Heller
TOPOS = {'minimal' :   (lambda: SingleSwitchTopo(k = 2)),
25
         'single4' :   (lambda: SingleSwitchTopo(k = 4)),
26
         'single100' : (lambda: SingleSwitchTopo(k = 100)),
27
         'linear2' :   (lambda: LinearTopo(k = 2)),
28
         'linear100' : (lambda: LinearTopo(k = 100))}
29
if USE_RIPCORD:
30
    TOPOS_RIPCORD = {
31 a6b47322 Brandon Heller
         'tree16' :   (lambda: TreeTopo(depth = 3, fanout = 4)),
32
         'tree64' :   (lambda: TreeTopo(depth = 4, fanout = 4)),
33 83086439 Brandon Heller
         'tree1024' : (lambda: TreeTopo(depth = 3, fanout = 32)),
34 a6b47322 Brandon Heller
         'fattree4' : (lambda: FatTreeTopo(k = 4)),
35 c98514ae Brandon Heller
         'fattree6' : (lambda: FatTreeTopo(k = 6)),
36 433a7cc8 Brandon Heller
         'vl2'      : (lambda: VL2Topo(da = 4, di = 4))}
37
    TOPOS.update(TOPOS_RIPCORD)
38 a6b47322 Brandon Heller
39
SWITCH_DEF = 'kernel'
40 1bb4412f Brandon Heller
SWITCHES = {'kernel' : KernelSwitch}
41 a6b47322 Brandon Heller
42
HOST_DEF = 'process'
43
HOSTS = {'process' : Host}
44
45
CONTROLLER_DEF = 'ref'
46 16c57ddb Brandon Heller
# a and b are the name and inNamespace params.
47 83086439 Brandon Heller
CONTROLLERS = {'ref' : Controller,
48 4804237f Brandon Heller
               'nox_dump' : lambda a, b: NOX(a, b, 'packetdump'),
49 16c57ddb Brandon Heller
               'nox_pysw' : lambda a, b: NOX(a, b, 'pyswitch'),
50 60d9ead6 David Erickson
               'remote' : lambda a, b: None,
51 16c57ddb Brandon Heller
               'none' :     lambda a, b: None}
52 a6b47322 Brandon Heller
53
# optional tests to run
54 0cd489a7 Brandon Heller
TESTS = ['cli', 'build', 'ping_all', 'ping_pair', 'iperf', 'all', 'iperf_udp']
55 a6b47322 Brandon Heller
56
def add_dict_option(opts, choices_dict, default, name, help_str = None):
57
    '''Convenience function to add choices dicts to OptionParser.
58
    
59
    @param opts OptionParser instance
60
    @param choices_dict dictionary of valid choices, must include default
61
    @param default default choice key
62
    @param name long option name
63
    @param help string
64
    '''
65
    if default not in choices_dict:
66
        raise Exception('Invalid  default %s for choices dict: %s' %
67
                        (default, name))
68
    if not help_str:
69
        help_str = '[' + ' '.join(choices_dict.keys()) + ']'
70
    opts.add_option('--' + name,
71
                    type = 'choice',
72
                    choices = choices_dict.keys(),
73
                    default = default,
74
                    help = help_str)
75
76
77
class MininetRunner(object):
78
    '''Build, setup, and run Mininet.'''
79
80
    def __init__(self):
81
        '''Init.'''
82
        self.options = None
83
        
84
        self.parse_args()
85
        self.setup()
86
        self.begin()
87
88
    def parse_args(self):
89
        '''Parse command-line args and return options object.
90
        
91
        @return opts parse options dict
92
        '''
93
        opts = OptionParser()
94
        add_dict_option(opts, TOPOS, TOPO_DEF, 'topo')
95
        add_dict_option(opts, SWITCHES, SWITCH_DEF, 'switch')
96
        add_dict_option(opts, HOSTS, HOST_DEF, 'host')
97
        add_dict_option(opts, CONTROLLERS, CONTROLLER_DEF, 'controller')
98
99
        opts.add_option('--test', type = 'choice', choices = TESTS,
100
                        default = TESTS[0],
101
                        help = '[' + ' '.join(TESTS) + ']')
102 8a034f4f Brandon Heller
        opts.add_option('--xterms', '-x', action = 'store_true',
103 a6b47322 Brandon Heller
                        default = False, help = 'spawn xterms for each node')
104 376bcba4 Brandon Heller
        opts.add_option('--mac', action = 'store_true',
105 54037995 Brandon Heller
                        default = False, help = 'set MACs equal to DPIDs')
106 376bcba4 Brandon Heller
        opts.add_option('--arp', action = 'store_true',
107
                        default = False, help = 'set all-pairs ARP entries')
108 a6b47322 Brandon Heller
        opts.add_option('--verbosity', '-v', type = 'choice',
109
                        choices = LEVELS.keys(), default = 'info',
110
                        help = '[' + ' '.join(LEVELS.keys()) + ']')
111 60d9ead6 David Erickson
        opts.add_option('--ip', type = 'string',
112
                        help = '[ip address as a dotted decimal string for a'
113
                        'remote controller]')
114
        opts.add_option('--port', type = 'string',
115
                        help = '[port integer for a listening remote'
116
                        ' controller]')
117 a6b47322 Brandon Heller
        self.options = opts.parse_args()[0]
118
119
    def setup(self):
120
        '''Setup and validate environment.'''
121
122
        # set logging verbosity
123
        set_loglevel(self.options.verbosity)
124
125
        # validate environment setup
126
        init()
127
128 83086439 Brandon Heller
        # check for invalid combinations
129 433a7cc8 Brandon Heller
        if self.options.controller == 'ref' and \
130
            (('fattree' in self.options.topo) or ('vl2' in self.options.topo)):
131 83086439 Brandon Heller
            raise Exception('multipath topos require multipath-capable '
132
                            'controller.')
133
134 a6b47322 Brandon Heller
    def begin(self):
135
        '''Create and run mininet.'''
136
137
        start = time.time()
138
139
        topo = TOPOS[self.options.topo]() # build topology object
140
        switch = SWITCHES[self.options.switch]
141
        host = HOSTS[self.options.host]
142
        controller = CONTROLLERS[self.options.controller]
143 60d9ead6 David Erickson
        if self.options.controller == 'remote':
144
            controller = lambda a, b: RemoteController(a, b,
145
                             ip_address = self.options.ip,
146
                             port = self.options.port)
147 a6b47322 Brandon Heller
148
        controller_params = ControllerParams(0x0a000000, 8) # 10.0.0.0/8
149 8a034f4f Brandon Heller
        xterms = self.options.xterms
150 376bcba4 Brandon Heller
        mac = self.options.mac
151
        arp = self.options.arp
152 8a034f4f Brandon Heller
        mn = Mininet(topo, switch, host, controller, controller_params,
153 376bcba4 Brandon Heller
                     xterms = xterms, auto_set_macs = mac,
154
                     auto_static_arp = arp)
155 a6b47322 Brandon Heller
156 eeb9cb3c Brandon Heller
        test = self.options.test
157
        if test != 'build':
158
            if test == 'cli':
159 a6b47322 Brandon Heller
                mn.interact()
160 83086439 Brandon Heller
            elif test == 'all':
161
                mn.start()
162
                mn.ping()
163
                mn.iperf()
164 a6b47322 Brandon Heller
                mn.stop()
165
            else:
166 eeb9cb3c Brandon Heller
                mn.run(test)
167 a6b47322 Brandon Heller
168
        elapsed = float(time.time() - start)
169
        print ('completed in %0.3f seconds' % elapsed)
170
171
172
if __name__ == "__main__":
173 83086439 Brandon Heller
    MininetRunner()