]> git.proxmox.com Git - mirror_frr.git/blame - tests/topotests/all_protocol_startup/test_all_protocol_startup.py
*: auto-convert to SPDX License IDs
[mirror_frr.git] / tests / topotests / all_protocol_startup / test_all_protocol_startup.py
CommitLineData
4501fbca 1#!/usr/bin/env python
acddc0ed 2# SPDX-License-Identifier: ISC
4501fbca
MW
3
4#
5# test_all_protocol_startup.py
6# Part of NetDEF Topology Tests
7#
8# Copyright (c) 2017 by
9# Network Device Education Foundation, Inc. ("NetDEF")
10#
4501fbca
MW
11
12"""
13test_all_protocol_startup.py: Test of all protocols at same time
14
15"""
16
17import os
18import re
19import sys
4501fbca 20import pytest
6a57e103 21import glob
4501fbca
MW
22from time import sleep
23
2c647bcd
DS
24pytestmark = [
25 pytest.mark.babeld,
26 pytest.mark.bgpd,
27 pytest.mark.isisd,
28 pytest.mark.nhrpd,
29 pytest.mark.ospfd,
30 pytest.mark.pbrd,
31 pytest.mark.ripd,
32]
6907ac7e 33
4501fbca
MW
34sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
35from lib import topotest
e82b531d 36from lib.topogen import Topogen, get_topogen
a5e5c9a3
DS
37from lib.common_config import (
38 required_linux_kernel_version,
39)
4501fbca
MW
40
41fatal_error = ""
42
43
44#####################################################
45##
46## Network Topology Definition
47##
48#####################################################
49
701a0192 50
e82b531d
CH
51def build_topo(tgen):
52 router = tgen.add_router("r1")
53 for i in range(0, 10):
54 tgen.add_switch("sw%d" % i).add_link(router)
4501fbca
MW
55
56
57#####################################################
58##
59## Tests starting
60##
61#####################################################
62
13f93db3 63
4501fbca 64def setup_module(module):
4501fbca
MW
65 global fatal_error
66
67 print("\n\n** %s: Setup Topology" % module.__name__)
68 print("******************************************\n")
69
4501fbca 70 thisDir = os.path.dirname(os.path.realpath(__file__))
e82b531d
CH
71 tgen = Topogen(build_topo, module.__name__)
72 tgen.start_topology()
4501fbca 73
e82b531d 74 net = tgen.net
4501fbca 75
701a0192 76 if net["r1"].get_routertype() != "frr":
4501fbca 77 fatal_error = "Test is only implemented for FRR"
701a0192 78 sys.stderr.write("\n\nTest is only implemented for FRR - Skipping\n\n")
4501fbca 79 pytest.skip(fatal_error)
701a0192 80
4501fbca
MW
81 # Starting Routers
82 #
83 # Main router
84 for i in range(1, 2):
701a0192 85 net["r%s" % i].loadConf("zebra", "%s/r%s/zebra.conf" % (thisDir, i))
86 net["r%s" % i].loadConf("ripd", "%s/r%s/ripd.conf" % (thisDir, i))
87 net["r%s" % i].loadConf("ripngd", "%s/r%s/ripngd.conf" % (thisDir, i))
88 net["r%s" % i].loadConf("ospfd", "%s/r%s/ospfd.conf" % (thisDir, i))
89 if net["r1"].checkRouterVersion("<", "4.0"):
90 net["r%s" % i].loadConf(
91 "ospf6d", "%s/r%s/ospf6d.conf-pre-v4" % (thisDir, i)
92 )
11761ab0 93 else:
701a0192 94 net["r%s" % i].loadConf("ospf6d", "%s/r%s/ospf6d.conf" % (thisDir, i))
95 net["r%s" % i].loadConf("isisd", "%s/r%s/isisd.conf" % (thisDir, i))
96 net["r%s" % i].loadConf("bgpd", "%s/r%s/bgpd.conf" % (thisDir, i))
97 if net["r%s" % i].daemon_available("ldpd"):
4501fbca 98 # Only test LDPd if it's installed and Kernel >= 4.5
701a0192 99 net["r%s" % i].loadConf("ldpd", "%s/r%s/ldpd.conf" % (thisDir, i))
100 net["r%s" % i].loadConf("sharpd")
101 net["r%s" % i].loadConf("nhrpd", "%s/r%s/nhrpd.conf" % (thisDir, i))
102 net["r%s" % i].loadConf("babeld", "%s/r%s/babeld.conf" % (thisDir, i))
103 net["r%s" % i].loadConf("pbrd", "%s/r%s/pbrd.conf" % (thisDir, i))
e82b531d 104 tgen.gears["r%s" % i].start()
4501fbca 105
622c4996 106 # For debugging after starting FRR daemons, uncomment the next line
c0fa628e 107 # tgen.mininet_cli()
4501fbca
MW
108
109
110def teardown_module(module):
4501fbca
MW
111 print("\n\n** %s: Shutdown Topology" % module.__name__)
112 print("******************************************\n")
e82b531d
CH
113 tgen = get_topogen()
114 tgen.stop_topology()
4501fbca
MW
115
116
117def test_router_running():
118 global fatal_error
c0fa628e
MS
119 tgen = get_topogen()
120 net = tgen.net
4501fbca
MW
121
122 # Skip if previous fatal error condition is raised
701a0192 123 if fatal_error != "":
4501fbca
MW
124 pytest.skip(fatal_error)
125
622c4996 126 print("\n\n** Check if FRR is running on each Router node")
4501fbca
MW
127 print("******************************************\n")
128 sleep(5)
129
130 # Starting Routers
131 for i in range(1, 2):
701a0192 132 fatal_error = net["r%s" % i].checkRouterRunning()
4501fbca
MW
133 assert fatal_error == "", fatal_error
134
622c4996 135 # For debugging after starting FRR daemons, uncomment the next line
c0fa628e 136 # tgen.mininet_cli()
4501fbca
MW
137
138
139def test_error_messages_vtysh():
140 global fatal_error
e82b531d 141 net = get_topogen().net
4501fbca
MW
142
143 # Skip if previous fatal error condition is raised
701a0192 144 if fatal_error != "":
4501fbca
MW
145 pytest.skip(fatal_error)
146
147 print("\n\n** Check for error messages on VTYSH")
148 print("******************************************\n")
149
150 failures = 0
151 for i in range(1, 2):
152 #
153 # First checking Standard Output
154 #
155
156 # VTYSH output from router
701a0192 157 vtystdout = net["r%s" % i].cmd('vtysh -c "show version" 2> /dev/null').rstrip()
4501fbca
MW
158
159 # Fix newlines (make them all the same)
701a0192 160 vtystdout = ("\n".join(vtystdout.splitlines()) + "\n").rstrip()
4501fbca
MW
161 # Drop everything starting with "FRRouting X.xx" message
162 vtystdout = re.sub(r"FRRouting [0-9]+.*", "", vtystdout, flags=re.DOTALL)
163
701a0192 164 if vtystdout == "":
4501fbca
MW
165 print("r%s StdOut ok" % i)
166
701a0192 167 assert vtystdout == "", "Vtysh StdOut Output check failed for router r%s" % i
798fb593 168
4501fbca
MW
169 #
170 # Second checking Standard Error
171 #
172
173 # VTYSH StdErr output from router
701a0192 174 vtystderr = net["r%s" % i].cmd('vtysh -c "show version" > /dev/null').rstrip()
4501fbca
MW
175
176 # Fix newlines (make them all the same)
701a0192 177 vtystderr = ("\n".join(vtystderr.splitlines()) + "\n").rstrip()
4501fbca 178 # # Drop everything starting with "FRRouting X.xx" message
701a0192 179 # vtystderr = re.sub(r"FRRouting [0-9]+.*", "", vtystderr, flags=re.DOTALL)
4501fbca 180
701a0192 181 if vtystderr == "":
4501fbca
MW
182 print("r%s StdErr ok" % i)
183
701a0192 184 assert vtystderr == "", "Vtysh StdErr Output check failed for router r%s" % i
4501fbca 185
7e7fc73b
MW
186 # Make sure that all daemons are running
187 for i in range(1, 2):
701a0192 188 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
189 assert fatal_error == "", fatal_error
190
4501fbca
MW
191
192def test_error_messages_daemons():
193 global fatal_error
e82b531d 194 net = get_topogen().net
4501fbca
MW
195
196 # Skip if previous fatal error condition is raised
701a0192 197 if fatal_error != "":
4501fbca
MW
198 pytest.skip(fatal_error)
199
200 print("\n\n** Check for error messages in daemons")
201 print("******************************************\n")
202
203 error_logs = ""
204
205 for i in range(1, 2):
701a0192 206 log = net["r%s" % i].getStdErr("ripd")
4501fbca
MW
207 if log:
208 error_logs += "r%s RIPd StdErr Output:\n" % i
209 error_logs += log
701a0192 210 log = net["r%s" % i].getStdErr("ripngd")
4501fbca
MW
211 if log:
212 error_logs += "r%s RIPngd StdErr Output:\n" % i
213 error_logs += log
701a0192 214 log = net["r%s" % i].getStdErr("ospfd")
4501fbca
MW
215 if log:
216 error_logs += "r%s OSPFd StdErr Output:\n" % i
217 error_logs += log
701a0192 218 log = net["r%s" % i].getStdErr("ospf6d")
4501fbca
MW
219 if log:
220 error_logs += "r%s OSPF6d StdErr Output:\n" % i
221 error_logs += log
701a0192 222 log = net["r%s" % i].getStdErr("isisd")
4501fbca
MW
223 # ISIS shows debugging enabled status on StdErr
224 # Remove these messages
225 log = re.sub(r"^IS-IS .* debugging is on.*", "", log).rstrip()
226 if log:
227 error_logs += "r%s ISISd StdErr Output:\n" % i
228 error_logs += log
701a0192 229 log = net["r%s" % i].getStdErr("bgpd")
4501fbca
MW
230 if log:
231 error_logs += "r%s BGPd StdErr Output:\n" % i
232 error_logs += log
701a0192 233 if net["r%s" % i].daemon_available("ldpd"):
234 log = net["r%s" % i].getStdErr("ldpd")
4501fbca
MW
235 if log:
236 error_logs += "r%s LDPd StdErr Output:\n" % i
237 error_logs += log
af39fbe7 238
701a0192 239 log = net["r1"].getStdErr("nhrpd")
960c3f25
MW
240 # NHRPD shows YANG model not embedded messages
241 # Ignore these
242 log = re.sub(r".*YANG model.*not embedded.*", "", log).rstrip()
af39fbe7
MS
243 if log:
244 error_logs += "r%s NHRPd StdErr Output:\n" % i
245 error_logs += log
246
701a0192 247 log = net["r1"].getStdErr("babeld")
af39fbe7
MS
248 if log:
249 error_logs += "r%s BABELd StdErr Output:\n" % i
250 error_logs += log
251
701a0192 252 log = net["r1"].getStdErr("pbrd")
af39fbe7
MS
253 if log:
254 error_logs += "r%s PBRd StdErr Output:\n" % i
255 error_logs += log
256
701a0192 257 log = net["r%s" % i].getStdErr("zebra")
4501fbca 258 if log:
960c3f25 259 error_logs += "r%s Zebra StdErr Output:\n" % i
4501fbca
MW
260 error_logs += log
261
262 if error_logs:
701a0192 263 sys.stderr.write(
264 "Failed check for StdErr Output on daemons:\n%s\n" % error_logs
265 )
4501fbca 266
08fa1af7 267 # Ignoring the issue if told to ignore (ie not yet fixed)
701a0192 268 if error_logs != "":
269 if os.environ.get("bamboo_TOPOTESTS_ISSUE_349") == "IGNORE":
270 sys.stderr.write(
271 "Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/349\n"
272 )
273 pytest.skip(
274 "Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/349"
275 )
08fa1af7 276
4501fbca
MW
277 assert error_logs == "", "Daemons report errors to StdErr"
278
4501fbca
MW
279
280def test_converge_protocols():
281 global fatal_error
e82b531d 282 net = get_topogen().net
4501fbca
MW
283
284 # Skip if previous fatal error condition is raised
701a0192 285 if fatal_error != "":
4501fbca
MW
286 pytest.skip(fatal_error)
287
288 thisDir = os.path.dirname(os.path.realpath(__file__))
289
290 print("\n\n** Waiting for protocols convergence")
291 print("******************************************\n")
292
293 # Not really implemented yet - just sleep 60 secs for now
8966cca2 294 sleep(5)
4501fbca 295
7e7fc73b 296 # Make sure that all daemons are running
556f76e1 297 failures = 0
7e7fc73b 298 for i in range(1, 2):
701a0192 299 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
300 assert fatal_error == "", fatal_error
301
701a0192 302 print("Show that v4 routes are right\n")
303 v4_routesFile = "%s/r%s/ipv4_routes.ref" % (thisDir, i)
0b25370e
DS
304 expected = (
305 net["r%s" % i].cmd("sort {} 2> /dev/null".format(v4_routesFile)).rstrip()
306 )
701a0192 307 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
308
309 actual = (
310 net["r%s" % i]
311 .cmd(
c0fa628e 312 "vtysh -c \"show ip route\" | sed -e '/^Codes: /,/^\\s*$/d' | sort 2> /dev/null"
701a0192 313 )
314 .rstrip()
315 )
556f76e1
DS
316 # Drop time in last update
317 actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual)
701a0192 318 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
319 diff = topotest.get_textdiff(
320 actual,
321 expected,
322 title1="Actual IP Routing Table",
323 title2="Expected IP RoutingTable",
324 )
556f76e1 325 if diff:
701a0192 326 sys.stderr.write("r%s failed IP Routing table check:\n%s\n" % (i, diff))
556f76e1
DS
327 failures += 1
328 else:
701a0192 329 print("r%s ok" % i)
556f76e1
DS
330
331 assert failures == 0, "IP Routing table failed for r%s\n%s" % (i, diff)
332
333 failures = 0
334
335 print("Show that v6 routes are right\n")
701a0192 336 v6_routesFile = "%s/r%s/ipv6_routes.ref" % (thisDir, i)
0b25370e
DS
337 expected = (
338 net["r%s" % i].cmd("sort {} 2> /dev/null".format(v6_routesFile)).rstrip()
339 )
701a0192 340 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
341
342 actual = (
343 net["r%s" % i]
344 .cmd(
c0fa628e 345 "vtysh -c \"show ipv6 route\" | sed -e '/^Codes: /,/^\\s*$/d' | sort 2> /dev/null"
701a0192 346 )
347 .rstrip()
348 )
556f76e1
DS
349 # Drop time in last update
350 actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual)
701a0192 351 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
352 diff = topotest.get_textdiff(
353 actual,
354 expected,
355 title1="Actual IPv6 Routing Table",
356 title2="Expected IPv6 RoutingTable",
357 )
556f76e1 358 if diff:
701a0192 359 sys.stderr.write("r%s failed IPv6 Routing table check:\n%s\n" % (i, diff))
556f76e1
DS
360 failures += 1
361 else:
701a0192 362 print("r%s ok" % i)
556f76e1
DS
363
364 assert failures == 0, "IPv6 Routing table failed for r%s\n%s" % (i, diff)
365
701a0192 366
887a232c 367def route_get_nhg_id(route_str):
e82b531d 368 net = get_topogen().net
887a232c
SW
369 output = net["r1"].cmd('vtysh -c "show ip route %s nexthop-group"' % route_str)
370 match = re.search(r"Nexthop Group ID: (\d+)", output)
701a0192 371 assert match is not None, (
372 "Nexthop Group ID not found for sharpd route %s" % route_str
373 )
887a232c
SW
374
375 nhg_id = int(match.group(1))
376 return nhg_id
377
701a0192 378
8f4d7212 379def verify_nexthop_group(nhg_id, recursive=False, ecmp=0):
e82b531d 380 net = get_topogen().net
9482d96e
DS
381 count = 0
382 valid = None
383 ecmpcount = None
384 depends = None
385 resolved_id = None
386 installed = None
387 found = False
388
389 while not found and count < 10:
390 count += 1
391 # Verify NHG is valid/installed
392 output = net["r1"].cmd('vtysh -c "show nexthop-group rib %d"' % nhg_id)
393 valid = re.search(r"Valid", output)
394 if valid is None:
395 found = False
396 sleep(1)
397 continue
398
399 if ecmp or recursive:
400 ecmpcount = re.search(r"Depends:.*\n", output)
401 if ecmpcount is None:
402 found = False
403 sleep(1)
404 continue
405
406 # list of IDs in group
407 depends = re.findall(r"\((\d+)\)", ecmpcount.group(0))
408
409 if ecmp:
410 if len(depends) != ecmp:
411 found = False
412 sleep(1)
413 continue
414 else:
415 # If recursive, we need to look at its resolved group
416 if len(depends) != 1:
417 found = False
418 sleep(1)
419 continue
420
421 resolved_id = int(depends[0])
422 verify_nexthop_group(resolved_id, False)
423 else:
424 installed = re.search(r"Installed", output)
425 if installed is None:
426 found = False
427 sleep(1)
428 continue
429 found = True
430
431 assert valid is not None, "Nexthop Group ID=%d not marked Valid" % nhg_id
8f4d7212 432 if ecmp or recursive:
9482d96e 433 assert ecmpcount is not None, "Nexthop Group ID=%d has no depends" % nhg_id
8f4d7212 434 if ecmp:
701a0192 435 assert len(depends) == ecmp, (
436 "Nexthop Group ID=%d doesn't match ecmp size" % nhg_id
437 )
8f4d7212 438 else:
701a0192 439 assert len(depends) == 1, (
440 "Nexthop Group ID=%d should only have one recursive depend" % nhg_id
441 )
887a232c 442 else:
9482d96e
DS
443 assert installed is not None, (
444 "Nexthop Group ID=%d not marked Installed" % nhg_id
445 )
887a232c 446
701a0192 447
8f4d7212 448def verify_route_nexthop_group(route_str, recursive=False, ecmp=0):
887a232c
SW
449 # Verify route and that zebra created NHGs for and they are valid/installed
450 nhg_id = route_get_nhg_id(route_str)
8f4d7212 451 verify_nexthop_group(nhg_id, recursive, ecmp)
887a232c 452
701a0192 453
8058df22
SW
454def test_nexthop_groups():
455 global fatal_error
e82b531d 456 net = get_topogen().net
8058df22
SW
457
458 # Skip if previous fatal error condition is raised
701a0192 459 if fatal_error != "":
8058df22
SW
460 pytest.skip(fatal_error)
461
462 print("\n\n** Verifying Nexthop Groups")
463 print("******************************************\n")
464
887a232c
SW
465 ### Nexthop Group Tests
466
467 ## Basic test
468
8058df22 469 # Create a lib nexthop-group
701a0192 470 net["r1"].cmd(
471 'vtysh -c "c t" -c "nexthop-group basic" -c "nexthop 1.1.1.1" -c "nexthop 1.1.1.2"'
472 )
8058df22
SW
473
474 # Create with sharpd using nexthop-group
887a232c 475 net["r1"].cmd('vtysh -c "sharp install routes 2.2.2.1 nexthop-group basic 1"')
887a232c 476 verify_route_nexthop_group("2.2.2.1/32")
8058df22 477
887a232c 478 ## Connected
8058df22 479
701a0192 480 net["r1"].cmd(
481 'vtysh -c "c t" -c "nexthop-group connected" -c "nexthop r1-eth1" -c "nexthop r1-eth2"'
482 )
8058df22 483
887a232c 484 net["r1"].cmd('vtysh -c "sharp install routes 2.2.2.2 nexthop-group connected 1"')
887a232c
SW
485 verify_route_nexthop_group("2.2.2.2/32")
486
487 ## Recursive
488
701a0192 489 net["r1"].cmd(
490 'vtysh -c "c t" -c "nexthop-group basic-recursive" -c "nexthop 2.2.2.1"'
491 )
887a232c 492
701a0192 493 net["r1"].cmd(
494 'vtysh -c "sharp install routes 3.3.3.1 nexthop-group basic-recursive 1"'
495 )
887a232c
SW
496
497 verify_route_nexthop_group("3.3.3.1/32", True)
498
499 ## Duplicate
500
701a0192 501 net["r1"].cmd(
502 'vtysh -c "c t" -c "nexthop-group duplicate" -c "nexthop 2.2.2.1" -c "nexthop 1.1.1.1"'
503 )
887a232c
SW
504
505 net["r1"].cmd('vtysh -c "sharp install routes 3.3.3.2 nexthop-group duplicate 1"')
506
507 verify_route_nexthop_group("3.3.3.2/32")
508
509 ## Two 4-Way ECMP
510
701a0192 511 net["r1"].cmd(
512 'vtysh -c "c t" -c "nexthop-group fourA" -c "nexthop 1.1.1.1" -c "nexthop 1.1.1.2" \
513 -c "nexthop 1.1.1.3" -c "nexthop 1.1.1.4"'
514 )
887a232c
SW
515
516 net["r1"].cmd('vtysh -c "sharp install routes 4.4.4.1 nexthop-group fourA 1"')
517
518 verify_route_nexthop_group("4.4.4.1/32")
519
701a0192 520 net["r1"].cmd(
521 'vtysh -c "c t" -c "nexthop-group fourB" -c "nexthop 1.1.1.5" -c "nexthop 1.1.1.6" \
522 -c "nexthop 1.1.1.7" -c "nexthop 1.1.1.8"'
523 )
887a232c
SW
524
525 net["r1"].cmd('vtysh -c "sharp install routes 4.4.4.2 nexthop-group fourB 1"')
526
527 verify_route_nexthop_group("4.4.4.2/32")
528
529 ## Recursive to 8-Way ECMP
530
701a0192 531 net["r1"].cmd(
532 'vtysh -c "c t" -c "nexthop-group eight-recursive" -c "nexthop 4.4.4.1" -c "nexthop 4.4.4.2"'
533 )
887a232c 534
701a0192 535 net["r1"].cmd(
536 'vtysh -c "sharp install routes 5.5.5.1 nexthop-group eight-recursive 1"'
537 )
887a232c
SW
538
539 verify_route_nexthop_group("5.5.5.1/32")
540
13f93db3
SW
541 ## 4-way ECMP Routes Pointing to Each Other
542
543 # This is to check for a bug with NH resolution where
544 # routes would infintely resolve to each other blowing
545 # up the resolved-> nexthop pointer.
546
547 net["r1"].cmd(
548 'vtysh -c "c t" -c "nexthop-group infinite-recursive" -c "nexthop 6.6.6.1" -c "nexthop 6.6.6.2" \
549 -c "nexthop 6.6.6.3" -c "nexthop 6.6.6.4"'
550 )
551
552 # static route nexthops can recurse to
553
554 net["r1"].cmd('vtysh -c "c t" -c "ip route 6.6.6.0/24 1.1.1.1"')
555
556 # Make routes that point to themselves in ecmp
557
558 net["r1"].cmd(
559 'vtysh -c "sharp install routes 6.6.6.4 nexthop-group infinite-recursive 1"'
560 )
0567f3a9 561 sleep(5)
13f93db3
SW
562
563 net["r1"].cmd(
564 'vtysh -c "sharp install routes 6.6.6.3 nexthop-group infinite-recursive 1"'
565 )
0567f3a9 566 sleep(5)
13f93db3
SW
567
568 net["r1"].cmd(
569 'vtysh -c "sharp install routes 6.6.6.2 nexthop-group infinite-recursive 1"'
570 )
0567f3a9 571 sleep(5)
13f93db3
SW
572
573 net["r1"].cmd(
574 'vtysh -c "sharp install routes 6.6.6.1 nexthop-group infinite-recursive 1"'
575 )
576
577 # Get routes and test if has too many (duplicate) nexthops
9482d96e
DS
578 count = 0
579 dups = []
13f93db3 580 nhg_id = route_get_nhg_id("6.6.6.1/32")
9482d96e
DS
581 while (len(dups) != 3) and count < 10:
582 output = net["r1"].cmd('vtysh -c "show nexthop-group rib %d"' % nhg_id)
13f93db3 583
9482d96e
DS
584 dups = re.findall(r"(via 1\.1\.1\.1)", output)
585 if len(dups) != 3:
586 count += 1
587 sleep(1)
13f93db3
SW
588
589 # Should find 3, itself is inactive
590 assert len(dups) == 3, (
591 "Route 6.6.6.1/32 with Nexthop Group ID=%d has wrong number of resolved nexthops"
592 % nhg_id
593 )
594
887a232c
SW
595 ## Remove all NHG routes
596
597 net["r1"].cmd('vtysh -c "sharp remove routes 2.2.2.1 1"')
598 net["r1"].cmd('vtysh -c "sharp remove routes 2.2.2.2 1"')
599 net["r1"].cmd('vtysh -c "sharp remove routes 3.3.3.1 1"')
600 net["r1"].cmd('vtysh -c "sharp remove routes 3.3.3.2 1"')
601 net["r1"].cmd('vtysh -c "sharp remove routes 4.4.4.1 1"')
602 net["r1"].cmd('vtysh -c "sharp remove routes 4.4.4.2 1"')
603 net["r1"].cmd('vtysh -c "sharp remove routes 5.5.5.1 1"')
13f93db3
SW
604 net["r1"].cmd('vtysh -c "sharp remove routes 6.6.6.1 4"')
605 net["r1"].cmd('vtysh -c "c t" -c "no ip route 6.6.6.0/24 1.1.1.1"')
4501fbca 606
701a0192 607
4501fbca
MW
608def test_rip_status():
609 global fatal_error
e82b531d 610 net = get_topogen().net
4501fbca
MW
611
612 # Skip if previous fatal error condition is raised
701a0192 613 if fatal_error != "":
4501fbca
MW
614 pytest.skip(fatal_error)
615
616 thisDir = os.path.dirname(os.path.realpath(__file__))
617
b2764f90 618 print("\n\n** Verifying RIP status")
4501fbca
MW
619 print("******************************************\n")
620 failures = 0
621 for i in range(1, 2):
701a0192 622 refTableFile = "%s/r%s/rip_status.ref" % (thisDir, i)
4501fbca
MW
623 if os.path.isfile(refTableFile):
624 # Read expected result from file
625 expected = open(refTableFile).read().rstrip()
626 # Fix newlines (make them all the same)
701a0192 627 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
4501fbca
MW
628
629 # Actual output from router
701a0192 630 actual = (
631 net["r%s" % i]
632 .cmd('vtysh -c "show ip rip status" 2> /dev/null')
633 .rstrip()
634 )
635 # Drop time in next due
4501fbca
MW
636 actual = re.sub(r"in [0-9]+ seconds", "in XX seconds", actual)
637 # Drop time in last update
638 actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual)
639 # Fix newlines (make them all the same)
701a0192 640 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
4501fbca
MW
641
642 # Generate Diff
701a0192 643 diff = topotest.get_textdiff(
644 actual,
645 expected,
17070436 646 title1="actual IP RIP status",
701a0192 647 title2="expected IP RIP status",
648 )
4501fbca
MW
649
650 # Empty string if it matches, otherwise diff contains unified diff
651 if diff:
701a0192 652 sys.stderr.write("r%s failed IP RIP status check:\n%s\n" % (i, diff))
4501fbca
MW
653 failures += 1
654 else:
655 print("r%s ok" % i)
656
657 assert failures == 0, "IP RIP status failed for router r%s:\n%s" % (i, diff)
658
7e7fc73b
MW
659 # Make sure that all daemons are running
660 for i in range(1, 2):
701a0192 661 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
662 assert fatal_error == "", fatal_error
663
4501fbca
MW
664
665def test_ripng_status():
666 global fatal_error
e82b531d 667 net = get_topogen().net
4501fbca
MW
668
669 # Skip if previous fatal error condition is raised
701a0192 670 if fatal_error != "":
4501fbca
MW
671 pytest.skip(fatal_error)
672
673 thisDir = os.path.dirname(os.path.realpath(__file__))
674
b2764f90 675 print("\n\n** Verifying RIPng status")
4501fbca
MW
676 print("******************************************\n")
677 failures = 0
678 for i in range(1, 2):
701a0192 679 refTableFile = "%s/r%s/ripng_status.ref" % (thisDir, i)
4501fbca
MW
680 if os.path.isfile(refTableFile):
681 # Read expected result from file
682 expected = open(refTableFile).read().rstrip()
683 # Fix newlines (make them all the same)
701a0192 684 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
4501fbca
MW
685
686 # Actual output from router
701a0192 687 actual = (
688 net["r%s" % i]
689 .cmd('vtysh -c "show ipv6 ripng status" 2> /dev/null')
690 .rstrip()
691 )
4501fbca
MW
692 # Mask out Link-Local mac address portion. They are random...
693 actual = re.sub(r" fe80::[0-9a-f:]+", " fe80::XXXX:XXXX:XXXX:XXXX", actual)
701a0192 694 # Drop time in next due
4501fbca
MW
695 actual = re.sub(r"in [0-9]+ seconds", "in XX seconds", actual)
696 # Drop time in last update
697 actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual)
698 # Fix newlines (make them all the same)
701a0192 699 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
4501fbca
MW
700
701 # Generate Diff
701a0192 702 diff = topotest.get_textdiff(
703 actual,
704 expected,
17070436 705 title1="actual IPv6 RIPng status",
701a0192 706 title2="expected IPv6 RIPng status",
707 )
4501fbca
MW
708
709 # Empty string if it matches, otherwise diff contains unified diff
710 if diff:
701a0192 711 sys.stderr.write(
712 "r%s failed IPv6 RIPng status check:\n%s\n" % (i, diff)
713 )
4501fbca
MW
714 failures += 1
715 else:
716 print("r%s ok" % i)
717
701a0192 718 assert failures == 0, "IPv6 RIPng status failed for router r%s:\n%s" % (
719 i,
720 diff,
721 )
4501fbca 722
7e7fc73b
MW
723 # Make sure that all daemons are running
724 for i in range(1, 2):
701a0192 725 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
726 assert fatal_error == "", fatal_error
727
4501fbca
MW
728
729def test_ospfv2_interfaces():
730 global fatal_error
e82b531d 731 net = get_topogen().net
4501fbca
MW
732
733 # Skip if previous fatal error condition is raised
701a0192 734 if fatal_error != "":
4501fbca
MW
735 pytest.skip(fatal_error)
736
737 thisDir = os.path.dirname(os.path.realpath(__file__))
738
b2764f90 739 print("\n\n** Verifying OSPFv2 interfaces")
4501fbca
MW
740 print("******************************************\n")
741 failures = 0
742 for i in range(1, 2):
701a0192 743 refTableFile = "%s/r%s/show_ip_ospf_interface.ref" % (thisDir, i)
4501fbca
MW
744 if os.path.isfile(refTableFile):
745 # Read expected result from file
746 expected = open(refTableFile).read().rstrip()
747 # Fix newlines (make them all the same)
701a0192 748 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
4501fbca
MW
749
750 # Actual output from router
701a0192 751 actual = (
752 net["r%s" % i]
753 .cmd('vtysh -c "show ip ospf interface" 2> /dev/null')
754 .rstrip()
755 )
4501fbca
MW
756 # Mask out Bandwidth portion. They may change..
757 actual = re.sub(r"BW [0-9]+ Mbit", "BW XX Mbit", actual)
8db751b8 758 actual = re.sub(r"ifindex [0-9]+", "ifindex X", actual)
c9d72a0b 759
701a0192 760 # Drop time in next due
4501fbca 761 actual = re.sub(r"Hello due in [0-9\.]+s", "Hello due in XX.XXXs", actual)
701a0192 762 actual = re.sub(
763 r"Hello due in [0-9\.]+ usecs", "Hello due in XX.XXXs", actual
764 )
985e6d50 765 # Fix 'MTU mismatch detection: enabled' vs 'MTU mismatch detection:enabled' - accept both
701a0192 766 actual = re.sub(
767 r"MTU mismatch detection:([a-z]+.*)",
768 r"MTU mismatch detection: \1",
769 actual,
770 )
4501fbca 771 # Fix newlines (make them all the same)
701a0192 772 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
4501fbca
MW
773
774 # Generate Diff
701a0192 775 diff = topotest.get_textdiff(
776 actual,
777 expected,
17070436 778 title1="actual SHOW IP OSPF INTERFACE",
701a0192 779 title2="expected SHOW IP OSPF INTERFACE",
780 )
4501fbca
MW
781
782 # Empty string if it matches, otherwise diff contains unified diff
783 if diff:
701a0192 784 sys.stderr.write(
785 "r%s failed SHOW IP OSPF INTERFACE check:\n%s\n" % (i, diff)
786 )
4501fbca
MW
787 failures += 1
788 else:
789 print("r%s ok" % i)
790
08fa1af7 791 # Ignoring the issue if told to ignore (ie not yet fixed)
701a0192 792 if failures != 0:
793 if os.environ.get("bamboo_TOPOTESTS_ISSUE_348") == "IGNORE":
794 sys.stderr.write(
795 "Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/348\n"
796 )
797 pytest.skip(
798 "Known issue - IGNORING. See https://github.com/FRRouting/frr/issues/348"
799 )
800
801 assert (
802 failures == 0
803 ), "SHOW IP OSPF INTERFACE failed for router r%s:\n%s" % (i, diff)
4501fbca 804
7e7fc73b
MW
805 # Make sure that all daemons are running
806 for i in range(1, 2):
701a0192 807 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
808 assert fatal_error == "", fatal_error
809
4501fbca
MW
810
811def test_isis_interfaces():
812 global fatal_error
e82b531d 813 net = get_topogen().net
4501fbca
MW
814
815 # Skip if previous fatal error condition is raised
701a0192 816 if fatal_error != "":
4501fbca
MW
817 pytest.skip(fatal_error)
818
819 thisDir = os.path.dirname(os.path.realpath(__file__))
820
b2764f90 821 print("\n\n** Verifying ISIS interfaces")
4501fbca
MW
822 print("******************************************\n")
823 failures = 0
824 for i in range(1, 2):
701a0192 825 refTableFile = "%s/r%s/show_isis_interface_detail.ref" % (thisDir, i)
4501fbca
MW
826 if os.path.isfile(refTableFile):
827 # Read expected result from file
828 expected = open(refTableFile).read().rstrip()
829 # Fix newlines (make them all the same)
701a0192 830 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
4501fbca
MW
831
832 # Actual output from router
701a0192 833 actual = (
834 net["r%s" % i]
835 .cmd('vtysh -c "show isis interface detail" 2> /dev/null')
836 .rstrip()
837 )
4501fbca
MW
838 # Mask out Link-Local mac address portion. They are random...
839 actual = re.sub(r"fe80::[0-9a-f:]+", "fe80::XXXX:XXXX:XXXX:XXXX", actual)
840 # Mask out SNPA mac address portion. They are random...
841 actual = re.sub(r"SNPA: [0-9a-f\.]+", "SNPA: XXXX.XXXX.XXXX", actual)
6ae351e8 842 # Mask out Circuit ID number
701a0192 843 actual = re.sub(r"Circuit Id: 0x[0-9a-f]+", "Circuit Id: 0xXX", actual)
4501fbca 844 # Fix newlines (make them all the same)
701a0192 845 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
4501fbca
MW
846
847 # Generate Diff
701a0192 848 diff = topotest.get_textdiff(
849 actual,
850 expected,
17070436 851 title1="actual SHOW ISIS INTERFACE DETAIL",
701a0192 852 title2="expected SHOW ISIS OSPF6 INTERFACE DETAIL",
853 )
4501fbca
MW
854
855 # Empty string if it matches, otherwise diff contains unified diff
856 if diff:
701a0192 857 sys.stderr.write(
858 "r%s failed SHOW ISIS INTERFACE DETAIL check:\n%s\n" % (i, diff)
859 )
4501fbca
MW
860 failures += 1
861 else:
862 print("r%s ok" % i)
863
701a0192 864 assert (
865 failures == 0
866 ), "SHOW ISIS INTERFACE DETAIL failed for router r%s:\n%s" % (i, diff)
4501fbca 867
7e7fc73b
MW
868 # Make sure that all daemons are running
869 for i in range(1, 2):
701a0192 870 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
871 assert fatal_error == "", fatal_error
872
4501fbca
MW
873
874def test_bgp_summary():
875 global fatal_error
e82b531d 876 net = get_topogen().net
4501fbca
MW
877
878 # Skip if previous fatal error condition is raised
701a0192 879 if fatal_error != "":
4501fbca
MW
880 pytest.skip(fatal_error)
881
882 thisDir = os.path.dirname(os.path.realpath(__file__))
883
b2764f90 884 print("\n\n** Verifying BGP Summary")
4501fbca
MW
885 print("******************************************\n")
886 failures = 0
887 for i in range(1, 2):
701a0192 888 refTableFile = "%s/r%s/show_ip_bgp_summary.ref" % (thisDir, i)
4501fbca
MW
889 if os.path.isfile(refTableFile):
890 # Read expected result from file
8c1d4cd5
LS
891 expected_original = open(refTableFile).read().rstrip()
892
a53c08bc
CH
893 for arguments in [
894 "",
895 "remote-as internal",
896 "remote-as external",
897 "remote-as 100",
898 "remote-as 123",
899 "neighbor 192.168.7.10",
900 "neighbor 192.168.7.10",
901 "neighbor fc00:0:0:8::1000",
902 "neighbor 10.0.0.1",
903 "terse",
904 "remote-as internal terse",
905 "remote-as external terse",
906 "remote-as 100 terse",
907 "remote-as 123 terse",
908 "neighbor 192.168.7.10 terse",
909 "neighbor 192.168.7.10 terse",
910 "neighbor fc00:0:0:8::1000 terse",
911 "neighbor 10.0.0.1 terse",
912 ]:
8c1d4cd5
LS
913 # Actual output from router
914 actual = (
915 net["r%s" % i]
a53c08bc
CH
916 .cmd(
917 'vtysh -c "show ip bgp summary ' + arguments + '" 2> /dev/null'
918 )
8c1d4cd5
LS
919 .rstrip()
920 )
96c81f66 921
8c1d4cd5
LS
922 # Mask out "using XXiXX bytes" portion. They are random...
923 actual = re.sub(r"using [0-9]+ bytes", "using XXXX bytes", actual)
924 # Mask out "using XiXXX KiB" portion. They are random...
925 actual = re.sub(r"using [0-9]+ KiB", "using XXXX KiB", actual)
926
927 # Remove extra summaries which exist with newer versions
928
929 # Remove summary lines (changed recently)
930 actual = re.sub(r"Total number.*", "", actual)
931 actual = re.sub(r"Displayed.*", "", actual)
932 # Remove IPv4 Unicast Summary (Title only)
6cac2fcc 933 actual = re.sub(r"IPv4 Unicast Summary \(VRF default\):", "", actual)
8c1d4cd5 934 # Remove IPv4 Multicast Summary (all of it)
6cac2fcc 935 actual = re.sub(r"IPv4 Multicast Summary \(VRF default\):", "", actual)
8c1d4cd5
LS
936 actual = re.sub(r"No IPv4 Multicast neighbor is configured", "", actual)
937 # Remove IPv4 VPN Summary (all of it)
6cac2fcc 938 actual = re.sub(r"IPv4 VPN Summary \(VRF default\):", "", actual)
8c1d4cd5
LS
939 actual = re.sub(r"No IPv4 VPN neighbor is configured", "", actual)
940 # Remove IPv4 Encap Summary (all of it)
6cac2fcc 941 actual = re.sub(r"IPv4 Encap Summary \(VRF default\):", "", actual)
8c1d4cd5
LS
942 actual = re.sub(r"No IPv4 Encap neighbor is configured", "", actual)
943 # Remove Unknown Summary (all of it)
6cac2fcc 944 actual = re.sub(r"Unknown Summary \(VRF default\):", "", actual)
8c1d4cd5 945 actual = re.sub(r"No Unknown neighbor is configured", "", actual)
87980f13
MW
946 # Make Connect/Active/Idle the same (change them all to Active)
947 actual = re.sub(r" Connect ", " Active ", actual)
948 actual = re.sub(r" Idle ", " Active ", actual)
8c1d4cd5 949
a53c08bc
CH
950 actual = re.sub(
951 r"IPv4 labeled-unicast Summary \(VRF default\):", "", actual
952 )
8c1d4cd5
LS
953 actual = re.sub(
954 r"No IPv4 labeled-unicast neighbor is configured", "", actual
955 )
8b2e59e9 956
8c1d4cd5 957 expected = expected_original
96c81f66
LS
958 # apply argumentss on expected output
959 if "internal" in arguments or "remote-as 100" in arguments:
8c1d4cd5 960 expected = re.sub(r".+\s+200\s+.+", "", expected)
96c81f66 961 elif "external" in arguments:
8c1d4cd5 962 expected = re.sub(r".+\s+100\s+.+Active.+", "", expected)
96c81f66 963 elif "remote-as 123" in arguments:
8c1d4cd5
LS
964 expected = re.sub(
965 r"(192.168.7.(1|2)0|fc00:0:0:8::(1|2)000).+Active.+",
a53c08bc
CH
966 "",
967 expected,
8c1d4cd5 968 )
96c81f66 969 expected = re.sub(r"\nNeighbor.+Desc", "", expected)
ce1944f0 970 expected = expected + "% No matching neighbor\n"
96c81f66 971 elif "192.168.7.10" in arguments:
8c1d4cd5 972 expected = re.sub(
a53c08bc 973 r"(192.168.7.20|fc00:0:0:8::(1|2)000).+Active.+", "", expected
8c1d4cd5 974 )
96c81f66 975 elif "fc00:0:0:8::1000" in arguments:
8c1d4cd5 976 expected = re.sub(
a53c08bc 977 r"(192.168.7.(1|2)0|fc00:0:0:8::2000).+Active.+", "", expected
8c1d4cd5 978 )
96c81f66 979 elif "10.0.0.1" in arguments:
1c49e813 980 expected = "No such neighbor in this view/vrf"
8c1d4cd5 981
96c81f66
LS
982 if "terse" in arguments:
983 expected = re.sub(r"BGP table version .+", "", expected)
984 expected = re.sub(r"RIB entries .+", "", expected)
985 expected = re.sub(r"Peers [0-9]+, using .+", "", expected)
986
8c1d4cd5
LS
987 # Strip empty lines
988 actual = actual.lstrip().rstrip()
989 expected = expected.lstrip().rstrip()
990 actual = re.sub(r"\n+", "\n", actual)
991 expected = re.sub(r"\n+", "\n", expected)
992
993 # reapply initial formatting
96c81f66
LS
994 if "terse" in arguments:
995 actual = re.sub(r" vrf-id 0\n", " vrf-id 0\n\n", actual)
996 expected = re.sub(r" vrf-id 0\n", " vrf-id 0\n\n", expected)
997 else:
998 actual = re.sub(r"KiB of memory\n", "KiB of memory\n\n", actual)
999 expected = re.sub(r"KiB of memory\n", "KiB of memory\n\n", expected)
8c1d4cd5
LS
1000
1001 # realign expected neighbor columns if needed
1002 try:
a53c08bc
CH
1003 idx_actual = (
1004 re.search(r"(Neighbor\s+V\s+)", actual).group(1).find("V")
1005 )
1006 idx_expected = (
1007 re.search(r"(Neighbor\s+V\s+)", expected).group(1).find("V")
1008 )
8c1d4cd5
LS
1009 idx_diff = idx_expected - idx_actual
1010 if idx_diff > 0:
1011 # Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
1012 expected = re.sub(" " * idx_diff + "V ", "V ", expected)
1013 # 192.168.7.10 4 100 0 0 0 0 0 never Active
1014 expected = re.sub(" " * idx_diff + "4 ", "4 ", expected)
1015 except AttributeError:
1016 pass
1017
1018 # Fix newlines (make them all the same)
1019 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
1020 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
1021
1022 # Generate Diff
1023 diff = topotest.get_textdiff(
1024 actual,
1025 expected,
a53c08bc 1026 title1="actual SHOW IP BGP SUMMARY " + arguments.upper(),
96c81f66 1027 title2="expected SHOW IP BGP SUMMARY " + arguments.upper(),
8c1d4cd5 1028 )
4501fbca 1029
8c1d4cd5
LS
1030 # Empty string if it matches, otherwise diff contains unified diff
1031 if diff:
1032 sys.stderr.write(
1033 "r%s failed SHOW IP BGP SUMMARY check:\n%s\n" % (i, diff)
1034 )
1035 failures += 1
1036 else:
1037 print("r%s ok" % i)
4501fbca 1038
a53c08bc
CH
1039 assert (
1040 failures == 0
1041 ), "SHOW IP BGP SUMMARY failed for router r%s:\n%s" % (
8c1d4cd5
LS
1042 i,
1043 diff,
701a0192 1044 )
4501fbca 1045
7e7fc73b
MW
1046 # Make sure that all daemons are running
1047 for i in range(1, 2):
701a0192 1048 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
1049 assert fatal_error == "", fatal_error
1050
4501fbca
MW
1051
1052def test_bgp_ipv6_summary():
1053 global fatal_error
e82b531d 1054 net = get_topogen().net
4501fbca
MW
1055
1056 # Skip if previous fatal error condition is raised
701a0192 1057 if fatal_error != "":
4501fbca
MW
1058 pytest.skip(fatal_error)
1059
1060 thisDir = os.path.dirname(os.path.realpath(__file__))
1061
b2764f90 1062 print("\n\n** Verifying BGP IPv6 Summary")
4501fbca
MW
1063 print("******************************************\n")
1064 failures = 0
1065 for i in range(1, 2):
701a0192 1066 refTableFile = "%s/r%s/show_bgp_ipv6_summary.ref" % (thisDir, i)
4501fbca
MW
1067 if os.path.isfile(refTableFile):
1068 # Read expected result from file
1069 expected = open(refTableFile).read().rstrip()
1070 # Fix newlines (make them all the same)
701a0192 1071 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
4501fbca
MW
1072
1073 # Actual output from router
701a0192 1074 actual = (
1075 net["r%s" % i]
1076 .cmd('vtysh -c "show bgp ipv6 summary" 2> /dev/null')
1077 .rstrip()
1078 )
4501fbca
MW
1079 # Mask out "using XXiXX bytes" portion. They are random...
1080 actual = re.sub(r"using [0-9]+ bytes", "using XXXX bytes", actual)
1081 # Mask out "using XiXXX KiB" portion. They are random...
1082 actual = re.sub(r"using [0-9]+ KiB", "using XXXX KiB", actual)
08fa1af7
MW
1083 #
1084 # Remove extra summaries which exist with newer versions
1085 #
1086 # Remove summary lines (changed recently)
701a0192 1087 actual = re.sub(r"Total number.*", "", actual)
1088 actual = re.sub(r"Displayed.*", "", actual)
08fa1af7 1089 # Remove IPv4 Unicast Summary (Title only)
6cac2fcc 1090 actual = re.sub(r"IPv6 Unicast Summary \(VRF default\):", "", actual)
08fa1af7 1091 # Remove IPv4 Multicast Summary (all of it)
6cac2fcc 1092 actual = re.sub(r"IPv6 Multicast Summary \(VRF default\):", "", actual)
701a0192 1093 actual = re.sub(r"No IPv6 Multicast neighbor is configured", "", actual)
08fa1af7 1094 # Remove IPv4 VPN Summary (all of it)
6cac2fcc 1095 actual = re.sub(r"IPv6 VPN Summary \(VRF default\):", "", actual)
701a0192 1096 actual = re.sub(r"No IPv6 VPN neighbor is configured", "", actual)
08fa1af7 1097 # Remove IPv4 Encap Summary (all of it)
6cac2fcc 1098 actual = re.sub(r"IPv6 Encap Summary \(VRF default\):", "", actual)
701a0192 1099 actual = re.sub(r"No IPv6 Encap neighbor is configured", "", actual)
08fa1af7 1100 # Remove Unknown Summary (all of it)
6cac2fcc 1101 actual = re.sub(r"Unknown Summary \(VRF default\):", "", actual)
701a0192 1102 actual = re.sub(r"No Unknown neighbor is configured", "", actual)
87980f13
MW
1103 # Make Connect/Active/Idle the same (change them all to Active)
1104 actual = re.sub(r" Connect ", " Active ", actual)
1105 actual = re.sub(r" Idle ", " Active ", actual)
8b2e59e9
DS
1106
1107 # Remove Labeled Unicast Summary (all of it)
a53c08bc
CH
1108 actual = re.sub(
1109 r"IPv6 labeled-unicast Summary \(VRF default\):", "", actual
1110 )
701a0192 1111 actual = re.sub(
1112 r"No IPv6 labeled-unicast neighbor is configured", "", actual
1113 )
8b2e59e9 1114
08fa1af7
MW
1115 # Strip empty lines
1116 actual = actual.lstrip()
1117 actual = actual.rstrip()
1118 #
4501fbca 1119 # Fix newlines (make them all the same)
701a0192 1120 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
4501fbca
MW
1121
1122 # Generate Diff
701a0192 1123 diff = topotest.get_textdiff(
1124 actual,
1125 expected,
17070436 1126 title1="actual SHOW BGP IPv6 SUMMARY",
701a0192 1127 title2="expected SHOW BGP IPv6 SUMMARY",
1128 )
4501fbca
MW
1129
1130 # Empty string if it matches, otherwise diff contains unified diff
1131 if diff:
701a0192 1132 sys.stderr.write(
1133 "r%s failed SHOW BGP IPv6 SUMMARY check:\n%s\n" % (i, diff)
1134 )
4501fbca
MW
1135 failures += 1
1136 else:
1137 print("r%s ok" % i)
1138
701a0192 1139 assert failures == 0, "SHOW BGP IPv6 SUMMARY failed for router r%s:\n%s" % (
1140 i,
1141 diff,
1142 )
4501fbca 1143
7e7fc73b
MW
1144 # Make sure that all daemons are running
1145 for i in range(1, 2):
701a0192 1146 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
1147 assert fatal_error == "", fatal_error
1148
9fa6ec14 1149
dda33b6e 1150def test_nht():
c0fa628e 1151 global fatal_error
e82b531d 1152 net = get_topogen().net
c0fa628e
MS
1153
1154 # Skip if previous fatal error condition is raised
1155 if fatal_error != "":
1156 pytest.skip(fatal_error)
1157
dda33b6e
DS
1158 print("\n\n**** Test that nexthop tracking is at least nominally working ****\n")
1159
1160 thisDir = os.path.dirname(os.path.realpath(__file__))
1161
1162 for i in range(1, 2):
1163 nhtFile = "%s/r%s/ip_nht.ref" % (thisDir, i)
1164 expected = open(nhtFile).read().rstrip()
1165 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
1166
9fa6ec14 1167 actual = net["r%s" % i].cmd('vtysh -c "show ip nht" 2> /dev/null').rstrip()
8db751b8 1168 actual = re.sub(r"fd [0-9]+", "fd XX", actual)
dda33b6e
DS
1169 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
1170
9fa6ec14 1171 diff = topotest.get_textdiff(
1172 actual,
1173 expected,
1174 title1="Actual `show ip nht`",
1175 title2="Expected `show ip nht`",
1176 )
dda33b6e
DS
1177
1178 if diff:
1179 assert 0, "r%s failed ip nht check:\n%s\n" % (i, diff)
1180 else:
1181 print("show ip nht is ok\n")
1182
1183 nhtFile = "%s/r%s/ipv6_nht.ref" % (thisDir, i)
1184 expected = open(nhtFile).read().rstrip()
1185 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
1186
9fa6ec14 1187 actual = net["r%s" % i].cmd('vtysh -c "show ipv6 nht" 2> /dev/null').rstrip()
8db751b8 1188 actual = re.sub(r"fd [0-9]+", "fd XX", actual)
dda33b6e
DS
1189 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
1190
9fa6ec14 1191 diff = topotest.get_textdiff(
1192 actual,
1193 expected,
1194 title1="Actual `show ip nht`",
1195 title2="Expected `show ip nht`",
1196 )
dda33b6e
DS
1197
1198 if diff:
1199 assert 0, "r%s failed ipv6 nht check:\n%s\n" % (i, diff)
1200 else:
1201 print("show ipv6 nht is ok\n")
4501fbca 1202
9fa6ec14 1203
4501fbca
MW
1204def test_bgp_ipv4():
1205 global fatal_error
e82b531d 1206 net = get_topogen().net
4501fbca
MW
1207
1208 # Skip if previous fatal error condition is raised
701a0192 1209 if fatal_error != "":
4501fbca
MW
1210 pytest.skip(fatal_error)
1211
1212 thisDir = os.path.dirname(os.path.realpath(__file__))
1213
b2764f90 1214 print("\n\n** Verifying BGP IPv4")
4501fbca 1215 print("******************************************\n")
6a57e103 1216 diffresult = {}
4501fbca 1217 for i in range(1, 2):
11761ab0 1218 success = 0
701a0192 1219 for refTableFile in glob.glob("%s/r%s/show_bgp_ipv4*.ref" % (thisDir, i)):
11761ab0
MS
1220 if os.path.isfile(refTableFile):
1221 # Read expected result from file
1222 expected = open(refTableFile).read().rstrip()
1223 # Fix newlines (make them all the same)
701a0192 1224 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
11761ab0
MS
1225
1226 # Actual output from router
701a0192 1227 actual = (
1228 net["r%s" % i].cmd('vtysh -c "show bgp ipv4" 2> /dev/null').rstrip()
1229 )
11761ab0 1230 # Remove summary line (changed recently)
701a0192 1231 actual = re.sub(r"Total number.*", "", actual)
1232 actual = re.sub(r"Displayed.*", "", actual)
11761ab0
MS
1233 actual = actual.rstrip()
1234 # Fix newlines (make them all the same)
701a0192 1235 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
11761ab0
MS
1236
1237 # Generate Diff
701a0192 1238 diff = topotest.get_textdiff(
1239 actual,
1240 expected,
11761ab0 1241 title1="actual SHOW BGP IPv4",
701a0192 1242 title2="expected SHOW BGP IPv4",
1243 )
11761ab0
MS
1244
1245 # Empty string if it matches, otherwise diff contains unified diff
1246 if diff:
1247 diffresult[refTableFile] = diff
1248 else:
1249 success = 1
1250 print("template %s matched: r%s ok" % (refTableFile, i))
1251 break
1252
1253 if not success:
701a0192 1254 resultstr = "No template matched.\n"
e7294b32 1255 for f in diffresult.keys():
701a0192 1256 resultstr += "template %s: r%s failed SHOW BGP IPv4 check:\n%s\n" % (
1257 f,
1258 i,
1259 diffresult[f],
1260 )
11761ab0 1261 raise AssertionError(
701a0192 1262 "SHOW BGP IPv4 failed for router r%s:\n%s" % (i, resultstr)
1263 )
4501fbca 1264
7e7fc73b
MW
1265 # Make sure that all daemons are running
1266 for i in range(1, 2):
701a0192 1267 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
1268 assert fatal_error == "", fatal_error
1269
4501fbca
MW
1270
1271def test_bgp_ipv6():
1272 global fatal_error
e82b531d 1273 net = get_topogen().net
4501fbca
MW
1274
1275 # Skip if previous fatal error condition is raised
701a0192 1276 if fatal_error != "":
4501fbca
MW
1277 pytest.skip(fatal_error)
1278
1279 thisDir = os.path.dirname(os.path.realpath(__file__))
1280
b2764f90 1281 print("\n\n** Verifying BGP IPv6")
4501fbca 1282 print("******************************************\n")
6a57e103 1283 diffresult = {}
4501fbca 1284 for i in range(1, 2):
11761ab0 1285 success = 0
701a0192 1286 for refTableFile in glob.glob("%s/r%s/show_bgp_ipv6*.ref" % (thisDir, i)):
11761ab0
MS
1287 if os.path.isfile(refTableFile):
1288 # Read expected result from file
1289 expected = open(refTableFile).read().rstrip()
1290 # Fix newlines (make them all the same)
701a0192 1291 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
11761ab0
MS
1292
1293 # Actual output from router
701a0192 1294 actual = (
1295 net["r%s" % i].cmd('vtysh -c "show bgp ipv6" 2> /dev/null').rstrip()
1296 )
11761ab0 1297 # Remove summary line (changed recently)
701a0192 1298 actual = re.sub(r"Total number.*", "", actual)
1299 actual = re.sub(r"Displayed.*", "", actual)
11761ab0
MS
1300 actual = actual.rstrip()
1301 # Fix newlines (make them all the same)
701a0192 1302 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
11761ab0
MS
1303
1304 # Generate Diff
701a0192 1305 diff = topotest.get_textdiff(
1306 actual,
1307 expected,
11761ab0 1308 title1="actual SHOW BGP IPv6",
701a0192 1309 title2="expected SHOW BGP IPv6",
1310 )
11761ab0
MS
1311
1312 # Empty string if it matches, otherwise diff contains unified diff
1313 if diff:
1314 diffresult[refTableFile] = diff
1315 else:
1316 success = 1
1317 print("template %s matched: r%s ok" % (refTableFile, i))
1318
1319 if not success:
701a0192 1320 resultstr = "No template matched.\n"
e7294b32 1321 for f in diffresult.keys():
701a0192 1322 resultstr += "template %s: r%s failed SHOW BGP IPv6 check:\n%s\n" % (
1323 f,
1324 i,
1325 diffresult[f],
1326 )
11761ab0 1327 raise AssertionError(
701a0192 1328 "SHOW BGP IPv6 failed for router r%s:\n%s" % (i, resultstr)
1329 )
4501fbca 1330
7e7fc73b
MW
1331 # Make sure that all daemons are running
1332 for i in range(1, 2):
701a0192 1333 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
1334 assert fatal_error == "", fatal_error
1335
701a0192 1336
41fce07c
DS
1337def test_route_map():
1338 global fatal_error
e82b531d 1339 net = get_topogen().net
41fce07c 1340
701a0192 1341 if fatal_error != "":
41fce07c
DS
1342 pytest.skip(fatal_error)
1343
1344 thisDir = os.path.dirname(os.path.realpath(__file__))
1345
1346 print("\n\n** Verifying some basic routemap forward references\n")
1347 print("*******************************************************\n")
1348 failures = 0
1349 for i in range(1, 2):
701a0192 1350 refroutemap = "%s/r%s/show_route_map.ref" % (thisDir, i)
41fce07c
DS
1351 if os.path.isfile(refroutemap):
1352 expected = open(refroutemap).read().rstrip()
701a0192 1353 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
41fce07c 1354
701a0192 1355 actual = (
1356 net["r%s" % i].cmd('vtysh -c "show route-map" 2> /dev/null').rstrip()
1357 )
1358 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
41fce07c 1359
701a0192 1360 diff = topotest.get_textdiff(
1361 actual,
1362 expected,
1363 title1="actual show route-map",
1364 title2="expected show route-map",
1365 )
41fce07c
DS
1366
1367 if diff:
701a0192 1368 sys.stderr.write(
1369 "r%s failed show route-map command Check:\n%s\n" % (i, diff)
1370 )
41fce07c
DS
1371 failures += 1
1372 else:
701a0192 1373 print("r%s ok" % i)
1374
1375 assert (
1376 failures == 0
1377 ), "Show route-map command failed for router r%s:\n%s" % (i, diff)
4501fbca
MW
1378
1379
887a232c
SW
1380def test_nexthop_groups_with_route_maps():
1381 global fatal_error
e82b531d 1382 net = get_topogen().net
887a232c
SW
1383
1384 # Skip if previous fatal error condition is raised
701a0192 1385 if fatal_error != "":
887a232c
SW
1386 pytest.skip(fatal_error)
1387
1388 print("\n\n** Verifying Nexthop Groups With Route-Maps")
1389 print("******************************************\n")
1390
1391 ### Nexthop Group With Route-Map Tests
1392
1393 # Create a lib nexthop-group
701a0192 1394 net["r1"].cmd(
1395 'vtysh -c "c t" -c "nexthop-group test" -c "nexthop 1.1.1.1" -c "nexthop 1.1.1.2"'
1396 )
887a232c
SW
1397
1398 ## Route-Map Proto Source
1399
1400 route_str = "2.2.2.1"
1401 src_str = "192.168.0.1"
1402
701a0192 1403 net["r1"].cmd(
1404 'vtysh -c "c t" -c "route-map NH-SRC permit 111" -c "set src %s"' % src_str
1405 )
887a232c
SW
1406 net["r1"].cmd('vtysh -c "c t" -c "ip protocol sharp route-map NH-SRC"')
1407
1408 net["r1"].cmd('vtysh -c "sharp install routes %s nexthop-group test 1"' % route_str)
1409
1410 verify_route_nexthop_group("%s/32" % route_str)
1411
1412 # Only a valid test on linux using nexthop objects
1413 if sys.platform.startswith("linux"):
701a0192 1414 output = net["r1"].cmd("ip route show %s/32" % route_str)
887a232c 1415 match = re.search(r"src %s" % src_str, output)
701a0192 1416 assert match is not None, "Route %s/32 not installed with src %s" % (
1417 route_str,
1418 src_str,
1419 )
887a232c
SW
1420
1421 # Remove NHG routes and route-map
1422 net["r1"].cmd('vtysh -c "sharp remove routes %s 1"' % route_str)
1423 net["r1"].cmd('vtysh -c "c t" -c "no ip protocol sharp route-map NH-SRC"')
701a0192 1424 net["r1"].cmd(
8db751b8 1425 'vtysh -c "c t" -c "no route-map NH-SRC permit 111" # -c "set src %s"' % src_str
701a0192 1426 )
887a232c
SW
1427 net["r1"].cmd('vtysh -c "c t" -c "no route-map NH-SRC"')
1428
1429 ## Route-Map Deny/Permit with same nexthop group
1430
1431 permit_route_str = "3.3.3.1"
1432 deny_route_str = "3.3.3.2"
1433
701a0192 1434 net["r1"].cmd(
1435 'vtysh -c "c t" -c "ip prefix-list NOPE seq 5 permit %s/32"' % permit_route_str
1436 )
1437 net["r1"].cmd(
1438 'vtysh -c "c t" -c "route-map NOPE permit 111" -c "match ip address prefix-list NOPE"'
1439 )
887a232c
SW
1440 net["r1"].cmd('vtysh -c "c t" -c "route-map NOPE deny 222"')
1441 net["r1"].cmd('vtysh -c "c t" -c "ip protocol sharp route-map NOPE"')
1442
1443 # This route should be permitted
701a0192 1444 net["r1"].cmd(
1445 'vtysh -c "sharp install routes %s nexthop-group test 1"' % permit_route_str
1446 )
887a232c
SW
1447
1448 verify_route_nexthop_group("%s/32" % permit_route_str)
1449
1450 # This route should be denied
701a0192 1451 net["r1"].cmd(
1452 'vtysh -c "sharp install routes %s nexthop-group test 1"' % deny_route_str
1453 )
887a232c
SW
1454
1455 nhg_id = route_get_nhg_id(deny_route_str)
1456 output = net["r1"].cmd('vtysh -c "show nexthop-group rib %d"' % nhg_id)
1457
1458 match = re.search(r"Valid", output)
1459 assert match is None, "Nexthop Group ID=%d should not be marked Valid" % nhg_id
1460
1461 match = re.search(r"Installed", output)
1462 assert match is None, "Nexthop Group ID=%d should not be marked Installed" % nhg_id
1463
1464 # Remove NHG routes and route-map
1465 net["r1"].cmd('vtysh -c "sharp remove routes %s 1"' % permit_route_str)
1466 net["r1"].cmd('vtysh -c "sharp remove routes %s 1"' % deny_route_str)
1467 net["r1"].cmd('vtysh -c "c t" -c "no ip protocol sharp route-map NOPE"')
1468 net["r1"].cmd('vtysh -c "c t" -c "no route-map NOPE permit 111"')
1469 net["r1"].cmd('vtysh -c "c t" -c "no route-map NOPE deny 222"')
1470 net["r1"].cmd('vtysh -c "c t" -c "no route-map NOPE"')
701a0192 1471 net["r1"].cmd(
1472 'vtysh -c "c t" -c "no ip prefix-list NOPE seq 5 permit %s/32"'
1473 % permit_route_str
1474 )
1475
887a232c 1476
8f4d7212
SW
1477def test_nexthop_group_replace():
1478 global fatal_error
e82b531d 1479 net = get_topogen().net
8f4d7212
SW
1480
1481 # Skip if previous fatal error condition is raised
701a0192 1482 if fatal_error != "":
8f4d7212
SW
1483 pytest.skip(fatal_error)
1484
1485 print("\n\n** Verifying Nexthop Groups")
1486 print("******************************************\n")
1487
1488 ### Nexthop Group Tests
1489
1490 ## 2-Way ECMP Directly Connected
1491
701a0192 1492 net["r1"].cmd(
1493 'vtysh -c "c t" -c "nexthop-group replace" -c "nexthop 1.1.1.1 r1-eth1 onlink" -c "nexthop 1.1.1.2 r1-eth2 onlink"'
1494 )
8f4d7212 1495
8beb469f
DS
1496 # At the moment there is absolutely no real easy way to query sharpd
1497 # for the nexthop group actually installed. If it is not installed
1498 # sharpd will just transmit the nexthops down instead of the nexthop
1499 # group id. Leading to a situation where the replace is not actually
1500 # being tested. So let's just wait some time here because this
1501 # is hard and this test fails all the time
1502 sleep(5)
1503
8f4d7212
SW
1504 # Create with sharpd using nexthop-group
1505 net["r1"].cmd('vtysh -c "sharp install routes 3.3.3.1 nexthop-group replace 1"')
1506
1507 verify_route_nexthop_group("3.3.3.1/32")
1508
1509 # Change the nexthop group
701a0192 1510 net["r1"].cmd(
1511 'vtysh -c "c t" -c "nexthop-group replace" -c "no nexthop 1.1.1.1 r1-eth1 onlink" -c "nexthop 1.1.1.3 r1-eth1 onlink" -c "nexthop 1.1.1.4 r1-eth4 onlink"'
1512 )
8f4d7212
SW
1513
1514 # Verify it updated. We can just check install and ecmp count here.
1515 verify_route_nexthop_group("3.3.3.1/32", False, 3)
1516
701a0192 1517
4501fbca
MW
1518def test_mpls_interfaces():
1519 global fatal_error
e82b531d 1520 net = get_topogen().net
4501fbca
MW
1521
1522 # Skip if previous fatal error condition is raised
701a0192 1523 if fatal_error != "":
4501fbca
MW
1524 pytest.skip(fatal_error)
1525
1526 # Skip if no LDP installed or old kernel
701a0192 1527 if net["r1"].daemon_available("ldpd") == False:
4501fbca
MW
1528 pytest.skip("No MPLS or kernel < 4.5")
1529
1530 thisDir = os.path.dirname(os.path.realpath(__file__))
1531
b2764f90 1532 print("\n\n** Verifying MPLS Interfaces")
4501fbca
MW
1533 print("******************************************\n")
1534 failures = 0
1535 for i in range(1, 2):
701a0192 1536 refTableFile = "%s/r%s/show_mpls_ldp_interface.ref" % (thisDir, i)
4501fbca
MW
1537 if os.path.isfile(refTableFile):
1538 # Read expected result from file
1539 expected = open(refTableFile).read().rstrip()
1540 # Fix newlines (make them all the same)
701a0192 1541 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
4501fbca
MW
1542
1543 # Actual output from router
701a0192 1544 actual = (
1545 net["r%s" % i]
1546 .cmd('vtysh -c "show mpls ldp interface" 2> /dev/null')
1547 .rstrip()
1548 )
4501fbca
MW
1549 # Mask out Timer in Uptime
1550 actual = re.sub(r" [0-9][0-9]:[0-9][0-9]:[0-9][0-9] ", " xx:xx:xx ", actual)
1551 # Fix newlines (make them all the same)
701a0192 1552 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
4501fbca
MW
1553
1554 # Generate Diff
701a0192 1555 diff = topotest.get_textdiff(
1556 actual,
1557 expected,
17070436 1558 title1="actual MPLS LDP interface status",
701a0192 1559 title2="expected MPLS LDP interface status",
1560 )
4501fbca
MW
1561
1562 # Empty string if it matches, otherwise diff contains unified diff
1563 if diff:
701a0192 1564 sys.stderr.write(
1565 "r%s failed MPLS LDP Interface status Check:\n%s\n" % (i, diff)
1566 )
4501fbca
MW
1567 failures += 1
1568 else:
1569 print("r%s ok" % i)
1570
701a0192 1571 if failures > 0:
4501fbca
MW
1572 fatal_error = "MPLS LDP Interface status failed"
1573
701a0192 1574 assert (
1575 failures == 0
1576 ), "MPLS LDP Interface status failed for router r%s:\n%s" % (i, diff)
4501fbca 1577
7e7fc73b
MW
1578 # Make sure that all daemons are running
1579 for i in range(1, 2):
701a0192 1580 fatal_error = net["r%s" % i].checkRouterRunning()
7e7fc73b
MW
1581 assert fatal_error == "", fatal_error
1582
4501fbca 1583
a5e5c9a3
DS
1584def test_resilient_nexthop_group():
1585 net = get_topogen().net
1586
1587 result = required_linux_kernel_version("5.19")
1588 if result is not True:
1589 pytest.skip("Kernel requirements are not met, kernel version should be >= 5.19")
1590
1591 net["r1"].cmd(
1592 'vtysh -c "conf" -c "nexthop-group resilience" -c "resilient buckets 64 idle-timer 128 unbalanced-timer 256" -c "nexthop 1.1.1.1 r1-eth1 onlink" -c "nexthop 1.1.1.2 r1-eth2 onlink"'
1593 )
1594
1595 output = net["r1"].cmd('vtysh -c "show nexthop-group rib sharp"')
1596 output = re.findall(r"Buckets", output)
1597
1598 verify_nexthop_group(185483878)
1599 assert len(output) == 1, "Resilient NHG not created in zebra"
1600
1601
4501fbca
MW
1602def test_shutdown_check_stderr():
1603 global fatal_error
e82b531d 1604 net = get_topogen().net
4501fbca
MW
1605
1606 # Skip if previous fatal error condition is raised
701a0192 1607 if fatal_error != "":
4501fbca
MW
1608 pytest.skip(fatal_error)
1609
b2764f90 1610 print("\n\n** Verifying unexpected STDERR output from daemons")
4501fbca
MW
1611 print("******************************************\n")
1612
701a0192 1613 if os.environ.get("TOPOTESTS_CHECK_STDERR") is None:
1614 print(
1615 "SKIPPED final check on StdErr output: Disabled (TOPOTESTS_CHECK_STDERR undefined)\n"
1616 )
1617 pytest.skip("Skipping test for Stderr output")
4501fbca
MW
1618
1619 thisDir = os.path.dirname(os.path.realpath(__file__))
1620
50c40bde
MW
1621 print("thisDir=" + thisDir)
1622
701a0192 1623 net["r1"].stopRouter()
4501fbca 1624
701a0192 1625 log = net["r1"].getStdErr("ripd")
8e957dbb
MW
1626 if log:
1627 print("\nRIPd StdErr Log:\n" + log)
701a0192 1628 log = net["r1"].getStdErr("ripngd")
8e957dbb
MW
1629 if log:
1630 print("\nRIPngd StdErr Log:\n" + log)
701a0192 1631 log = net["r1"].getStdErr("ospfd")
8e957dbb
MW
1632 if log:
1633 print("\nOSPFd StdErr Log:\n" + log)
701a0192 1634 log = net["r1"].getStdErr("ospf6d")
8e957dbb
MW
1635 if log:
1636 print("\nOSPF6d StdErr Log:\n" + log)
701a0192 1637 log = net["r1"].getStdErr("isisd")
8e957dbb
MW
1638 if log:
1639 print("\nISISd StdErr Log:\n" + log)
701a0192 1640 log = net["r1"].getStdErr("bgpd")
8e957dbb
MW
1641 if log:
1642 print("\nBGPd StdErr Log:\n" + log)
af39fbe7 1643
701a0192 1644 log = net["r1"].getStdErr("nhrpd")
af39fbe7
MS
1645 if log:
1646 print("\nNHRPd StdErr Log:\n" + log)
1647
701a0192 1648 log = net["r1"].getStdErr("pbrd")
af39fbe7
MS
1649 if log:
1650 print("\nPBRd StdErr Log:\n" + log)
1651
701a0192 1652 log = net["r1"].getStdErr("babeld")
af39fbe7
MS
1653 if log:
1654 print("\nBABELd StdErr Log:\n" + log)
1655
701a0192 1656 if net["r1"].daemon_available("ldpd"):
1657 log = net["r1"].getStdErr("ldpd")
8e957dbb
MW
1658 if log:
1659 print("\nLDPd StdErr Log:\n" + log)
701a0192 1660 log = net["r1"].getStdErr("zebra")
8e957dbb
MW
1661 if log:
1662 print("\nZebra StdErr Log:\n" + log)
4501fbca
MW
1663
1664
50c40bde
MW
1665def test_shutdown_check_memleak():
1666 global fatal_error
e82b531d 1667 net = get_topogen().net
50c40bde
MW
1668
1669 # Skip if previous fatal error condition is raised
701a0192 1670 if fatal_error != "":
50c40bde
MW
1671 pytest.skip(fatal_error)
1672
701a0192 1673 if os.environ.get("TOPOTESTS_CHECK_MEMLEAK") is None:
1674 print(
1675 "SKIPPED final check on Memory leaks: Disabled (TOPOTESTS_CHECK_MEMLEAK undefined)\n"
1676 )
1677 pytest.skip("Skipping test for memory leaks")
1678
50c40bde
MW
1679 thisDir = os.path.dirname(os.path.realpath(__file__))
1680
1681 for i in range(1, 2):
701a0192 1682 net["r%s" % i].stopRouter()
1683 net["r%s" % i].report_memory_leaks(
1684 os.environ.get("TOPOTESTS_CHECK_MEMLEAK"), os.path.basename(__file__)
1685 )
50c40bde
MW
1686
1687
701a0192 1688if __name__ == "__main__":
4501fbca
MW
1689 # To suppress tracebacks, either use the following pytest call or add "--tb=no" to cli
1690 # retval = pytest.main(["-s", "--tb=no"])
1691 retval = pytest.main(["-s"])
1692 sys.exit(retval)