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