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