]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/ripng_topo1/test_ripng_topo1.py
doc: Add `show ipv6 rpf X:X::X:X` command to docs
[mirror_frr.git] / tests / topotests / ripng_topo1 / test_ripng_topo1.py
1 #!/usr/bin/env python
2
3 #
4 # test_ripng_topo1.py
5 # Part of NetDEF Topology Tests
6 #
7 # Copyright (c) 2017 by
8 # Network Device Education Foundation, Inc. ("NetDEF")
9 #
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
13 # in all copies.
14 #
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
22 # OF THIS SOFTWARE.
23 #
24
25 """
26 test_ripng_topo1.py: Test of RIPng Topology
27
28 """
29
30 import os
31 import re
32 import sys
33 import pytest
34 from time import sleep
35
36
37 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
38 from lib import topotest
39 from lib.topogen import Topogen, get_topogen
40
41 fatal_error = ""
42
43 pytestmark = [pytest.mark.ripd]
44
45 #####################################################
46 ##
47 ## Network Topology Definition
48 ##
49 #####################################################
50
51
52 def build_topo(tgen):
53 # Setup RIPng Routers
54 for i in range(1, 4):
55 tgen.add_router("r%s" % i)
56
57 #
58 # On main router
59 # First switch is for a dummy interface (for local network)
60 switch = tgen.add_switch("sw1")
61 switch.add_link(tgen.gears["r1"])
62 #
63 # Switches for RIPng
64 # switch 2 switch is for connection to RIP router
65 switch = tgen.add_switch("sw2")
66 switch.add_link(tgen.gears["r1"])
67 switch.add_link(tgen.gears["r2"])
68 # switch 3 is between RIP routers
69 switch = tgen.add_switch("sw3")
70 switch.add_link(tgen.gears["r2"])
71 switch.add_link(tgen.gears["r3"], nodeif="r3-eth1")
72 # switch 4 is stub on remote RIP router
73 switch = tgen.add_switch("sw4")
74 switch.add_link(tgen.gears["r3"], nodeif="r3-eth0")
75
76 switch = tgen.add_switch("sw5")
77 switch.add_link(tgen.gears["r1"])
78 switch = tgen.add_switch("sw6")
79 switch.add_link(tgen.gears["r1"])
80
81
82 #####################################################
83 ##
84 ## Tests starting
85 ##
86 #####################################################
87
88
89 def setup_module(module):
90 print("\n\n** %s: Setup Topology" % module.__name__)
91 print("******************************************\n")
92
93 thisDir = os.path.dirname(os.path.realpath(__file__))
94 tgen = Topogen(build_topo, module.__name__)
95 tgen.start_topology()
96
97 net = tgen.net
98
99 # Starting Routers
100 #
101 for i in range(1, 4):
102 net["r%s" % i].loadConf("zebra", "%s/r%s/zebra.conf" % (thisDir, i))
103 net["r%s" % i].loadConf("ripngd", "%s/r%s/ripngd.conf" % (thisDir, i))
104 tgen.gears["r%s" % i].start()
105
106 # For debugging after starting FRR daemons, uncomment the next line
107 # tgen.mininet_cli()
108
109
110 def teardown_module(module):
111 print("\n\n** %s: Shutdown Topology" % module.__name__)
112 print("******************************************\n")
113 tgen = get_topogen()
114 tgen.stop_topology()
115
116
117 def test_router_running():
118 global fatal_error
119 net = get_topogen().net
120
121 # Skip if previous fatal error condition is raised
122 if fatal_error != "":
123 pytest.skip(fatal_error)
124
125 print("\n\n** Check if FRR is running on each Router node")
126 print("******************************************\n")
127
128 # Starting Routers
129 for i in range(1, 4):
130 fatal_error = net["r%s" % i].checkRouterRunning()
131 assert fatal_error == "", fatal_error
132
133
134 def test_converge_protocols():
135 global fatal_error
136 net = get_topogen().net
137
138 # Skip if previous fatal error condition is raised
139 if fatal_error != "":
140 pytest.skip(fatal_error)
141
142 thisDir = os.path.dirname(os.path.realpath(__file__))
143
144 print("\n\n** Waiting for protocols convergence")
145 print("******************************************\n")
146
147 # Not really implemented yet - just sleep 11 secs for now
148 sleep(11)
149
150 # Make sure that all daemons are running
151 for i in range(1, 4):
152 fatal_error = net["r%s" % i].checkRouterRunning()
153 assert fatal_error == "", fatal_error
154
155
156 def test_ripng_status():
157 global fatal_error
158 net = get_topogen().net
159
160 # Skip if previous fatal error condition is raised
161 if fatal_error != "":
162 pytest.skip(fatal_error)
163
164 thisDir = os.path.dirname(os.path.realpath(__file__))
165
166 # Verify RIP Status
167 print("\n\n** Verifying RIPng status")
168 print("******************************************\n")
169 failures = 0
170 for i in range(1, 4):
171 refTableFile = "%s/r%s/ripng_status.ref" % (thisDir, i)
172 if os.path.isfile(refTableFile):
173 # Read expected result from file
174 expected = open(refTableFile).read().rstrip()
175 # Fix newlines (make them all the same)
176 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
177
178 # Actual output from router
179 actual = (
180 net["r%s" % i]
181 .cmd('vtysh -c "show ipv6 ripng status" 2> /dev/null')
182 .rstrip()
183 )
184 # Mask out Link-Local mac address portion. They are random...
185 actual = re.sub(r" fe80::[0-9a-f:]+", " fe80::XXXX:XXXX:XXXX:XXXX", actual)
186 # Drop time in next due
187 actual = re.sub(r"in [0-9]+ seconds", "in XX seconds", actual)
188 # Drop time in last update
189 actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual)
190 # Fix newlines (make them all the same)
191 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
192
193 # Generate Diff
194 diff = topotest.get_textdiff(
195 actual,
196 expected,
197 title1="actual IPv6 RIPng status",
198 title2="expected IPv6 RIPng status",
199 )
200
201 # Empty string if it matches, otherwise diff contains unified diff
202 if diff:
203 sys.stderr.write(
204 "r%s failed IPv6 RIPng status check:\n%s\n" % (i, diff)
205 )
206 failures += 1
207 else:
208 print("r%s ok" % i)
209
210 assert failures == 0, "IPv6 RIPng status failed for router r%s:\n%s" % (
211 i,
212 diff,
213 )
214
215 # Make sure that all daemons are running
216 for i in range(1, 4):
217 fatal_error = net["r%s" % i].checkRouterRunning()
218 assert fatal_error == "", fatal_error
219
220
221 def test_ripng_routes():
222 global fatal_error
223 net = get_topogen().net
224
225 # Skip if previous fatal error condition is raised
226 if fatal_error != "":
227 pytest.skip(fatal_error)
228
229 thisDir = os.path.dirname(os.path.realpath(__file__))
230
231 # Verify RIPng Status
232 print("\n\n** Verifying RIPng routes")
233 print("******************************************\n")
234 failures = 0
235 for i in range(1, 4):
236 refTableFile = "%s/r%s/show_ipv6_ripng.ref" % (thisDir, i)
237 if os.path.isfile(refTableFile):
238 # Read expected result from file
239 expected = open(refTableFile).read().rstrip()
240 # Fix newlines (make them all the same)
241 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
242
243 # Actual output from router
244 actual = (
245 net["r%s" % i].cmd('vtysh -c "show ipv6 ripng" 2> /dev/null').rstrip()
246 )
247 # Drop Time
248 actual = re.sub(r" [0-9][0-9]:[0-5][0-9]", " XX:XX", actual)
249 # Mask out Link-Local mac address portion. They are random...
250 actual = re.sub(
251 r" fe80::[0-9a-f: ]+", " fe80::XXXX:XXXX:XXXX:XXXX ", actual
252 )
253 # Remove trailing spaces on all lines
254 actual = "\n".join([line.rstrip() for line in actual.splitlines()])
255
256 # Fix newlines (make them all the same)
257 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
258
259 # Generate Diff
260 diff = topotest.get_textdiff(
261 actual,
262 expected,
263 title1="actual SHOW IPv6 RIPng",
264 title2="expected SHOW IPv6 RIPng",
265 )
266
267 # Empty string if it matches, otherwise diff contains unified diff
268 if diff:
269 sys.stderr.write("r%s failed SHOW IPv6 RIPng check:\n%s\n" % (i, diff))
270 failures += 1
271 else:
272 print("r%s ok" % i)
273
274 assert failures == 0, "SHOW IPv6 RIPng failed for router r%s:\n%s" % (
275 i,
276 diff,
277 )
278
279 # Make sure that all daemons are running
280 for i in range(1, 4):
281 fatal_error = net["r%s" % i].checkRouterRunning()
282 assert fatal_error == "", fatal_error
283
284
285 def test_zebra_ipv6_routingTable():
286 global fatal_error
287 net = get_topogen().net
288
289 # Skip if previous fatal error condition is raised
290 if fatal_error != "":
291 pytest.skip(fatal_error)
292
293 thisDir = os.path.dirname(os.path.realpath(__file__))
294
295 # Verify OSPFv3 Routing Table
296 print("\n\n** Verifying Zebra IPv6 Routing Table")
297 print("******************************************\n")
298 failures = 0
299 for i in range(1, 4):
300 refTableFile = "%s/r%s/show_ipv6_route.ref" % (thisDir, i)
301 if os.path.isfile(refTableFile):
302 # Read expected result from file
303 expected = open(refTableFile).read().rstrip()
304 # Fix newlines (make them all the same)
305 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
306
307 # Actual output from router
308 actual = (
309 net["r%s" % i]
310 .cmd('vtysh -c "show ipv6 route" 2> /dev/null | grep "^R"')
311 .rstrip()
312 )
313 # Mask out Link-Local mac address portion. They are random...
314 actual = re.sub(r" fe80::[0-9a-f:]+", " fe80::XXXX:XXXX:XXXX:XXXX", actual)
315 # Drop timers on end of line
316 actual = re.sub(r", [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", "", actual)
317 # Fix newlines (make them all the same)
318 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
319
320 # Generate Diff
321 diff = topotest.get_textdiff(
322 actual,
323 expected,
324 title1="actual Zebra IPv6 routing table",
325 title2="expected Zebra IPv6 routing table",
326 )
327
328 # Empty string if it matches, otherwise diff contains unified diff
329 if diff:
330 sys.stderr.write(
331 "r%s failed Zebra IPv6 Routing Table Check:\n%s\n" % (i, diff)
332 )
333 failures += 1
334 else:
335 print("r%s ok" % i)
336
337 assert (
338 failures == 0
339 ), "Zebra IPv6 Routing Table verification failed for router r%s:\n%s" % (
340 i,
341 diff,
342 )
343
344 # Make sure that all daemons are running
345 for i in range(1, 4):
346 fatal_error = net["r%s" % i].checkRouterRunning()
347 assert fatal_error == "", fatal_error
348
349
350 def test_shutdown_check_stderr():
351 global fatal_error
352 net = get_topogen().net
353
354 # Skip if previous fatal error condition is raised
355 if fatal_error != "":
356 pytest.skip(fatal_error)
357
358 if os.environ.get("TOPOTESTS_CHECK_STDERR") is None:
359 print(
360 "SKIPPED final check on StdErr output: Disabled (TOPOTESTS_CHECK_STDERR undefined)\n"
361 )
362 pytest.skip("Skipping test for Stderr output")
363
364 thisDir = os.path.dirname(os.path.realpath(__file__))
365
366 print("\n\n** Verifying unexpected STDERR output from daemons")
367 print("******************************************\n")
368
369 net["r1"].stopRouter()
370
371 log = net["r1"].getStdErr("ripngd")
372 if log:
373 print("\nRIPngd StdErr Log:\n" + log)
374 log = net["r1"].getStdErr("zebra")
375 if log:
376 print("\nZebra StdErr Log:\n" + log)
377
378
379 def test_shutdown_check_memleak():
380 global fatal_error
381 net = get_topogen().net
382
383 # Skip if previous fatal error condition is raised
384 if fatal_error != "":
385 pytest.skip(fatal_error)
386
387 if os.environ.get("TOPOTESTS_CHECK_MEMLEAK") is None:
388 print(
389 "SKIPPED final check on Memory leaks: Disabled (TOPOTESTS_CHECK_MEMLEAK undefined)\n"
390 )
391 pytest.skip("Skipping test for memory leaks")
392
393 thisDir = os.path.dirname(os.path.realpath(__file__))
394
395 net["r1"].stopRouter()
396 net["r1"].report_memory_leaks(
397 os.environ.get("TOPOTESTS_CHECK_MEMLEAK"), os.path.basename(__file__)
398 )
399
400
401 if __name__ == "__main__":
402
403 # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli
404 # retval = pytest.main(["-s", "--tb=no"])
405 retval = pytest.main(["-s"])
406 sys.exit(retval)