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