Statistics
| Branch: | Tag: | Revision:

mininet / bin / mn_run.py @ 723d068c

History | View | Annotate | Download (6.46 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 time
9

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

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

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

    
40
SWITCH_DEF = 'kernel'
41
SWITCHES = {'kernel': KernelSwitch,
42
            'user': UserSwitch}
43

    
44
HOST_DEF = 'process'
45
HOSTS = {'process': Host}
46

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

    
55
# optional tests to run
56
TESTS = ['cli', 'build', 'ping_all', 'ping_pair', 'iperf', 'all', 'iperf_udp']
57

    
58

    
59
def add_dict_option(opts, choices_dict, default, name, help_str = None):
60
    '''Convenience function to add choices dicts to OptionParser.
61

62
    @param opts OptionParser instance
63
    @param choices_dict dictionary of valid choices, must include default
64
    @param default default choice key
65
    @param name long option name
66
    @param help string
67
    '''
68
    if default not in choices_dict:
69
        raise Exception('Invalid  default %s for choices dict: %s' %
70
                        (default, name))
71
    if not help_str:
72
        help_str = '[' + ' '.join(choices_dict.keys()) + ']'
73
    opts.add_option('--' + name,
74
                    type = 'choice',
75
                    choices = choices_dict.keys(),
76
                    default = default,
77
                    help = help_str)
78

    
79

    
80
class MininetRunner(object):
81
    '''Build, setup, and run Mininet.'''
82

    
83
    def __init__(self):
84
        '''Init.'''
85
        self.options = None
86

    
87
        self.parse_args()
88
        self.setup()
89
        self.begin()
90

    
91
    def parse_args(self):
92
        '''Parse command-line args and return options object.
93

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

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

    
124
    def setup(self):
125
        '''Setup and validate environment.'''
126

    
127
        # set logging verbosity
128
        lg.set_loglevel(self.options.verbosity)
129

    
130
        # validate environment setup
131
        init()
132

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

    
139
    def begin(self):
140
        '''Create and run mininet.'''
141

    
142
        start = time.time()
143

    
144
        topo = TOPOS[self.options.topo]() # build topology object
145
        switch = SWITCHES[self.options.switch]
146
        host = HOSTS[self.options.host]
147
        controller = CONTROLLERS[self.options.controller]
148
        if self.options.controller == 'remote':
149
            controller = lambda a, b: RemoteController(a, b,
150
                             ip_address = self.options.ip,
151
                             port = self.options.port)
152

    
153
        controller_params = ControllerParams(0x0a000000, 8) # 10.0.0.0/8
154
        in_namespace = self.options.in_namespace
155
        xterms = self.options.xterms
156
        mac = self.options.mac
157
        arp = self.options.arp
158
        mn = Mininet(topo, switch, host, controller, controller_params,
159
                     in_namespace = in_namespace,
160
                     xterms = xterms, auto_set_macs = mac,
161
                     auto_static_arp = arp)
162

    
163
        test = self.options.test
164
        if test != 'build':
165
            if test == 'cli':
166
                mn.interact()
167
            elif test == 'all':
168
                mn.start()
169
                mn.ping()
170
                mn.iperf()
171
                mn.stop()
172
            else:
173
                mn.run(test)
174

    
175
        elapsed = float(time.time() - start)
176
        print ('completed in %0.3f seconds' % elapsed)
177

    
178

    
179
if __name__ == "__main__":
180
    MininetRunner()