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