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() |