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