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