blob: 08ccd1a73996d3365747cd1df971846bd6f71ac7 [file] [log] [blame]
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -08001#!/usr/bin/python
2import os
3import re
4from optparse import OptionParser
5from ipaddress import ip_network
6from mininet.node import RemoteController, OVSBridge, Host
7from mininet.link import TCLink
8from mininet.log import setLogLevel
9from mininet.net import Mininet
10from mininet.topo import Topo
11from mininet.nodelib import NAT
12from mininet.cli import CLI
13
14from routinglib import BgpRouter, RoutedHost
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080015from trellislib import DhcpServer, TaggedRoutedHost, DualHomedRoutedHost, DualHomedTaggedRoutedHost, DhcpClient, Dhcp6Client, DhcpServer, Dhcp6Server, TrellisHost
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080016
17# Parse command line options and dump results
18def parseOptions():
19 "Parse command line options"
20 parser = OptionParser()
21 parser.add_option( '--dhcp', dest='dhcp', type='int', default=0,
22 help='Configure hosts with dhcp or not' )
23 parser.add_option( '--routers', dest='routers', type='int', default=0,
24 help='Configure external routers or not in the topology' )
25 parser.add_option( '--ipv6', dest='ipv6', type='int', default=0,
26 help='Configure hosts with ipv6 or not' )
27 parser.add_option( '--ipv4', dest='ipv4', type='int', default=1,
28 help='Configure hosts with ipv4 or not' )
29 parser.add_option( '--onos-ip', dest='onosIp', type='str', default='',
30 help='IP address list of ONOS instances, separated by comma(,). Overrides --onos option' )
31
32 ( options, args ) = parser.parse_args()
33 return options, args
34
35opts, args = parseOptions()
36
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080037class ComcastLeafSpineFabric(Topo):
38
39 spines = dict()
40 leafs = dict()
41 hosts_dict = dict()
42
43 def createIpv4Hosts(self, dhcp):
44
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080045 h1 = self.addHost('h1v4', cls=TrellisHost,
46 mac='00:aa:00:00:00:01', ips=['10.1.0.1/24'],
47 gateway='10.1.0.254', dhcpClient=dhcp)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080048 self.addLink(h1, self.leafs[0])
49 self.hosts_dict['h1v4'] = h1
50
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080051 h2 = self.addHost('h2v4', cls=TrellisHost,
52 mac='00:aa:00:00:01:01', ips=['10.1.10.1/24'],
53 gateway='10.1.10.254', dhcpClient=dhcp)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080054 self.addLink(h2, self.leafs[0])
55 self.hosts_dict['h2v4'] = h2
56
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080057 h3 = self.addHost('h3v4', cls=TrellisHost,
58 mac='00:aa:00:00:00:02', ips=['10.2.0.1/24'],
59 gateway='10.2.0.254', dhcpClient=dhcp)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080060 self.addLink(h3, self.leafs[1])
61 self.hosts_dict['h3v4'] = h3
62
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080063 h4 = self.addHost('h4v4', cls=TrellisHost,
64 mac='00:aa:00:00:00:03', ips=['10.2.30.1/24'],
65 gateway='10.2.30.254', dhcpClient=dhcp,
66 dualHomed=True)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080067 self.addLink(h4, self.leafs[1])
68 self.addLink(h4, self.leafs[2])
69 self.hosts_dict['h4v4'] = h4
70
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080071 h5 = self.addHost('h5v4', cls=TrellisHost,
72 mac='00:aa:00:00:00:04', ips=['10.2.20.1/24'],
73 gateway='10.2.20.254', dhcpClient=dhcp, vlan=30,
74 dualHomed=True)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080075 self.addLink(h5, self.leafs[1])
76 self.addLink(h5, self.leafs[2])
77 self.hosts_dict['h5v4'] = h5
78
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080079 h6 = self.addHost('h6v4', cls=TrellisHost,
80 mac='00:aa:00:00:00:05', ips=['10.2.10.1/24'],
81 gateway='10.2.10.254', dhcpClient=dhcp, vlan=20)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080082 self.addLink(h6, self.leafs[2])
83 self.hosts_dict['h6v4'] = h6
84
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080085 h7 = self.addHost('h7v4', cls=TrellisHost,
86 mac='00:aa:00:00:01:05', ips=['10.2.40.1/24'],
87 gateway='10.2.40.254', dhcpClient=dhcp, vlan=40)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080088 self.addLink(h7, self.leafs[2])
89 self.hosts_dict['h7v4'] = h7
90
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080091 h8 = self.addHost('h8v4', cls=TrellisHost,
92 mac='00:aa:00:00:00:06', ips=['10.3.0.1/24'],
93 gateway='10.3.0.254', dhcpClient=dhcp, vlan=30)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -080094 self.addLink(h8, self.leafs[3])
95 self.hosts_dict['h8v4'] = h8
96
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -080097 h9 = self.addHost('h9v4', cls=TrellisHost,
98 mac='00:aa:00:00:00:07', ips=['10.3.10.1/24'],
99 gateway='10.3.10.254', dhcpClient=dhcp, vlan=40,
100 dualHomed=True)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800101 self.addLink(h9, self.leafs[3])
102 self.addLink(h9, self.leafs[4])
103 self.hosts_dict['h9v4'] = h9
104
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800105 h10 = self.addHost('h10v4', cls=TrellisHost,
106 mac='00:aa:00:00:00:08', ips=['10.3.30.1/24'],
107 gateway='10.3.30.254', dhcpClient=dhcp, vlan=40,
108 dualHomed=True)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800109 self.addLink(h10, self.leafs[3])
110 self.addLink(h10, self.leafs[4])
111 self.hosts_dict['h10v4'] = h10
112
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800113 h11 = self.addHost('h11v4', cls=TrellisHost,
114 mac='00:aa:00:00:00:0a', ips=['10.3.20.1/24'],
115 gateway='10.3.20.254', dhcpClient=dhcp, vlan=40)
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800116 self.addLink(h11, self.leafs[4])
117 self.hosts_dict['h11v4'] = h11
118
119 return
120
121 def createIpv6Hosts(self, dhcp):
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800122
123 h1 = self.addHost('h1v6', cls=TrellisHost,
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800124 mac='00:bb:00:00:00:01', ips=["1000::3fe/120"],
125 gateway='1000::3ff', dhcpClient=dhcp, ipv6=1)
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800126 self.addLink(h1, self.leafs[0])
127 self.hosts_dict['h1v6'] = h1
128
129 h2 = self.addHost('h2v6', cls=TrellisHost,
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800130 mac='00:bb:00:00:01:01', ips=['1001::3fe/120'],
131 gateway='1001::3ff', dhcpClient=dhcp, ipv6=1)
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800132 self.addLink(h2, self.leafs[0])
133 self.hosts_dict['h2v6'] = h2
134
135 h3 = self.addHost('h3v6', cls=TrellisHost,
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800136 mac='00:bb:00:00:00:02', ips=['1002::3fe/120'],
137 gateway='1002::3ff', dhcpClient=dhcp, ipv6=1)
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800138 self.addLink(h3, self.leafs[1])
139 self.hosts_dict['h3v6'] = h3
140
141 h4 = self.addHost('h4v6', cls=TrellisHost,
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800142 mac='00:bb:00:00:00:03', ips=['1003::3fe/120'],
143 gateway='1003::3ff', dhcpClient=dhcp, ipv6=1,
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800144 dualHomed=True)
145 self.addLink(h4, self.leafs[1])
146 self.addLink(h4, self.leafs[2])
147 self.hosts_dict['h4v6'] = h4
148
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800149 # TODO: Remove this line when we
150 # find WHY dhcpv6 with tagged clients
151 # does not work.
152 dhcp = False
153
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800154 h5 = self.addHost('h5v6', cls=TrellisHost,
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800155 mac='00:bb:00:00:00:04', ips=['1004::3fe/120'],
156 gateway='1004::3ff', dhcpClient=dhcp, ipv6=1,
157 vlan=30,
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800158 dualHomed=True)
159 self.addLink(h5, self.leafs[1])
160 self.addLink(h5, self.leafs[2])
161 self.hosts_dict['h5v6'] = h5
162
163 h6 = self.addHost('h6v6', cls=TrellisHost,
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800164 mac='00:bb:00:00:00:05', ips=['1005::3fe/120'],
165 gateway='1005::3ff', dhcpClient=dhcp, vlan=20,
166 ipv6=1)
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800167 self.addLink(h6, self.leafs[2])
168 self.hosts_dict['h6v6'] = h6
169
170 h7 = self.addHost('h7v6', cls=TrellisHost,
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800171 mac='00:bb:00:00:01:05', ips=['1006::3fe/120'],
172 gateway='1006::3ff', dhcpClient=dhcp, ipv6=1,
173 vlan=40)
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800174 self.addLink(h7, self.leafs[2])
175 self.hosts_dict['h7v6'] = h7
176
177 h8 = self.addHost('h8v6', cls=TrellisHost,
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800178 mac='00:bb:00:00:00:06', ips=['1007::3fe/120'],
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800179 gateway='1007::3ff', dhcpClient=dhcp, vlan=30)
180 self.addLink(h8, self.leafs[3])
181 self.hosts_dict['h8v6'] = h8
182
183 h9 = self.addHost('h9v6', cls=TrellisHost,
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800184 mac='00:bb:00:00:00:07', ips=['1008::3fe/120'],
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800185 gateway='1008::3ff', dhcpClient=dhcp, vlan=40,
186 dualHomed=True)
187 self.addLink(h9, self.leafs[3])
188 self.addLink(h9, self.leafs[4])
189 self.hosts_dict['h9v6'] = h9
190
191 h10 = self.addHost('h10v6', cls=TrellisHost,
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800192 mac='00:bb:00:00:00:08', ips=['1009::3fe/120'],
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800193 gateway='1009::3ff', dhcpClient=dhcp, vlan=40,
194 dualHomed=True)
195 self.addLink(h10, self.leafs[3])
196 self.addLink(h10, self.leafs[4])
197 self.hosts_dict['h10v6'] = h10
198
199 h11 = self.addHost('h11v6', cls=TrellisHost,
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800200 mac='00:bb:00:00:00:0a', ips=['1010::3fe/120'],
Andreas Pantelopoulosf6ed5012018-02-08 21:26:01 -0800201 gateway='1010::3ff', dhcpClient=dhcp, vlan=40)
202 self.addLink(h11, self.leafs[4])
203 self.hosts_dict['h11v6'] = h11
204
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800205 return
206
207 '''
208 Creates the topology employed by Comcast which is a 2x5
209 leaf spine traffic.
210
211 S1 S2
212
213 L1 L2 L3 L4 L5
214
215 Where L2/L3 and L4/L5 are paired switches.
216 Parameters for this topology :
217 dhcp = True/False : set up dhcp servers
218 routers = True/False : set up external routers
219 '''
220 def __init__(self, dhcp=False, routers=False, ipv4=False, ipv6=False, **opts):
221 Topo.__init__(self, **opts)
222
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800223 linkopts = dict( bw=10 )
224
225 spine = 2
226 leaf = 5
227
228 # Create spine switches
229 for s in range(spine):
230 self.spines[s] = self.addSwitch('spine10%s' % (s + 1), dpid = "00000000010%s" % (s + 1) )
231
232 # Create leaf switches
233 for ls in range(leaf):
234 self.leafs[ls] = self.addSwitch('leaf%s' % (ls + 1), dpid = "00000000000%s" % ( ls + 1) )
235
236 # connecting leaf and spines, leafs 1-5 have double links
237 for s in range( spine ):
238 spine_switch = self.spines[s]
239
240 for ls in range( leaf ):
241 leaf_switch = self.leafs[ls]
242
243 self.addLink( spine_switch, leaf_switch, **linkopts )
244 if ls > 0:
245 self.addLink( spine_switch, leaf_switch, **linkopts )
246
247 # connect paired leafs
248 self.addLink(self.leafs[1], self.leafs[2], **linkopts)
249 self.addLink(self.leafs[3], self.leafs[4], **linkopts)
250
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800251 # create hosts
252 if ipv6:
253 self.createIpv6Hosts(dhcp)
254
255 if ipv4:
256 self.createIpv4Hosts(dhcp)
257
258 if not ipv4 and not ipv6:
259 print("No hosts were created!")
260
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800261 # create quagga routers
You Wang91befd72018-02-28 16:41:23 -0800262 # Note: Change "fpm connection ip" to $OC1 in zebradbgp1.conf and zebradbgp2.conf to make quagga work correctly
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800263 if routers:
264 last_ls = self.leafs[4]
You Wang91befd72018-02-28 16:41:23 -0800265 last_paired_ls = self.leafs[3]
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800266
267 # Control plane switch (for quagga fpm)
268 cs0 = self.addSwitch('cs0', cls=OVSBridge)
269
270 # Control plane NAT (for quagga fpm)
271 nat = self.addHost('nat', cls=NAT,
272 ip='172.16.0.1/12',
273 subnet=str(ip_network(u'172.16.0.0/12')), inNamespace=False)
274 self.addLink(cs0, nat)
275
276 # Internal Quagga bgp1
277 intfs = {'bgp1-eth0': [{'ipAddrs': ['10.0.1.2/24', '2000::102/120'], 'mac': '00:88:00:00:00:03', 'vlan': '110'},
278 {'ipAddrs': ['10.0.7.2/24', '2000::702/120'], 'mac': '00:88:00:00:00:03', 'vlan': '170'}],
279 'bgp1-eth1': {'ipAddrs': ['172.16.0.3/12']}}
280 bgp1 = self.addHost('bgp1', cls=BgpRouter,
281 interfaces=intfs,
282 quaggaConfFile='./bgpdbgp1.conf',
283 zebraConfFile='./zebradbgp1.conf')
284 self.addLink(bgp1, last_paired_ls)
285 self.addLink(bgp1, cs0)
286
287 # Internal Quagga bgp2
288 intfs = {'bgp2-eth0': [{'ipAddrs': ['10.0.5.2/24', '2000::502/120'], 'mac': '00:88:00:00:00:04', 'vlan': '150'},
289 {'ipAddrs': ['10.0.6.2/24', '2000::602/120'], 'mac': '00:88:00:00:00:04', 'vlan': '160'}],
290 'bgp2-eth1': {'ipAddrs': ['172.16.0.4/12']}}
291 bgp2 = self.addHost('bgp2', cls=BgpRouter,
292 interfaces=intfs,
293 quaggaConfFile='./bgpdbgp2.conf',
294 zebraConfFile='./zebradbgp2.conf')
295 self.addLink(bgp2, last_ls)
296 self.addLink(bgp2, cs0)
297
298 # External Quagga r1
299 intfs = {'r1-eth0': {'ipAddrs': ['10.0.1.1/24', '2000::101/120'], 'mac': '00:88:00:00:00:01'},
300 'r1-eth1': {'ipAddrs': ['10.0.5.1/24', '2000::501/120'], 'mac': '00:88:00:00:00:11'},
301 'r1-eth2': {'ipAddrs': ['10.0.99.1/16']},
302 'r1-eth3': {'ipAddrs': ['2000::9901/120']},
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -0800303 'r1-eth4': {'ipAddrs': ['2000::7701/120']},
304 'r1-eth5': {'ipAddrs': ['10.0.88.1/24']},
305 'r1-eth6': {'ipAddrs': ['2000::8701/120']}}
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800306 r1 = self.addHost('r1', cls=BgpRouter,
307 interfaces=intfs,
308 quaggaConfFile='./bgpdr1.conf')
309 self.addLink(r1, last_paired_ls)
310 self.addLink(r1, last_ls)
311
312 # External IPv4 Host behind r1
You Wang91befd72018-02-28 16:41:23 -0800313 rh1v4 = self.addHost('rh1v4', cls=RoutedHost, ips=['10.0.99.2/24'], gateway='10.0.99.1')
314 self.addLink(r1, rh1v4)
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800315
316 # External IPv6 Host behind r1
317 rh1v6 = self.addHost('rh1v6', cls=RoutedHost, ips=['2000::9902/120'], gateway='2000::9901')
318 self.addLink(r1, rh1v6)
319
320 # Another external IPv6 Host behind r1
321 rh11v6 = self.addHost('rh11v6', cls=RoutedHost, ips=['2000::7702/120'], gateway='2000::7701')
322 self.addLink(r1, rh11v6)
323
Andreas Pantelopoulos2eae3242018-03-06 13:47:20 -0800324 # Add an external ipv4 hosts that is not configured in the bgp conf
325 # files
326 rh5v4 = self.addHost('rh5v4', cls=RoutedHost, ips=['10.0.88.2/24'], gateway='10.0.88.1')
327 self.addLink(r1, rh5v4)
328
329 # Add an external ipv6 hosts that is not configured in the bgp conf
330 # files
331 rh5v6 = self.addHost('rh5v6', cls=RoutedHost, ips=['2000::8702/120'], gateway='2000::8701')
332 self.addLink(r1, rh5v6)
333
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800334 # External Quagga r2
335 intfs = {'r2-eth0': {'ipAddrs': ['10.0.6.1/24', '2000::601/120'], 'mac': '00:88:00:00:00:02'},
336 'r2-eth1': {'ipAddrs': ['10.0.7.1/24', '2000::701/120'], 'mac': '00:88:00:00:00:22'},
337 'r2-eth2': {'ipAddrs': ['10.0.99.1/16']},
338 'r2-eth3': {'ipAddrs': ['2000::9901/120']},
339 'r2-eth4': {'ipAddrs': ['2000::8801/120']}}
340 r2 = self.addHost('r2', cls=BgpRouter,
341 interfaces=intfs,
342 quaggaConfFile='./bgpdr2.conf')
343 self.addLink(r2, last_ls)
344 self.addLink(r2, last_paired_ls)
345
346 # External IPv4 Host behind r2
You Wang91befd72018-02-28 16:41:23 -0800347 rh2v4 = self.addHost('rh2v4', cls=RoutedHost, ips=['10.0.99.2/24'], gateway='10.0.99.1')
348 self.addLink(r2, rh2v4)
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800349
350 # External IPv6 Host behind r2
You Wang91befd72018-02-28 16:41:23 -0800351 rh2v6 = self.addHost('rh2v6', cls=RoutedHost, ips=['2000::9902/120'], gateway='2000::9901')
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800352 self.addLink(r2, rh2v6)
353
354 # Another external IPv6 Host behind r1
355 rh22v6 = self.addHost('rh22v6', cls=RoutedHost, ips=['2000::8802/120'], gateway='2000::8801')
356 self.addLink(r2, rh22v6)
357
You Wang79577812018-02-27 16:39:50 -0800358 # create dhcp servers
359 if dhcp:
360 cs1 = self.addSwitch('cs1', cls=OVSBridge)
361 self.addLink(cs1, self.leafs[4])
362 if ipv4:
363 dhcp4 = self.addHost( 'dhcp', cls=TrellisHost,
You Wang91befd72018-02-28 16:41:23 -0800364 mac="00:cc:00:00:00:01", ips=["10.0.3.253/24"],
You Wang79577812018-02-27 16:39:50 -0800365 gateway="10.0.3.254", dhcpServer=True)
366 self.addLink(dhcp4, cs1, **linkopts)
367 if ipv6:
368 dhcp6 = self.addHost( 'dhcp6', cls=TrellisHost,
You Wang91befd72018-02-28 16:41:23 -0800369 mac="00:dd:00:00:00:01", ips=["2000::3fd/120"],
You Wang79577812018-02-27 16:39:50 -0800370 gateway="2000::3ff", dhcpServer=True, ipv6=True)
371 self.addLink(dhcp6, cs1, **linkopts)
372
Andreas Pantelopoulos971c91d2018-02-12 11:28:10 -0800373
Andreas Pantelopoulos90f0b102018-02-01 13:21:45 -0800374def config( opts ):
375
376 dhcp = bool(opts.dhcp)
377 routers = bool(opts.routers)
378 ipv6 = bool(opts.ipv6)
379 ipv4 = bool(opts.ipv4)
380
381 if opts.onosIp != '':
382 controllers = opts.onosIp.split( ',' )
383 else:
384 controllers = ['127.0.0.1']
385 topo = ComcastLeafSpineFabric(dhcp=dhcp, routers=routers, ipv6=ipv6,
386 ipv4=ipv4)
387
388 net = Mininet( topo=topo, link=TCLink, build=False,
389 controller=None, autoSetMacs=True )
390 i = 0
391 for ip in controllers:
392 net.addController( "c%s" % ( i ), controller=RemoteController, ip=ip )
393 i += 1
394
395 net.build()
396 net.start()
397 CLI( net )
398 net.stop()
399
400
401if __name__ == '__main__':
402 setLogLevel('info')
403 config(opts)
404 os.system('sudo mn -c')
405