blob: 5eba83e4a9e1f1c272e05be55eeea633154bfe30 [file] [log] [blame]
pingping-lina7a13a82015-08-31 16:20:53 -07001#!/usr/bin/python
2
3"""
4Set up the SDN-IP function test topology
5"""
6
7"""
8AS1 = 64513, (SDN AS)
9AS2 = 64514, reachable by 192.168.10.1, 192.168.20.1
10AS3 = 64516, reachable by 192.168.30.1
11AS4 = 64517, reachable by 192.168.40.1
12AS6 = 64520, reachable by 192.168.60.2, (route server 192.168.60.1)
13"""
14
15from mininet.net import Mininet
16from mininet.node import Controller, RemoteController
17from mininet.log import setLogLevel, info
18from mininet.cli import CLI
19from mininet.topo import Topo
20from mininet.util import quietRun
21from mininet.moduledeps import pathCheck
22
23import os.path
24import time
25from subprocess import Popen, STDOUT, PIPE
26
27QUAGGA_DIR = '/usr/lib/quagga'
28QUAGGA_RUN_DIR = '/usr/local/var/run/quagga'
29
30
31class SDNTopo( Topo ):
32 "SDN Topology"
33
34 def __init__( self, *args, **kwargs ):
35 global numHost101
36 global numHost200
37 numHost101 = 101
38 numHost200 = 200
39 Topo.__init__( self, *args, **kwargs )
40 sw1 = self.addSwitch( 'sw1', dpid = '00000000000000a1' )
41 sw2 = self.addSwitch( 'sw2', dpid = '00000000000000a2' )
42 sw3 = self.addSwitch( 'sw3', dpid = '00000000000000a3' )
43 sw4 = self.addSwitch( 'sw4', dpid = '00000000000000a4' )
44 sw5 = self.addSwitch( 'sw5', dpid = '00000000000000a5' )
45 sw6 = self.addSwitch( 'sw6', dpid = '00000000000000a6' )
46 # add a switch for 100 quagga hosts
47 sw100 = self.addSwitch( 'sw100', dpid = '0000000000000100' )
48 swTestOn = self.addSwitch( 'swTestOn', dpid = '0000000000000102' )
49 # Note this switch isn't part of the SDN topology
50 # We'll use the ovs-controller to turn this into a learning switch
51 as6sw = self.addSwitch( 'as6sw', dpid = '00000000000000a7' )
52
53 host1 = self.addHost( 'host1' )
54 host2 = self.addHost( 'host2' )
55 root1 = self.addHost( 'root1', inNamespace = False , ip = '0' )
56 root2 = self.addHost( 'root2', inNamespace = False, ip = '0' )
57 rootTestOn = self.addHost( 'rootTestOn', inNamespace = False, ip = '0' )
58
59 # AS2 host
60 host3 = self.addHost( 'host3' )
61 as2host = self.addHost( 'as2host' )
62 # AS3 host
63 host4 = self.addHost( 'host4' )
64 as3host = self.addHost( 'as3host' )
65 # AS4 host
66 for i in range( numHost101, numHost200 + 1 ):
67 self.addHost( 'host%s' % ( i ) )
68
69 as4host = self.addHost( 'as4host' )
70 for i in range( numHost101, numHost200 + 1 ):
71 self.addHost( 'as4host%s' % ( i ) )
72 # AS6 host
73 as6rs = self.addHost( 'as6rs' )
74 host5 = self.addHost( 'host5' )
75 as6host = self.addHost( 'as6host' )
76
77 self.addLink( host1, sw1 )
78 self.addLink( host2, sw1 )
79 # Links to the multihomed AS
80 self.addLink( host3, sw3 )
81 self.addLink( host3, sw5 )
82 self.addLink( as2host, host3 )
83 # Single links to the remaining two ASes
84 self.addLink( host4, sw2 )
85 self.addLink( sw100, sw6 )
86 self.addLink( as3host, host4 )
87 for i in range( numHost101, numHost200 + 1 ):
88 self.addLink( 'host%s' % ( i ), sw100 )
89 for i in range( numHost101, numHost200 + 1 ):
90 self.addLink( 'host%s' % ( i ), 'as4host%s' % ( i ) )
91
92 # AS3-AS4 link
93 # self.addLink( host4, host5)
94 # Add new AS6 to its bridge
95 self.addLink( as6rs, as6sw )
96 self.addLink( host5, as6sw )
97 self.addLink( as6host, host5 )
98 # test the host behind the router(behind the router server)
99 '''
100 for i in range(1, 10):
101 host = self.addHost('as6host%d' % i)
102 self.addLink(host, as6router)
103 '''
104 # Internal Connection To Hosts
105 self.addLink( root1, host1 )
106 self.addLink( root2, host2 )
107
108 self.addLink( sw1, sw2 )
109 self.addLink( sw1, sw3 )
110 self.addLink( sw2, sw4 )
111 self.addLink( sw3, sw4 )
112 self.addLink( sw3, sw5 )
113 self.addLink( sw4, sw6 )
114 self.addLink( sw5, sw6 )
115 self.addLink( as6sw, sw4 )
116
117 self.addLink( swTestOn, rootTestOn )
118 self.addLink( swTestOn, host3 )
119 self.addLink( swTestOn, host4 )
120 self.addLink( swTestOn, host5 )
121 self.addLink( swTestOn, as2host )
122
123 for i in range( numHost101, numHost200 + 1 ):
124 self.addLink( swTestOn, 'host' + str( i ) )
125
126def startsshd( host ):
127 "Start sshd on host"
128 info( '*** Starting sshd\n' )
129 name, intf, ip = host.name, host.defaultIntf(), host.IP()
130 banner = '/tmp/%s.banner' % name
131 host.cmd( 'echo "Welcome to %s at %s" > %s' % ( name, ip, banner ) )
132 host.cmd( '/usr/sbin/sshd -o "Banner %s"' % banner, '-o "UseDNS no"' )
133 info( '***', host.name, 'is running sshd on', intf, 'at', ip, '\n' )
134
135def startsshds ( hosts ):
136 for h in hosts:
137 startsshd( h )
138
139def stopsshd():
140 "Stop *all* sshd processes with a custom banner"
141 info( '*** Shutting down stale sshd/Banner processes ',
142 quietRun( "pkill -9 -f Banner" ), '\n' )
143
144def startquagga( host, num, config_file ):
145 info( '*** Starting Quagga on %s\n' % host )
146 zebra_cmd = \
147 '%s/zebra -d -f ./zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid'\
148 % ( QUAGGA_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num )
149 quagga_cmd = '%s/bgpd -d -f %s -z %s/zserv%s.api -i %s/bgpd%s.pid' \
150 % ( QUAGGA_DIR, config_file, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num )
151
152 print zebra_cmd
153 print quagga_cmd
154
155 host.cmd( zebra_cmd )
156 host.cmd( quagga_cmd )
157
158def startquaggahost5( host, num ):
159 info( '*** Starting Quagga on %s\n' % host )
160 zebra_cmd = \
161 '%s/zebra -d -f ./zebra.conf -z %s/zserv%s.api -i %s/zebra%s.pid' \
162 % ( QUAGGA_DIR, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num )
163 quagga_cmd = \
164 '%s/bgpd -d -f ./as4quaggas/quagga%s.conf -z %s/zserv%s.api -i %s/bgpd%s.pid'\
165 % ( QUAGGA_DIR, num, QUAGGA_RUN_DIR, num, QUAGGA_RUN_DIR, num )
166
167 host.cmd( zebra_cmd )
168 host.cmd( quagga_cmd )
169
170
171def stopquagga():
172 quietRun( 'sudo pkill -9 -f bgpd' )
173 quietRun( 'sudo pkill -9 -f zebra' )
174
175def sdn1net():
176 topo = SDNTopo()
177 info( '*** Creating network\n' )
178 net = Mininet( topo = topo, controller = RemoteController )
179
180 host1, host2, host3, host4, host5 = \
181 net.get( 'host1', 'host2' , 'host3', 'host4', 'host5' )
182
183 # Adding 2nd, 3rd and 4th interface to host1 connected to sw1
184 # for another BGP peering
185 host1.setMAC( '00:00:00:00:00:01', 'host1-eth0' )
186 host1.cmd( 'ip addr add 192.168.20.101/24 dev host1-eth0' )
187 host1.cmd( 'ip addr add 192.168.30.101/24 dev host1-eth0' )
188 host1.cmd( 'ip addr add 192.168.40.101/24 dev host1-eth0' )
189 host1.cmd( 'ip addr add 192.168.60.101/24 dev host1-eth0' )
190
191 # Net has to be start after adding the above link
192 net.start()
193 for i in range( numHost101, numHost200 + 1 ):
194 host100 = net.get( 'host%s' % ( i ) )
195 host100.cmd( 'ifconfig host%s-eth0 192.168.40.%s up' % ( i, i - 100 ) )
196 host100.setIP( str( i ) + ".0.0.254", 8, str( host100 ) + "-eth1" )
197 host100.setMAC( '00:00:' + str( i - 101 ) + ':00:00:90', 'host'
198 + str( i ) + '-eth0' )
199 host100.cmd( 'sysctl net.ipv4.conf.all.forwarding=1' )
200
201 # Set up as6sw as a learning switch as quickly as possible so it
202 # hopefully doesn't connect to the actual controller
203 # TODO figure out how to change controller before starting switch
204 as6sw = net.get( 'as6sw' )
205 as6sw.cmd( 'ovs-vsctl set-controller as6sw none' )
206 as6sw.cmd( 'ovs-vsctl set-fail-mode as6sw standalone' )
207
208
209 sw1, sw2, sw3, sw4, sw5, sw6 = \
210 net.get( 'sw1', 'sw2', 'sw3', 'sw4', 'sw5', 'sw6' )
211 sw1.cmd( 'ovs-vsctl set-controller sw1 tcp:10.128.4.52:6633' )
212 sw2.cmd( 'ovs-vsctl set-controller sw2 tcp:10.128.4.52:6633' )
213 sw3.cmd( 'ovs-vsctl set-controller sw3 tcp:10.128.4.52:6633' )
214 sw4.cmd( 'ovs-vsctl set-controller sw4 tcp:10.128.4.52:6633' )
215 sw5.cmd( 'ovs-vsctl set-controller sw5 tcp:10.128.4.52:6633' )
216 sw6.cmd( 'ovs-vsctl set-controller sw6 tcp:10.128.4.52:6633' )
217
218
219 # Set up sw100 as a learning
220 sw100 = net.get( 'sw100' )
221 sw100.cmd( 'ovs-vsctl set-controller sw100 none' )
222 sw100.cmd( 'ovs-vsctl set-fail-mode sw100 standalone' )
223
224 swTestOn = net.get( 'swTestOn' )
225 swTestOn.cmd( 'ovs-vsctl set-controller swTestOn none' )
226 swTestOn.cmd( 'ovs-vsctl set-fail-mode swTestOn standalone' )
227
228 host1.defaultIntf().setIP( '192.168.10.101/24' )
229
230 # Configure new host interfaces
231 host2.defaultIntf().setIP( '172.16.10.2/24' )
232 host2.defaultIntf().setMAC( '00:00:00:00:01:02' )
233
234 # Set up AS2
235 host3.setIP( '192.168.10.1', 24, 'host3-eth0' )
236 host3.setIP( '192.168.20.1', 24, 'host3-eth1' )
237 host3.setMAC( '00:00:00:00:02:01', 'host3-eth0' )
238 host3.setMAC( '00:00:00:00:02:02', 'host3-eth1' )
239 host3.setIP( '3.0.0.254', 8, 'host3-eth2' )
240 host3.cmd( 'sysctl net.ipv4.conf.all.forwarding=1' )
241
242 host3.setIP( '1.168.30.2', 24, 'host3-eth3' )
243 host3.cmd( 'sysctl net.ipv4.conf.all.arp_ignore=1' )
244 host3.cmd( 'sysctl net.ipv4.conf.all.arp_announce=1' )
245 as2host = net.get( 'as2host' )
246
247 for i in range( 0, 20 ):
248 as2host.cmd( 'sudo ip addr add 3.0.%d.1/24 dev as2host-eth0' % i )
249 as2host.setIP( '1.168.30.100', 24, 'as2host-eth1' )
250
251 as2host.cmd( 'ip route add default via 3.0.0.254' )
252
253 # Set up AS3
254 host4.setIP( '192.168.30.1', 24, 'host4-eth0' )
255 host4.setMAC( '00:00:00:00:03:01', 'host4-eth0' )
256 host4.setIP( '4.0.0.254', 8, 'host4-eth1' )
257 host4.setMAC( '00:00:00:00:03:99', 'host4-eth1' )
258 host4.cmd( 'sysctl net.ipv4.conf.all.forwarding=1' )
259 as3host = net.get( 'as3host' )
260 for i in range( 0, 20 ):
261 as3host.cmd( 'sudo ip addr add 4.0.%d.1/24 dev as3host-eth0' % i )
262 as3host.cmd( 'ip route add default via 4.0.0.254' )
263
264 # root space
265 host4.setIP( '1.168.30.3', 24, 'host4-eth2' )
266 host4.setMAC( '00:00:00:00:03:03', 'host4-eth2' )
267
268 # setup interface address for 100 quagga hosts
269 time.sleep( 10 )
270 for i in range( numHost101, numHost200 + 1 ):
271 as4host100 = net.get( 'as4host%s' % ( i ) )
272 as4host100.defaultIntf().setIP( str( i ) + '.0.0.1/24' )
273 as4host100.cmd( 'ip route add default via ' + str( i ) + '.0.0.254' )
274 for j in range( 0, 100 ):
275 as4host100.cmd( 'sudo ip addr add %d.0.%d.1/24 dev %s-eth0' \
276 % ( i, j, as4host100 ) )
277
278 # Set up AS6 - This has a router and a route server
279 as6rs, host5 = net.get( 'as6rs', 'host5' )
280 as6rs.setIP( '192.168.60.1', 24, 'as6rs-eth0' )
281 as6rs.setMAC( '00:00:00:00:06:01', 'as6rs-eth0' )
282 host5.setIP( '192.168.60.2', 24, 'host5-eth0' )
283 host5.setMAC( '00:00:00:00:06:02', 'host5-eth0' )
284 host5.setIP( '5.0.0.254', 8, 'host5-eth1' )
285 host5.cmd( 'sysctl net.ipv4.conf.all.forwarding=1' )
286 host5.setIP( '1.168.30.5', 24, 'host5-eth2' )
287 host5.setMAC( '00:00:00:00:06:05', 'host5-eth2' )
288
289 as6host = net.get( 'as6host' )
290 as6host.defaultIntf().setIP( '5.0.0.1/24' )
291 as6host.cmd( 'ip route add default via 5.0.0.254' )
292 for i in range( 0, 10 ):
293 as6host.cmd( 'sudo ip addr add 5.0.%d.1/24 dev as6host-eth0' % i )
294
295 # test the host in the as6
296 '''
297 for i in range(1, 10):
298 baseip = (i-1)*4
299 host = net.get('as6host%d' % i)
300 host.defaultIntf().setIP('172.16.70.%d/24' % (baseip+1))
301 host.cmd('ip route add default via 172.16.70.%d' % (baseip+2))
302 as6router.setIP('172.16.70.%d' % (baseip+2), 30, 'as6router-eth%d' % (i+1))
303 '''
304
305 # Start Quagga on border routers
306 startquagga( host3, 1, 'quagga1.conf' )
307 startquagga( host4, 2, 'quagga2.conf' )
308 for i in range( numHost101, numHost200 + 1 ):
309 host100 = net.get( 'host%d' % ( i ) )
310 startquaggahost5( host100, i )
311
312 startquagga( as6rs, 4, 'quagga-as6-rs.conf' )
313 startquagga( host5, 5, 'quagga-as6.conf' )
314
315 root1, root2, rootTestOn = net.get( 'root1', 'root2', 'rootTestOn' )
316 host1.intf( 'host1-eth1' ).setIP( '1.1.1.1/24' )
317 root1.intf( 'root1-eth0' ).setIP( '1.1.1.2/24' )
318 host2.intf( 'host2-eth1' ).setIP( '1.1.2.1/24' )
319 root2.intf( 'root2-eth0' ).setIP( '1.1.2.2/24' )
320
321 rootTestOn.cmd( 'ip addr add 1.168.30.99/24 dev rootTestOn-eth0' )
322
323 stopsshd()
324 for i in range( numHost101, numHost200 + 1 ):
325 hostX = net.get( 'host%s' % ( i ) )
326 hostX.setIP( '1.168.30.' + str( i ), 24, str( "host" ) + str( i )
327 + "-eth2" )
328 startsshd( hostX )
329
330 startquagga( host1, 100, 'quagga-sdn.conf' )
331 hosts = [ host1, host2, host3, host4, host5, as2host ];
332 startsshds( hosts )
333 #
334 onos1 = '10.128.4.52'
335 forwarding1 = '%s:2000:%s:2000' % ( '1.1.1.2', onos1 )
336 root1.cmd( 'ssh -nNT -o "PasswordAuthentication no" \
337 -o "StrictHostKeyChecking no" -l sdn -L %s %s & ' % ( forwarding1, onos1 ) )
338
339 # Forward 2605 to root namespace for easier access to SDN domain BGPd
340 # If root can ssh to itself without a password this should work
341 '''
342 root1.cmd('ssh -N -o "PasswordAuthentication no" \
343 -o "StrictHostKeyChecking no" -L 2605:1.1.1.1:2605 1.1.1.1 &')
344 '''
345 time.sleep( 3000000000 )
346 CLI( net )
347
348 # Close the ssh port forwarding
349 # quietRun('sudo pkill -f 1.1.1.1')
350
351 stopsshd()
352 stopquagga()
353 net.stop()
354
355if __name__ == '__main__':
356 setLogLevel( 'debug' )
357 sdn1net()