]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/ripng_topo1/test_ripng_topo1.py
5 # Part of NetDEF Topology Tests
7 # Copyright (c) 2017 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_ripng_topo1.py: Test of RIPng Topology
35 from time
import sleep
37 from mininet
.topo
import Topo
38 from mininet
.net
import Mininet
39 from mininet
.node
import Node
, OVSSwitch
, Host
40 from mininet
.log
import setLogLevel
, info
41 from mininet
.cli
import CLI
42 from mininet
.link
import Intf
44 from functools
import partial
46 sys
.path
.append(os
.path
.dirname(os
.path
.dirname(os
.path
.abspath(__file__
))))
47 from lib
import topotest
51 pytestmark
= [pytest
.mark
.ripd
]
53 #####################################################
55 ## Network Topology Definition
57 #####################################################
60 class NetworkTopo(Topo
):
63 def build(self
, **_opts
):
69 router
[1] = topotest
.addRouter(self
, "r1")
73 router
[i
] = topotest
.addRouter(self
, "r%s" % i
)
79 # First switch is for a dummy interface (for local network)
80 switch
[1] = self
.addSwitch("sw1", cls
=topotest
.LegacySwitch
)
81 self
.addLink(switch
[1], router
[1], intfName2
="r1-eth0")
84 # switch 2 switch is for connection to RIP router
85 switch
[2] = self
.addSwitch("sw2", cls
=topotest
.LegacySwitch
)
86 self
.addLink(switch
[2], router
[1], intfName2
="r1-eth1")
87 self
.addLink(switch
[2], router
[2], intfName2
="r2-eth0")
88 # switch 3 is between RIP routers
89 switch
[3] = self
.addSwitch("sw3", cls
=topotest
.LegacySwitch
)
90 self
.addLink(switch
[3], router
[2], intfName2
="r2-eth1")
91 self
.addLink(switch
[3], router
[3], intfName2
="r3-eth1")
92 # switch 4 is stub on remote RIP router
93 switch
[4] = self
.addSwitch("sw4", cls
=topotest
.LegacySwitch
)
94 self
.addLink(switch
[4], router
[3], intfName2
="r3-eth0")
96 switch
[5] = self
.addSwitch("sw5", cls
=topotest
.LegacySwitch
)
97 self
.addLink(switch
[5], router
[1], intfName2
="r1-eth2")
98 switch
[6] = self
.addSwitch("sw6", cls
=topotest
.LegacySwitch
)
99 self
.addLink(switch
[6], router
[1], intfName2
="r1-eth3")
102 #####################################################
106 #####################################################
109 def setup_module(module
):
112 print("\n\n** %s: Setup Topology" % module
.__name
__)
113 print("******************************************\n")
115 print("Cleanup old Mininet runs")
116 os
.system("sudo mn -c > /dev/null 2>&1")
118 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
121 net
= Mininet(controller
=None, topo
=topo
)
126 for i
in range(1, 4):
127 net
["r%s" % i
].loadConf("zebra", "%s/r%s/zebra.conf" % (thisDir
, i
))
128 net
["r%s" % i
].loadConf("ripngd", "%s/r%s/ripngd.conf" % (thisDir
, i
))
129 net
["r%s" % i
].startRouter()
131 # For debugging after starting FRR daemons, uncomment the next line
135 def teardown_module(module
):
138 print("\n\n** %s: Shutdown Topology" % module
.__name
__)
139 print("******************************************\n")
141 # End - Shutdown network
145 def test_router_running():
149 # Skip if previous fatal error condition is raised
150 if fatal_error
!= "":
151 pytest
.skip(fatal_error
)
153 print("\n\n** Check if FRR is running on each Router node")
154 print("******************************************\n")
157 for i
in range(1, 4):
158 fatal_error
= net
["r%s" % i
].checkRouterRunning()
159 assert fatal_error
== "", fatal_error
161 # For debugging after starting FRR daemons, uncomment the next line
165 def test_converge_protocols():
169 # Skip if previous fatal error condition is raised
170 if fatal_error
!= "":
171 pytest
.skip(fatal_error
)
173 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
175 print("\n\n** Waiting for protocols convergence")
176 print("******************************************\n")
178 # Not really implemented yet - just sleep 11 secs for now
181 # Make sure that all daemons are running
182 for i
in range(1, 4):
183 fatal_error
= net
["r%s" % i
].checkRouterRunning()
184 assert fatal_error
== "", fatal_error
186 # For debugging after starting FRR daemons, uncomment the next line
190 def test_ripng_status():
194 # Skip if previous fatal error condition is raised
195 if fatal_error
!= "":
196 pytest
.skip(fatal_error
)
198 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
201 print("\n\n** Verifying RIPng status")
202 print("******************************************\n")
204 for i
in range(1, 4):
205 refTableFile
= "%s/r%s/ripng_status.ref" % (thisDir
, i
)
206 if os
.path
.isfile(refTableFile
):
207 # Read expected result from file
208 expected
= open(refTableFile
).read().rstrip()
209 # Fix newlines (make them all the same)
210 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
212 # Actual output from router
215 .cmd('vtysh -c "show ipv6 ripng status" 2> /dev/null')
218 # Mask out Link-Local mac address portion. They are random...
219 actual
= re
.sub(r
" fe80::[0-9a-f:]+", " fe80::XXXX:XXXX:XXXX:XXXX", actual
)
220 # Drop time in next due
221 actual
= re
.sub(r
"in [0-9]+ seconds", "in XX seconds", actual
)
222 # Drop time in last update
223 actual
= re
.sub(r
" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual
)
224 # Fix newlines (make them all the same)
225 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
228 diff
= topotest
.get_textdiff(
231 title1
="actual IPv6 RIPng status",
232 title2
="expected IPv6 RIPng status",
235 # Empty string if it matches, otherwise diff contains unified diff
238 "r%s failed IPv6 RIPng status check:\n%s\n" % (i
, diff
)
244 assert failures
== 0, "IPv6 RIPng status failed for router r%s:\n%s" % (
249 # Make sure that all daemons are running
250 for i
in range(1, 4):
251 fatal_error
= net
["r%s" % i
].checkRouterRunning()
252 assert fatal_error
== "", fatal_error
254 # For debugging after starting FRR daemons, uncomment the next line
258 def test_ripng_routes():
262 # Skip if previous fatal error condition is raised
263 if fatal_error
!= "":
264 pytest
.skip(fatal_error
)
266 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
268 # Verify RIPng Status
269 print("\n\n** Verifying RIPng routes")
270 print("******************************************\n")
272 for i
in range(1, 4):
273 refTableFile
= "%s/r%s/show_ipv6_ripng.ref" % (thisDir
, i
)
274 if os
.path
.isfile(refTableFile
):
275 # Read expected result from file
276 expected
= open(refTableFile
).read().rstrip()
277 # Fix newlines (make them all the same)
278 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
280 # Actual output from router
282 net
["r%s" % i
].cmd('vtysh -c "show ipv6 ripng" 2> /dev/null').rstrip()
285 actual
= re
.sub(r
" [0-9][0-9]:[0-5][0-9]", " XX:XX", actual
)
286 # Mask out Link-Local mac address portion. They are random...
288 r
" fe80::[0-9a-f: ]+", " fe80::XXXX:XXXX:XXXX:XXXX ", actual
290 # Remove trailing spaces on all lines
291 actual
= "\n".join([line
.rstrip() for line
in actual
.splitlines()])
293 # Fix newlines (make them all the same)
294 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
297 diff
= topotest
.get_textdiff(
300 title1
="actual SHOW IPv6 RIPng",
301 title2
="expected SHOW IPv6 RIPng",
304 # Empty string if it matches, otherwise diff contains unified diff
306 sys
.stderr
.write("r%s failed SHOW IPv6 RIPng check:\n%s\n" % (i
, diff
))
311 assert failures
== 0, "SHOW IPv6 RIPng failed for router r%s:\n%s" % (
316 # Make sure that all daemons are running
317 for i
in range(1, 4):
318 fatal_error
= net
["r%s" % i
].checkRouterRunning()
319 assert fatal_error
== "", fatal_error
321 # For debugging after starting FRR daemons, uncomment the next line
325 def test_zebra_ipv6_routingTable():
329 # Skip if previous fatal error condition is raised
330 if fatal_error
!= "":
331 pytest
.skip(fatal_error
)
333 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
335 # Verify OSPFv3 Routing Table
336 print("\n\n** Verifying Zebra IPv6 Routing Table")
337 print("******************************************\n")
339 for i
in range(1, 4):
340 refTableFile
= "%s/r%s/show_ipv6_route.ref" % (thisDir
, i
)
341 if os
.path
.isfile(refTableFile
):
342 # Read expected result from file
343 expected
= open(refTableFile
).read().rstrip()
344 # Fix newlines (make them all the same)
345 expected
= ("\n".join(expected
.splitlines()) + "\n").splitlines(1)
347 # Actual output from router
350 .cmd('vtysh -c "show ipv6 route" 2> /dev/null | grep "^R"')
353 # Mask out Link-Local mac address portion. They are random...
354 actual
= re
.sub(r
" fe80::[0-9a-f:]+", " fe80::XXXX:XXXX:XXXX:XXXX", actual
)
355 # Drop timers on end of line
356 actual
= re
.sub(r
", [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", "", actual
)
357 # Fix newlines (make them all the same)
358 actual
= ("\n".join(actual
.splitlines()) + "\n").splitlines(1)
361 diff
= topotest
.get_textdiff(
364 title1
="actual Zebra IPv6 routing table",
365 title2
="expected Zebra IPv6 routing table",
368 # Empty string if it matches, otherwise diff contains unified diff
371 "r%s failed Zebra IPv6 Routing Table Check:\n%s\n" % (i
, diff
)
379 ), "Zebra IPv6 Routing Table verification failed for router r%s:\n%s" % (
384 # Make sure that all daemons are running
385 for i
in range(1, 4):
386 fatal_error
= net
["r%s" % i
].checkRouterRunning()
387 assert fatal_error
== "", fatal_error
389 # For debugging after starting FRR daemons, uncomment the next line
393 def test_shutdown_check_stderr():
397 # Skip if previous fatal error condition is raised
398 if fatal_error
!= "":
399 pytest
.skip(fatal_error
)
401 if os
.environ
.get("TOPOTESTS_CHECK_STDERR") is None:
403 "SKIPPED final check on StdErr output: Disabled (TOPOTESTS_CHECK_STDERR undefined)\n"
405 pytest
.skip("Skipping test for Stderr output")
407 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
409 print("\n\n** Verifying unexpected STDERR output from daemons")
410 print("******************************************\n")
412 net
["r1"].stopRouter()
414 log
= net
["r1"].getStdErr("ripngd")
416 print("\nRIPngd StdErr Log:\n" + log
)
417 log
= net
["r1"].getStdErr("zebra")
419 print("\nZebra StdErr Log:\n" + log
)
422 def test_shutdown_check_memleak():
426 # Skip if previous fatal error condition is raised
427 if fatal_error
!= "":
428 pytest
.skip(fatal_error
)
430 if os
.environ
.get("TOPOTESTS_CHECK_MEMLEAK") is None:
432 "SKIPPED final check on Memory leaks: Disabled (TOPOTESTS_CHECK_MEMLEAK undefined)\n"
434 pytest
.skip("Skipping test for memory leaks")
436 thisDir
= os
.path
.dirname(os
.path
.realpath(__file__
))
438 net
["r1"].stopRouter()
439 net
["r1"].report_memory_leaks(
440 os
.environ
.get("TOPOTESTS_CHECK_MEMLEAK"), os
.path
.basename(__file__
)
444 if __name__
== "__main__":
447 # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli
448 # retval = pytest.main(["-s", "--tb=no"])
449 retval
= pytest
.main(["-s"])