]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/ospf6-topo1/test_ospf6_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
29 SW1 - Stub Net 1 SW2 - Stub Net 2 \
30 fc00:1:1:1::/64 fc00:2:2:2::/64 \
31 \___________________/ \___________________/ |
35 +---------+---------+ +---------+---------+ |
37 | FRRouting | | FRRouting | |
38 | Rtr-ID: 10.0.0.1 | | Rtr-ID: 10.0.0.2 | |
39 +---------+---------+ +---------+---------+ |
41 \______ ___________/ OSPFv3
47 ~~ fc00:A:A:A::/64 ~~ |
50 | ::3 | SW3 - Stub Net 3 |
51 +---------+---------+ /-+ fc00:3:3:3::/64 |
53 | FRRouting +--/ \---- /
54 | Rtr-ID: 10.0.0.3 | ::3 ___________/
55 +---------+---------+ \
61 ~~ fc00:B:B:B::/64 ~~ \
62 ~~~~~~~~~~~~~~~~~~ OSPFv3
65 +---------+---------+ /---- |
66 | R4 | | SW4 - Stub Net 4 |
67 | FRRouting +------+ fc00:4:4:4::/64 |
68 | Rtr-ID: 10.0.0.4 | ::4 | /
69 +-------------------+ \---- /
77 from time
import sleep
79 from functools
import partial
81 from mininet
.topo
import Topo
83 # Save the Current Working Directory to find configuration files later.
84 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
85 sys
.path
.append(os
.path
.join(CWD
, '../'))
87 # pylint: disable=C0413
88 # Import topogen and topotest helpers
89 from lib
import topotest
90 from lib
.topogen
import Topogen
, TopoRouter
, get_topogen
91 from lib
.topolog
import logger
94 #####################################################
96 ## Network Topology Definition
98 #####################################################
100 class NetworkTopo(Topo
):
101 "OSPFv3 (IPv6) Test Topology 1"
103 def build(self
, **_opts
):
106 tgen
= get_topogen(self
)
109 for routern
in range(1, 5):
110 tgen
.add_router('r{}'.format(routern
))
113 # Wire up the switches and routers
114 # Note that we specify the link names so we match the config files
117 # Create a empty network for router 1
118 switch
= tgen
.add_switch('s1')
119 switch
.add_link(tgen
.gears
['r1'], nodeif
='r1-stubnet')
121 # Create a empty network for router 2
122 switch
= tgen
.add_switch('s2')
123 switch
.add_link(tgen
.gears
['r2'], nodeif
='r2-stubnet')
125 # Create a empty network for router 3
126 switch
= tgen
.add_switch('s3')
127 switch
.add_link(tgen
.gears
['r3'], nodeif
='r3-stubnet')
129 # Create a empty network for router 4
130 switch
= tgen
.add_switch('s4')
131 switch
.add_link(tgen
.gears
['r4'], nodeif
='r4-stubnet')
133 # Interconnect routers 1, 2, and 3
134 switch
= tgen
.add_switch('s5')
135 switch
.add_link(tgen
.gears
['r1'], nodeif
='r1-sw5')
136 switch
.add_link(tgen
.gears
['r2'], nodeif
='r2-sw5')
137 switch
.add_link(tgen
.gears
['r3'], nodeif
='r3-sw5')
139 # Interconnect routers 3 and 4
140 switch
= tgen
.add_switch('s6')
141 switch
.add_link(tgen
.gears
['r3'], nodeif
='r3-sw6')
142 switch
.add_link(tgen
.gears
['r4'], nodeif
='r4-sw6')
145 #####################################################
149 #####################################################
151 def setup_module(mod
):
152 "Sets up the pytest environment"
154 tgen
= Topogen(NetworkTopo
, mod
.__name
__)
155 tgen
.start_topology()
157 logger
.info("** %s: Setup Topology" % mod
.__name
__)
158 logger
.info("******************************************")
160 # For debugging after starting net, but before starting FRR,
161 # uncomment the next line
164 router_list
= tgen
.routers()
165 for rname
, router
in router_list
.iteritems():
168 os
.path
.join(CWD
, '{}/zebra.conf'.format(rname
))
172 os
.path
.join(CWD
, '{}/ospf6d.conf'.format(rname
))
175 # Initialize all routers.
178 # For debugging after starting FRR daemons, uncomment the next line
182 def teardown_module(mod
):
183 "Teardown the pytest environment"
188 def test_ospf6_converged():
192 # Don't run this test if we have any failure.
193 if tgen
.routers_have_failure():
194 pytest
.skip(tgen
.errors
)
196 # For debugging, uncomment the next line
199 # Wait for OSPF6 to converge (All Neighbors in either Full or TwoWay State)
200 logger
.info("Waiting for OSPF6 convergence")
203 pat1
= re
.compile('^[0-9]')
204 pat2
= re
.compile('Full')
208 logger
.info("Timeout in %s: " % timeout
),
211 # Look for any node not yet converged
212 for router
, rnode
in tgen
.routers().iteritems():
213 resStr
= rnode
.vtysh_cmd('show ipv6 ospf neigh')
217 for line
in resStr
.splitlines():
218 res1
= pat1
.match(line
)
221 res2
= pat2
.search(line
)
227 if isConverged
== False:
228 logger
.info('Waiting for {}'.format(router
))
240 # Bail out with error if a router fails to converge
241 ospfStatus
= rnode
.vtysh_cmd('show ipv6 ospf neigh')
242 assert False, "OSPFv6 did not converge:\n{}".format(ospfStatus
)
244 logger
.info("OSPFv3 converged.")
246 # For debugging, uncomment the next line
249 # Make sure that all daemons are still running
250 if tgen
.routers_have_failure():
251 assert tgen
.errors
== "", tgen
.errors
253 def compare_show_ipv6(rname
, expected
):
255 Calls 'show ipv6 route' for router `rname` and compare the obtained
256 result with the expected output.
260 # Use the vtysh output, with some masking to make comparison easy
261 current
= topotest
.ip6_route_zebra(tgen
.gears
[rname
])
263 # Use just the 'O'spf lines of the output
265 for line
in current
.splitlines():
266 if re
.match('^O', line
):
269 current
= '\n'.join(linearr
)
271 return topotest
.difflines(topotest
.normalize_text(current
),
272 topotest
.normalize_text(expected
),
273 title1
="Current output",
274 title2
="Expected output")
276 def test_ospfv3_routingTable():
279 if tgen
.routers_have_failure():
280 pytest
.skip('skipped because of router(s) failure')
282 # For debugging, uncomment the next line
285 # Verify OSPFv3 Routing Table
286 for router
, rnode
in tgen
.routers().iteritems():
287 logger
.info('Waiting for router "%s" convergence', router
)
289 # Load expected results from the command
290 reffile
= os
.path
.join(CWD
, '{}/show_ipv6_route.ref'.format(router
))
291 expected
= open(reffile
).read()
293 # Run test function until we get an result. Wait at most 60 seconds.
295 compare_show_ipv6
, router
, expected
)
296 result
, diff
= topotest
.run_and_expect(test_func
, '',
298 assert result
, 'OSPFv3 did not converge on {}:\n{}'.format(router
, diff
)
301 def test_linux_ipv6_kernel_routingTable():
305 if tgen
.routers_have_failure():
306 pytest
.skip('skipped because of router(s) failure')
308 # Verify Linux Kernel Routing Table
309 logger
.info("Verifying Linux IPv6 Kernel Routing Table")
313 # Get a list of all current link-local addresses first as they change for
314 # each run and we need to translate them
316 for i
in range(1, 5):
317 linklocals
+= tgen
.net
['r{}'.format(i
)].get_ipv6_linklocal()
319 # Now compare the routing tables (after substituting link-local addresses)
321 for i
in range(1, 5):
322 # Actual output from router
323 actual
= tgen
.gears
['r{}'.format(i
)].run('ip -6 route').rstrip()
325 refTableFile
= os
.path
.join(CWD
, 'r{}/ip_6_address.nhg.ref'.format(i
))
327 refTableFile
= os
.path
.join(CWD
, 'r{}/ip_6_address.ref'.format(i
))
329 if os
.path
.isfile(refTableFile
):
330 expected
= open(refTableFile
).read().rstrip()
331 # Fix newlines (make them all the same)
332 expected
= ('\n'.join(expected
.splitlines())).splitlines(1)
334 # Mask out Link-Local mac addresses
335 for ll
in linklocals
:
336 actual
= actual
.replace(ll
[1], "fe80::__(%s)__" % ll
[0])
337 # Mask out protocol name or number
338 actual
= re
.sub(r
"[ ]+proto [0-9a-z]+ +", " proto XXXX ", actual
)
339 actual
= re
.sub(r
"[ ]+nhid [0-9]+ +", " nhid XXXX ", actual
)
340 # Remove ff00::/8 routes (seen on some kernels - not from FRR)
341 actual
= re
.sub(r
'ff00::/8.*', '', actual
)
344 actual
= actual
.lstrip()
345 actual
= actual
.rstrip()
346 actual
= re
.sub(r
' +', ' ', actual
)
349 for line
in sorted(actual
.splitlines()):
350 if line
.startswith('fe80::/64 ') \
351 or line
.startswith('unreachable fe80::/64 '):
353 filtered_lines
.append(line
)
354 actual
= '\n'.join(filtered_lines
).splitlines(1)
357 # logger.info("Router r%s table" % i)
358 # for line in actual:
359 # logger.info(line.rstrip())
362 diff
= topotest
.get_textdiff(actual
, expected
,
363 title1
="actual OSPFv3 IPv6 routing table",
364 title2
="expected OSPFv3 IPv6 routing table")
366 # Empty string if it matches, otherwise diff contains unified diff
368 sys
.stderr
.write('r%s failed Linux IPv6 Kernel Routing Table Check:\n%s\n' % (i
, diff
))
371 logger
.info("r%s ok" % i
)
373 assert failures
== 0, "Linux Kernel IPv6 Routing Table verification failed for router r%s:\n%s" % (i
, diff
)
376 def test_shutdown_check_stderr():
380 if tgen
.routers_have_failure():
381 pytest
.skip('skipped because of router(s) failure')
383 if os
.environ
.get('TOPOTESTS_CHECK_STDERR') is None:
384 logger
.info("SKIPPED final check on StdErr output: Disabled (TOPOTESTS_CHECK_STDERR undefined)\n")
385 pytest
.skip('Skipping test for Stderr output')
389 logger
.info("\n\n** Verifying unexpected STDERR output from daemons")
390 logger
.info("******************************************")
392 for i
in range(1, 5):
393 net
['r%s' % i
].stopRouter()
394 log
= net
['r%s' % i
].getStdErr('ospf6d')
396 logger
.info("\nRouter r%s OSPF6d StdErr Log:\n%s" % (i
, log
))
397 log
= net
['r%s' % i
].getStdErr('zebra')
399 logger
.info("\nRouter r%s Zebra StdErr Log:\n%s" % (i
, log
))
402 def test_shutdown_check_memleak():
403 "Run the memory leak test and report results."
405 if os
.environ
.get('TOPOTESTS_CHECK_MEMLEAK') is None:
406 logger
.info("SKIPPED final check on Memory leaks: Disabled (TOPOTESTS_CHECK_MEMLEAK undefined)")
407 pytest
.skip('Skipping test for memory leaks')
413 for i
in range(1, 5):
414 net
['r%s' % i
].stopRouter()
415 net
['r%s' % i
].report_memory_leaks(
416 os
.environ
.get('TOPOTESTS_CHECK_MEMLEAK'),
417 os
.path
.basename(__file__
))
420 if __name__
== '__main__':
422 # To suppress tracebacks, either use the following pytest call or
423 # add "--tb=no" to cli
424 # retval = pytest.main(["-s", "--tb=no"])
426 retval
= pytest
.main(["-s"])