]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/bgp_multiview_topo1/test_bgp_multiview_topo1.py
4 # test_bgp_multiview_topo1.py
5 # Part of NetDEF Topology Tests
7 # Copyright (c) 2016 by
8 # Network Device Education Foundation, Inc. ("NetDEF")
10 # Permission to use, copy, modify, and/or distribute this software
11 # for any purpose with or without fee is hereby granted, provided
12 # that the above copyright notice and this permission notice appear
15 # THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
16 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
18 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
19 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
21 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
26 test_bgp_multiview_topo1.py: Simple Quagga/FRR Route-Server Test
28 +----------+ +----------+ +----------+ +----------+ +----------+
29 | peer1 | | peer2 | | peer3 | | peer4 | | peer5 |
30 | AS 65001 | | AS 65002 | | AS 65003 | | AS 65004 | | AS 65005 |
31 +-----+----+ +-----+----+ +-----+----+ +-----+----+ +-----+----+
32 | .1 | .2 | .3 | .4 | .5
33 | ______/ / / _________/
34 \ / ________________/ / /
35 | | / _________________________/ / +----------+
36 | | | / __________________________/ ___| peer6 |
37 | | | | / ____________________________/.6 | AS 65006 |
38 | | | | | / _________________________ +----------+
39 | | | | | | / __________________ \ +----------+
40 | | | | | | | / \ \___| peer7 |
41 | | | | | | | | \ .7 | AS 65007 |
42 ~~~~~~~~~~~~~~~~~~~~~ \ +----------+
43 ~~ SW1 ~~ \ +----------+
44 ~~ Switch ~~ \_____| peer8 |
45 ~~ 172.16.1.0/24 ~~ .8 | AS 65008 |
46 ~~~~~~~~~~~~~~~~~~~~~ +----------+
58 ~~~~~~~~~~~~~ Stub Network is redistributed
59 ~~ SW0 ~~ into each BGP view with different
60 ~~ 172.20.0.1/28 ~~ attributes (using route-map)
70 from time
import sleep
72 from mininet
.topo
import Topo
73 from mininet
.net
import Mininet
74 from mininet
.node
import Node
, OVSSwitch
, Host
75 from mininet
.log
import setLogLevel
, info
76 from mininet
.cli
import CLI
77 from mininet
.link
import Intf
79 from functools
import partial
81 sys
.path
.append(os
.path
.dirname(os
.path
.dirname(os
.path
.abspath(__file__
))))
82 from lib
import topotest
87 #####################################################
89 ## Network Topology Definition
91 #####################################################
93 class NetworkTopo(Topo
):
94 "BGP Multiview Topology 1"
96 def build(self
, **_opts
):
98 exabgpPrivateDirs
= ['/etc/exabgp',
104 for i
in range(1, 2):
105 router
[i
] = topotest
.addRouter(self
, 'r%s' % i
)
107 # Setup Provider BGP peers
109 for i
in range(1, 9):
110 peer
[i
] = self
.addHost('peer%s' % i
, ip
='172.16.1.%s/24' % i
,
111 defaultRoute
='via 172.16.1.254',
112 privateDirs
=exabgpPrivateDirs
)
116 # First switch is for a dummy interface (for local network)
117 switch
[0] = self
.addSwitch('sw0', cls
=topotest
.LegacySwitch
)
118 self
.addLink(switch
[0], router
[1], intfName2
='r1-stub')
119 # Second switch is for connection to all peering routers
120 switch
[1] = self
.addSwitch('sw1', cls
=topotest
.LegacySwitch
)
121 self
.addLink(switch
[1], router
[1], intfName2
='r1-eth0')
122 for j
in range(1, 9):
123 self
.addLink(switch
[1], peer
[j
], intfName2
='peer%s-eth0' % j
)
126 #####################################################
130 #####################################################
132 def setup_module(module
):
135 print("\n\n** %s: Setup Topology" % module
.__name
__)
136 print("******************************************\n")
138 print("Cleanup old Mininet runs")
139 os
.system('sudo mn -c > /dev/null 2>&1')
141 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
144 net
= Mininet(controller
=None, topo
=topo
)
148 for i
in range(1, 2):
149 net
['r%s' % i
].loadConf('zebra', '%s/r%s/zebra.conf' % (thisDir
, i
))
150 net
['r%s' % i
].loadConf('bgpd', '%s/r%s/bgpd.conf' % (thisDir
, i
))
151 net
['r%s' % i
].startRouter()
153 # Starting PE Hosts and init ExaBGP on each of them
154 print('*** Starting BGP on all 8 Peers in 10s')
156 for i
in range(1, 9):
157 net
['peer%s' % i
].cmd('cp %s/exabgp.env /etc/exabgp/exabgp.env' % thisDir
)
158 net
['peer%s' % i
].cmd('cp %s/peer%s/* /etc/exabgp/' % (thisDir
, i
))
159 net
['peer%s' % i
].cmd('chmod 644 /etc/exabgp/*')
160 net
['peer%s' % i
].cmd('chmod 755 /etc/exabgp/*.py')
161 net
['peer%s' % i
].cmd('chown -R exabgp:exabgp /etc/exabgp')
162 net
['peer%s' % i
].cmd('exabgp -e /etc/exabgp/exabgp.env /etc/exabgp/exabgp.cfg')
166 # For debugging after starting Quagga/FRR daemons, uncomment the next line
169 def teardown_module(module
):
172 print("\n\n** %s: Shutdown Topology" % module
.__name
__)
173 print("******************************************\n")
175 # Shutdown - clean up everything
176 print('*** Killing BGP on Peer routers')
178 for i
in range(1, 9):
179 net
['peer%s' % i
].cmd('kill `cat /var/run/exabgp/exabgp.pid`')
181 # End - Shutdown network
184 def test_router_running():
188 # Skip if previous fatal error condition is raised
189 if (fatal_error
!= ""):
190 pytest
.skip(fatal_error
)
192 print("\n\n** Check if FRR/Quagga is running on each Router node")
193 print("******************************************\n")
197 for i
in range(1, 2):
198 fatal_error
= net
['r%s' % i
].checkRouterRunning()
199 assert fatal_error
== "", fatal_error
201 # For debugging after starting FRR/Quagga daemons, uncomment the next line
205 def test_bgp_converge():
206 "Check for BGP converged on all peers and BGP views"
211 # Skip if previous fatal error condition is raised
212 if (fatal_error
!= ""):
213 pytest
.skip(fatal_error
)
215 # Wait for BGP to converge (All Neighbors in either Full or TwoWay State)
216 print("\n\n** Verify for BGP to converge")
217 print("******************************************\n")
220 print("Timeout in %s: " % timeout
),
222 # Look for any node not yet converged
223 for i
in range(1, 2):
224 for view
in range(1, 4):
225 notConverged
= net
['r%s' % i
].cmd('vtysh -c "show ip bgp view %s summary" 2> /dev/null | grep ^[0-9] | grep -v " 11$"' % view
)
227 print('Waiting for r%s, view %s' % (i
, view
))
239 # Bail out with error if a router fails to converge
240 bgpStatus
= net
['r%s' % i
].cmd('vtysh -c "show ip bgp view %s summary"' % view
)
241 assert False, "BGP did not converge:\n%s" % bgpStatus
243 # Wait for an extra 30s to announce all routes
244 print('Waiting 30s for routes to be announced');
247 print("BGP converged.")
250 # # Only wait if we actually went through a convergence
251 # print("\nwaiting 15s for routes to populate")
254 # Make sure that all daemons are running
255 for i
in range(1, 2):
256 fatal_error
= net
['r%s' % i
].checkRouterRunning()
257 assert fatal_error
== "", fatal_error
259 # For debugging after starting Quagga/FRR daemons, uncomment the next line
262 def test_bgp_routingTable():
266 # Skip if previous fatal error condition is raised
267 if (fatal_error
!= ""):
268 pytest
.skip(fatal_error
)
270 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
272 print("\n\n** Verifying BGP Routing Tables")
273 print("******************************************\n")
275 for i
in range(1, 2):
276 for view
in range(1, 4):
277 refTableFile
= '%s/r%s/show_ip_bgp_view_%s.ref' % (thisDir
, i
, view
)
278 if os
.path
.isfile(refTableFile
):
279 # Read expected result from file
280 expected
= open(refTableFile
).read().rstrip()
281 # Fix newlines (make them all the same)
282 expected
= ('\n'.join(expected
.splitlines()) + '\n').splitlines(1)
284 # Actual output from router
285 actual
= net
['r%s' % i
].cmd('vtysh -c "show ip bgp view %s" 2> /dev/null' % view
).rstrip()
287 # Fix inconsitent spaces between 0.99.24 and newer versions of Quagga...
288 actual
= re
.sub('0 0', '0 0', actual
)
289 actual
= re
.sub(r
'([0-9]) 32768', r
'\1 32768', actual
)
290 # Remove summary line (changed recently)
291 actual
= re
.sub(r
'Total number.*', '', actual
)
292 actual
= re
.sub(r
'Displayed.*', '', actual
)
293 actual
= actual
.rstrip()
294 # Fix table version (ignore it)
295 actual
= re
.sub(r
'(BGP table version is )[0-9]+', r
'\1XXX', actual
)
297 # Fix newlines (make them all the same)
298 actual
= ('\n'.join(actual
.splitlines()) + '\n').splitlines(1)
301 diff
= ''.join(difflib
.context_diff(actual
, expected
,
302 fromfile
="actual BGP routing table",
303 tofile
="expected BGP routing table"))
304 # Empty string if it matches, otherwise diff contains unified diff
307 sys
.stderr
.write('r%s failed Routing Table Check for view %s:\n%s\n'
313 assert failures
== 0, "Routing Table verification failed for router r%s, view %s:\n%s" % (i
, view
, diff
)
315 # Make sure that all daemons are running
316 for i
in range(1, 2):
317 fatal_error
= net
['r%s' % i
].checkRouterRunning()
318 assert fatal_error
== "", fatal_error
320 # For debugging after starting FRR/Quagga daemons, uncomment the next line
324 def test_shutdown_check_stderr():
328 # Skip if previous fatal error condition is raised
329 if (fatal_error
!= ""):
330 pytest
.skip(fatal_error
)
332 if os
.environ
.get('TOPOTESTS_CHECK_STDERR') is None:
333 print("SKIPPED final check on StdErr output: Disabled (TOPOTESTS_CHECK_STDERR undefined)\n")
334 pytest
.skip('Skipping test for Stderr output')
336 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
338 print("\n\n** Verifying unexpected STDERR output from daemons")
339 print("******************************************\n")
341 net
['r1'].stopRouter()
343 log
= net
['r1'].getStdErr('bgpd')
344 print("\nBGPd StdErr Log:\n" + log
)
345 log
= net
['r1'].getStdErr('zebra')
346 print("\nZebra StdErr Log:\n" + log
)
349 def test_shutdown_check_memleak():
353 # Skip if previous fatal error condition is raised
354 if (fatal_error
!= ""):
355 pytest
.skip(fatal_error
)
357 if os
.environ
.get('TOPOTESTS_CHECK_MEMLEAK') is None:
358 print("SKIPPED final check on Memory leaks: Disabled (TOPOTESTS_CHECK_MEMLEAK undefined)\n")
359 pytest
.skip('Skipping test for memory leaks')
361 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
363 net
['r1'].stopRouter()
364 net
['r1'].report_memory_leaks(os
.environ
.get('TOPOTESTS_CHECK_MEMLEAK'), os
.path
.basename(__file__
))
367 if __name__
== '__main__':
370 # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli
371 # retval = pytest.main(["-s", "--tb=no"])
372 retval
= pytest
.main(["-s"])