]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/all-protocol-startup/test_all_protocol_startup.py
Merge pull request #6016 from sarav511/ppend
[mirror_frr.git] / tests / topotests / all-protocol-startup / test_all_protocol_startup.py
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 """
26 test_all_protocol_startup.py: Test of all protocols at same time
27
28 """
29
30 import os
31 import re
32 import sys
33 import pytest
34 import glob
35 from time import sleep
36
37 from mininet.topo import Topo
38 from mininet.net import Mininet
39 from mininet.node import Node, OVSSwitch, Host
40 from mininet.log import setLogLevel, info
41 from mininet.cli import CLI
42 from mininet.link import Intf
43
44 from functools import partial
45
46 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
47 from lib import topotest
48
49 fatal_error = ""
50
51
52 #####################################################
53 ##
54 ## Network Topology Definition
55 ##
56 #####################################################
57
58
59 class NetworkTopo(Topo):
60 "All Protocol Startup Test"
61
62 def build(self, **_opts):
63
64 # Setup Routers
65 router = {}
66 #
67 # Setup Main Router
68 router[1] = topotest.addRouter(self, "r1")
69 #
70
71 # Setup Switches
72 switch = {}
73 #
74 for i in range(0, 10):
75 switch[i] = self.addSwitch("sw%s" % i, cls=topotest.LegacySwitch)
76 self.addLink(switch[i], router[1], intfName2="r1-eth%s" % i)
77
78
79 #####################################################
80 ##
81 ## Tests starting
82 ##
83 #####################################################
84
85
86 def 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")
94 os.system("sudo mn -c > /dev/null 2>&1")
95 os.system("sudo rm /tmp/r* > /dev/null 2>&1")
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
103 if net["r1"].get_routertype() != "frr":
104 fatal_error = "Test is only implemented for FRR"
105 sys.stderr.write("\n\nTest is only implemented for FRR - Skipping\n\n")
106 pytest.skip(fatal_error)
107
108 # Starting Routers
109 #
110 # Main router
111 for i in range(1, 2):
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 )
120 else:
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"):
125 # Only test LDPd if it's installed and Kernel >= 4.5
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()
132
133 # For debugging after starting FRR daemons, uncomment the next line
134 # CLI(net)
135
136
137 def 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
147 def test_router_running():
148 global fatal_error
149 global net
150
151 # Skip if previous fatal error condition is raised
152 if fatal_error != "":
153 pytest.skip(fatal_error)
154
155 print("\n\n** Check if FRR is running on each Router node")
156 print("******************************************\n")
157 sleep(5)
158
159 # Starting Routers
160 for i in range(1, 2):
161 fatal_error = net["r%s" % i].checkRouterRunning()
162 assert fatal_error == "", fatal_error
163
164 # For debugging after starting FRR daemons, uncomment the next line
165 # CLI(net)
166
167
168 def test_error_messages_vtysh():
169 global fatal_error
170 global net
171
172 # Skip if previous fatal error condition is raised
173 if fatal_error != "":
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
186 vtystdout = net["r%s" % i].cmd('vtysh -c "show version" 2> /dev/null').rstrip()
187
188 # Fix newlines (make them all the same)
189 vtystdout = ("\n".join(vtystdout.splitlines()) + "\n").rstrip()
190 # Drop everything starting with "FRRouting X.xx" message
191 vtystdout = re.sub(r"FRRouting [0-9]+.*", "", vtystdout, flags=re.DOTALL)
192
193 if vtystdout == "":
194 print("r%s StdOut ok" % i)
195
196 assert vtystdout == "", "Vtysh StdOut Output check failed for router r%s" % i
197
198 #
199 # Second checking Standard Error
200 #
201
202 # VTYSH StdErr output from router
203 vtystderr = net["r%s" % i].cmd('vtysh -c "show version" > /dev/null').rstrip()
204
205 # Fix newlines (make them all the same)
206 vtystderr = ("\n".join(vtystderr.splitlines()) + "\n").rstrip()
207 # # Drop everything starting with "FRRouting X.xx" message
208 # vtystderr = re.sub(r"FRRouting [0-9]+.*", "", vtystderr, flags=re.DOTALL)
209
210 if vtystderr == "":
211 print("r%s StdErr ok" % i)
212
213 assert vtystderr == "", "Vtysh StdErr Output check failed for router r%s" % i
214
215 # Make sure that all daemons are running
216 for i in range(1, 2):
217 fatal_error = net["r%s" % i].checkRouterRunning()
218 assert fatal_error == "", fatal_error
219
220 # For debugging after starting FRR daemons, uncomment the next line
221 # CLI(net)
222
223
224 def test_error_messages_daemons():
225 global fatal_error
226 global net
227
228 # Skip if previous fatal error condition is raised
229 if fatal_error != "":
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):
238 log = net["r%s" % i].getStdErr("ripd")
239 if log:
240 error_logs += "r%s RIPd StdErr Output:\n" % i
241 error_logs += log
242 log = net["r%s" % i].getStdErr("ripngd")
243 if log:
244 error_logs += "r%s RIPngd StdErr Output:\n" % i
245 error_logs += log
246 log = net["r%s" % i].getStdErr("ospfd")
247 if log:
248 error_logs += "r%s OSPFd StdErr Output:\n" % i
249 error_logs += log
250 log = net["r%s" % i].getStdErr("ospf6d")
251 if log:
252 error_logs += "r%s OSPF6d StdErr Output:\n" % i
253 error_logs += log
254 log = net["r%s" % i].getStdErr("isisd")
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
261 log = net["r%s" % i].getStdErr("bgpd")
262 if log:
263 error_logs += "r%s BGPd StdErr Output:\n" % i
264 error_logs += log
265 if net["r%s" % i].daemon_available("ldpd"):
266 log = net["r%s" % i].getStdErr("ldpd")
267 if log:
268 error_logs += "r%s LDPd StdErr Output:\n" % i
269 error_logs += log
270
271 log = net["r1"].getStdErr("nhrpd")
272 if log:
273 error_logs += "r%s NHRPd StdErr Output:\n" % i
274 error_logs += log
275
276 log = net["r1"].getStdErr("babeld")
277 if log:
278 error_logs += "r%s BABELd StdErr Output:\n" % i
279 error_logs += log
280
281 log = net["r1"].getStdErr("pbrd")
282 if log:
283 error_logs += "r%s PBRd StdErr Output:\n" % i
284 error_logs += log
285
286 log = net["r%s" % i].getStdErr("zebra")
287 if log:
288 error_logs += "r%s Zebra StdErr Output:\n"
289 error_logs += log
290
291 if error_logs:
292 sys.stderr.write(
293 "Failed check for StdErr Output on daemons:\n%s\n" % error_logs
294 )
295
296 # Ignoring the issue if told to ignore (ie not yet fixed)
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 )
305
306 assert error_logs == "", "Daemons report errors to StdErr"
307
308 # For debugging after starting FRR daemons, uncomment the next line
309 # CLI(net)
310
311
312 def test_converge_protocols():
313 global fatal_error
314 global net
315
316 # Skip if previous fatal error condition is raised
317 if fatal_error != "":
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
328 # Make sure that all daemons are running
329 failures = 0
330 for i in range(1, 2):
331 fatal_error = net["r%s" % i].checkRouterRunning()
332 assert fatal_error == "", fatal_error
333
334 print("Show that v4 routes are right\n")
335 v4_routesFile = "%s/r%s/ipv4_routes.ref" % (thisDir, i)
336 expected = open(v4_routesFile).read().rstrip()
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 )
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)
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 )
355 if diff:
356 sys.stderr.write("r%s failed IP Routing table check:\n%s\n" % (i, diff))
357 failures += 1
358 else:
359 print("r%s ok" % i)
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")
366 v6_routesFile = "%s/r%s/ipv6_routes.ref" % (thisDir, i)
367 expected = open(v6_routesFile).read().rstrip()
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 )
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)
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 )
386 if diff:
387 sys.stderr.write("r%s failed IPv6 Routing table check:\n%s\n" % (i, diff))
388 failures += 1
389 else:
390 print("r%s ok" % i)
391
392 assert failures == 0, "IPv6 Routing table failed for r%s\n%s" % (i, diff)
393
394 # For debugging after starting FRR daemons, uncomment the next line
395 ## CLI(net)
396
397
398 def 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)
401 assert match is not None, (
402 "Nexthop Group ID not found for sharpd route %s" % route_str
403 )
404
405 nhg_id = int(match.group(1))
406 return nhg_id
407
408
409 def verify_nexthop_group(nhg_id, recursive=False, ecmp=0):
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
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:
424 assert len(depends) == ecmp, (
425 "Nexthop Group ID=%d doesn't match ecmp size" % nhg_id
426 )
427 else:
428 # If recursive, we need to look at its resolved group
429 assert len(depends) == 1, (
430 "Nexthop Group ID=%d should only have one recursive depend" % nhg_id
431 )
432 resolved_id = int(depends[0])
433 verify_nexthop_group(resolved_id, False)
434
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
439
440 def verify_route_nexthop_group(route_str, recursive=False, ecmp=0):
441 # Verify route and that zebra created NHGs for and they are valid/installed
442 nhg_id = route_get_nhg_id(route_str)
443 verify_nexthop_group(nhg_id, recursive, ecmp)
444
445
446 def test_nexthop_groups():
447 global fatal_error
448 global net
449
450 # Skip if previous fatal error condition is raised
451 if fatal_error != "":
452 pytest.skip(fatal_error)
453
454 print("\n\n** Verifying Nexthop Groups")
455 print("******************************************\n")
456
457 ### Nexthop Group Tests
458
459 ## Basic test
460
461 # Create a lib nexthop-group
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 )
465
466 # Create with sharpd using nexthop-group
467 net["r1"].cmd('vtysh -c "sharp install routes 2.2.2.1 nexthop-group basic 1"')
468
469 verify_route_nexthop_group("2.2.2.1/32")
470
471 ## Connected
472
473 net["r1"].cmd(
474 'vtysh -c "c t" -c "nexthop-group connected" -c "nexthop r1-eth1" -c "nexthop r1-eth2"'
475 )
476
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
483 net["r1"].cmd(
484 'vtysh -c "c t" -c "nexthop-group basic-recursive" -c "nexthop 2.2.2.1"'
485 )
486
487 net["r1"].cmd(
488 'vtysh -c "sharp install routes 3.3.3.1 nexthop-group basic-recursive 1"'
489 )
490
491 verify_route_nexthop_group("3.3.3.1/32", True)
492
493 ## Duplicate
494
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 )
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
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 )
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
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 )
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
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 )
528
529 net["r1"].cmd(
530 'vtysh -c "sharp install routes 5.5.5.1 nexthop-group eight-recursive 1"'
531 )
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"')
546
547
548 def test_rip_status():
549 global fatal_error
550 global net
551
552 # Skip if previous fatal error condition is raised
553 if fatal_error != "":
554 pytest.skip(fatal_error)
555
556 thisDir = os.path.dirname(os.path.realpath(__file__))
557
558 print("\n\n** Verifying RIP status")
559 print("******************************************\n")
560 failures = 0
561 for i in range(1, 2):
562 refTableFile = "%s/r%s/rip_status.ref" % (thisDir, i)
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)
567 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
568
569 # Actual output from router
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
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)
580 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
581
582 # Generate Diff
583 diff = topotest.get_textdiff(
584 actual,
585 expected,
586 title1="actual IP RIP status",
587 title2="expected IP RIP status",
588 )
589
590 # Empty string if it matches, otherwise diff contains unified diff
591 if diff:
592 sys.stderr.write("r%s failed IP RIP status check:\n%s\n" % (i, diff))
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
599 # Make sure that all daemons are running
600 for i in range(1, 2):
601 fatal_error = net["r%s" % i].checkRouterRunning()
602 assert fatal_error == "", fatal_error
603
604 # For debugging after starting FRR daemons, uncomment the next line
605 # CLI(net)
606
607
608 def test_ripng_status():
609 global fatal_error
610 global net
611
612 # Skip if previous fatal error condition is raised
613 if fatal_error != "":
614 pytest.skip(fatal_error)
615
616 thisDir = os.path.dirname(os.path.realpath(__file__))
617
618 print("\n\n** Verifying RIPng status")
619 print("******************************************\n")
620 failures = 0
621 for i in range(1, 2):
622 refTableFile = "%s/r%s/ripng_status.ref" % (thisDir, i)
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)
627 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
628
629 # Actual output from router
630 actual = (
631 net["r%s" % i]
632 .cmd('vtysh -c "show ipv6 ripng status" 2> /dev/null')
633 .rstrip()
634 )
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)
637 # Drop time in next due
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)
642 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
643
644 # Generate Diff
645 diff = topotest.get_textdiff(
646 actual,
647 expected,
648 title1="actual IPv6 RIPng status",
649 title2="expected IPv6 RIPng status",
650 )
651
652 # Empty string if it matches, otherwise diff contains unified diff
653 if diff:
654 sys.stderr.write(
655 "r%s failed IPv6 RIPng status check:\n%s\n" % (i, diff)
656 )
657 failures += 1
658 else:
659 print("r%s ok" % i)
660
661 assert failures == 0, "IPv6 RIPng status failed for router r%s:\n%s" % (
662 i,
663 diff,
664 )
665
666 # Make sure that all daemons are running
667 for i in range(1, 2):
668 fatal_error = net["r%s" % i].checkRouterRunning()
669 assert fatal_error == "", fatal_error
670
671 # For debugging after starting FRR daemons, uncomment the next line
672 # CLI(net)
673
674
675 def test_ospfv2_interfaces():
676 global fatal_error
677 global net
678
679 # Skip if previous fatal error condition is raised
680 if fatal_error != "":
681 pytest.skip(fatal_error)
682
683 thisDir = os.path.dirname(os.path.realpath(__file__))
684
685 print("\n\n** Verifying OSPFv2 interfaces")
686 print("******************************************\n")
687 failures = 0
688 for i in range(1, 2):
689 refTableFile = "%s/r%s/show_ip_ospf_interface.ref" % (thisDir, i)
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)
694 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
695
696 # Actual output from router
697 actual = (
698 net["r%s" % i]
699 .cmd('vtysh -c "show ip ospf interface" 2> /dev/null')
700 .rstrip()
701 )
702 # Mask out Bandwidth portion. They may change..
703 actual = re.sub(r"BW [0-9]+ Mbit", "BW XX Mbit", actual)
704 actual = re.sub(r"ifindex [0-9]", "ifindex X", actual)
705
706 # Drop time in next due
707 actual = re.sub(r"Hello due in [0-9\.]+s", "Hello due in XX.XXXs", actual)
708 actual = re.sub(
709 r"Hello due in [0-9\.]+ usecs", "Hello due in XX.XXXs", actual
710 )
711 # Fix 'MTU mismatch detection: enabled' vs 'MTU mismatch detection:enabled' - accept both
712 actual = re.sub(
713 r"MTU mismatch detection:([a-z]+.*)",
714 r"MTU mismatch detection: \1",
715 actual,
716 )
717 # Fix newlines (make them all the same)
718 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
719
720 # Generate Diff
721 diff = topotest.get_textdiff(
722 actual,
723 expected,
724 title1="actual SHOW IP OSPF INTERFACE",
725 title2="expected SHOW IP OSPF INTERFACE",
726 )
727
728 # Empty string if it matches, otherwise diff contains unified diff
729 if diff:
730 sys.stderr.write(
731 "r%s failed SHOW IP OSPF INTERFACE check:\n%s\n" % (i, diff)
732 )
733 failures += 1
734 else:
735 print("r%s ok" % i)
736
737 # Ignoring the issue if told to ignore (ie not yet fixed)
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)
750
751 # Make sure that all daemons are running
752 for i in range(1, 2):
753 fatal_error = net["r%s" % i].checkRouterRunning()
754 assert fatal_error == "", fatal_error
755
756 # For debugging after starting FRR daemons, uncomment the next line
757 # CLI(net)
758
759
760 def test_isis_interfaces():
761 global fatal_error
762 global net
763
764 # Skip if previous fatal error condition is raised
765 if fatal_error != "":
766 pytest.skip(fatal_error)
767
768 thisDir = os.path.dirname(os.path.realpath(__file__))
769
770 print("\n\n** Verifying ISIS interfaces")
771 print("******************************************\n")
772 failures = 0
773 for i in range(1, 2):
774 refTableFile = "%s/r%s/show_isis_interface_detail.ref" % (thisDir, i)
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)
779 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
780
781 # Actual output from router
782 actual = (
783 net["r%s" % i]
784 .cmd('vtysh -c "show isis interface detail" 2> /dev/null')
785 .rstrip()
786 )
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)
791 # Mask out Circuit ID number
792 actual = re.sub(r"Circuit Id: 0x[0-9a-f]+", "Circuit Id: 0xXX", actual)
793 # Fix newlines (make them all the same)
794 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
795
796 # Generate Diff
797 diff = topotest.get_textdiff(
798 actual,
799 expected,
800 title1="actual SHOW ISIS INTERFACE DETAIL",
801 title2="expected SHOW ISIS OSPF6 INTERFACE DETAIL",
802 )
803
804 # Empty string if it matches, otherwise diff contains unified diff
805 if diff:
806 sys.stderr.write(
807 "r%s failed SHOW ISIS INTERFACE DETAIL check:\n%s\n" % (i, diff)
808 )
809 failures += 1
810 else:
811 print("r%s ok" % i)
812
813 assert (
814 failures == 0
815 ), "SHOW ISIS INTERFACE DETAIL failed for router r%s:\n%s" % (i, diff)
816
817 # Make sure that all daemons are running
818 for i in range(1, 2):
819 fatal_error = net["r%s" % i].checkRouterRunning()
820 assert fatal_error == "", fatal_error
821
822 # For debugging after starting FRR daemons, uncomment the next line
823 # CLI(net)
824
825
826 def test_bgp_summary():
827 global fatal_error
828 global net
829
830 # Skip if previous fatal error condition is raised
831 if fatal_error != "":
832 pytest.skip(fatal_error)
833
834 thisDir = os.path.dirname(os.path.realpath(__file__))
835
836 print("\n\n** Verifying BGP Summary")
837 print("******************************************\n")
838 failures = 0
839 for i in range(1, 2):
840 refTableFile = "%s/r%s/show_ip_bgp_summary.ref" % (thisDir, i)
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)
845 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
846
847 # Actual output from router
848 actual = (
849 net["r%s" % i]
850 .cmd('vtysh -c "show ip bgp summary" 2> /dev/null')
851 .rstrip()
852 )
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)
857 #
858 # Remove extra summaries which exist with newer versions
859 #
860 # Remove summary lines (changed recently)
861 actual = re.sub(r"Total number.*", "", actual)
862 actual = re.sub(r"Displayed.*", "", actual)
863 # Remove IPv4 Unicast Summary (Title only)
864 actual = re.sub(r"IPv4 Unicast Summary:", "", actual)
865 # Remove IPv4 Multicast Summary (all of it)
866 actual = re.sub(r"IPv4 Multicast Summary:", "", actual)
867 actual = re.sub(r"No IPv4 Multicast neighbor is configured", "", actual)
868 # Remove IPv4 VPN Summary (all of it)
869 actual = re.sub(r"IPv4 VPN Summary:", "", actual)
870 actual = re.sub(r"No IPv4 VPN neighbor is configured", "", actual)
871 # Remove IPv4 Encap Summary (all of it)
872 actual = re.sub(r"IPv4 Encap Summary:", "", actual)
873 actual = re.sub(r"No IPv4 Encap neighbor is configured", "", actual)
874 # Remove Unknown Summary (all of it)
875 actual = re.sub(r"Unknown Summary:", "", actual)
876 actual = re.sub(r"No Unknown neighbor is configured", "", actual)
877
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 )
882
883 # Strip empty lines
884 actual = actual.lstrip()
885 actual = actual.rstrip()
886 #
887 # Fix newlines (make them all the same)
888 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
889
890 # Generate Diff
891 diff = topotest.get_textdiff(
892 actual,
893 expected,
894 title1="actual SHOW IP BGP SUMMARY",
895 title2="expected SHOW IP BGP SUMMARY",
896 )
897
898 # Empty string if it matches, otherwise diff contains unified diff
899 if diff:
900 sys.stderr.write(
901 "r%s failed SHOW IP BGP SUMMARY check:\n%s\n" % (i, diff)
902 )
903 failures += 1
904 else:
905 print("r%s ok" % i)
906
907 assert failures == 0, "SHOW IP BGP SUMMARY failed for router r%s:\n%s" % (
908 i,
909 diff,
910 )
911
912 # Make sure that all daemons are running
913 for i in range(1, 2):
914 fatal_error = net["r%s" % i].checkRouterRunning()
915 assert fatal_error == "", fatal_error
916
917 # For debugging after starting FRR daemons, uncomment the next line
918 # CLI(net)
919
920
921 def test_bgp_ipv6_summary():
922 global fatal_error
923 global net
924
925 # Skip if previous fatal error condition is raised
926 if fatal_error != "":
927 pytest.skip(fatal_error)
928
929 thisDir = os.path.dirname(os.path.realpath(__file__))
930
931 print("\n\n** Verifying BGP IPv6 Summary")
932 print("******************************************\n")
933 failures = 0
934 for i in range(1, 2):
935 refTableFile = "%s/r%s/show_bgp_ipv6_summary.ref" % (thisDir, i)
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)
940 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
941
942 # Actual output from router
943 actual = (
944 net["r%s" % i]
945 .cmd('vtysh -c "show bgp ipv6 summary" 2> /dev/null')
946 .rstrip()
947 )
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)
952 #
953 # Remove extra summaries which exist with newer versions
954 #
955 # Remove summary lines (changed recently)
956 actual = re.sub(r"Total number.*", "", actual)
957 actual = re.sub(r"Displayed.*", "", actual)
958 # Remove IPv4 Unicast Summary (Title only)
959 actual = re.sub(r"IPv6 Unicast Summary:", "", actual)
960 # Remove IPv4 Multicast Summary (all of it)
961 actual = re.sub(r"IPv6 Multicast Summary:", "", actual)
962 actual = re.sub(r"No IPv6 Multicast neighbor is configured", "", actual)
963 # Remove IPv4 VPN Summary (all of it)
964 actual = re.sub(r"IPv6 VPN Summary:", "", actual)
965 actual = re.sub(r"No IPv6 VPN neighbor is configured", "", actual)
966 # Remove IPv4 Encap Summary (all of it)
967 actual = re.sub(r"IPv6 Encap Summary:", "", actual)
968 actual = re.sub(r"No IPv6 Encap neighbor is configured", "", actual)
969 # Remove Unknown Summary (all of it)
970 actual = re.sub(r"Unknown Summary:", "", actual)
971 actual = re.sub(r"No Unknown neighbor is configured", "", actual)
972
973 # Remove Labeled Unicast Summary (all of it)
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 )
978
979 # Strip empty lines
980 actual = actual.lstrip()
981 actual = actual.rstrip()
982 #
983 # Fix newlines (make them all the same)
984 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
985
986 # Generate Diff
987 diff = topotest.get_textdiff(
988 actual,
989 expected,
990 title1="actual SHOW BGP IPv6 SUMMARY",
991 title2="expected SHOW BGP IPv6 SUMMARY",
992 )
993
994 # Empty string if it matches, otherwise diff contains unified diff
995 if diff:
996 sys.stderr.write(
997 "r%s failed SHOW BGP IPv6 SUMMARY check:\n%s\n" % (i, diff)
998 )
999 failures += 1
1000 else:
1001 print("r%s ok" % i)
1002
1003 assert failures == 0, "SHOW BGP IPv6 SUMMARY failed for router r%s:\n%s" % (
1004 i,
1005 diff,
1006 )
1007
1008 # Make sure that all daemons are running
1009 for i in range(1, 2):
1010 fatal_error = net["r%s" % i].checkRouterRunning()
1011 assert fatal_error == "", fatal_error
1012
1013 # For debugging after starting FRR daemons, uncomment the next line
1014 # CLI(net)
1015
1016
1017 def test_bgp_ipv4():
1018 global fatal_error
1019 global net
1020
1021 # Skip if previous fatal error condition is raised
1022 if fatal_error != "":
1023 pytest.skip(fatal_error)
1024
1025 thisDir = os.path.dirname(os.path.realpath(__file__))
1026
1027 print("\n\n** Verifying BGP IPv4")
1028 print("******************************************\n")
1029 diffresult = {}
1030 for i in range(1, 2):
1031 success = 0
1032 for refTableFile in glob.glob("%s/r%s/show_bgp_ipv4*.ref" % (thisDir, i)):
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)
1037 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
1038
1039 # Actual output from router
1040 actual = (
1041 net["r%s" % i].cmd('vtysh -c "show bgp ipv4" 2> /dev/null').rstrip()
1042 )
1043 # Remove summary line (changed recently)
1044 actual = re.sub(r"Total number.*", "", actual)
1045 actual = re.sub(r"Displayed.*", "", actual)
1046 actual = actual.rstrip()
1047 # Fix newlines (make them all the same)
1048 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
1049
1050 # Generate Diff
1051 diff = topotest.get_textdiff(
1052 actual,
1053 expected,
1054 title1="actual SHOW BGP IPv4",
1055 title2="expected SHOW BGP IPv4",
1056 )
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:
1067 resultstr = "No template matched.\n"
1068 for f in diffresult.iterkeys():
1069 resultstr += "template %s: r%s failed SHOW BGP IPv4 check:\n%s\n" % (
1070 f,
1071 i,
1072 diffresult[f],
1073 )
1074 raise AssertionError(
1075 "SHOW BGP IPv4 failed for router r%s:\n%s" % (i, resultstr)
1076 )
1077
1078 # Make sure that all daemons are running
1079 for i in range(1, 2):
1080 fatal_error = net["r%s" % i].checkRouterRunning()
1081 assert fatal_error == "", fatal_error
1082
1083 # For debugging after starting FRR daemons, uncomment the next line
1084 # CLI(net)
1085
1086
1087 def test_bgp_ipv6():
1088 global fatal_error
1089 global net
1090
1091 # Skip if previous fatal error condition is raised
1092 if fatal_error != "":
1093 pytest.skip(fatal_error)
1094
1095 thisDir = os.path.dirname(os.path.realpath(__file__))
1096
1097 print("\n\n** Verifying BGP IPv6")
1098 print("******************************************\n")
1099 diffresult = {}
1100 for i in range(1, 2):
1101 success = 0
1102 for refTableFile in glob.glob("%s/r%s/show_bgp_ipv6*.ref" % (thisDir, i)):
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)
1107 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
1108
1109 # Actual output from router
1110 actual = (
1111 net["r%s" % i].cmd('vtysh -c "show bgp ipv6" 2> /dev/null').rstrip()
1112 )
1113 # Remove summary line (changed recently)
1114 actual = re.sub(r"Total number.*", "", actual)
1115 actual = re.sub(r"Displayed.*", "", actual)
1116 actual = actual.rstrip()
1117 # Fix newlines (make them all the same)
1118 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
1119
1120 # Generate Diff
1121 diff = topotest.get_textdiff(
1122 actual,
1123 expected,
1124 title1="actual SHOW BGP IPv6",
1125 title2="expected SHOW BGP IPv6",
1126 )
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:
1136 resultstr = "No template matched.\n"
1137 for f in diffresult.iterkeys():
1138 resultstr += "template %s: r%s failed SHOW BGP IPv6 check:\n%s\n" % (
1139 f,
1140 i,
1141 diffresult[f],
1142 )
1143 raise AssertionError(
1144 "SHOW BGP IPv6 failed for router r%s:\n%s" % (i, resultstr)
1145 )
1146
1147 # Make sure that all daemons are running
1148 for i in range(1, 2):
1149 fatal_error = net["r%s" % i].checkRouterRunning()
1150 assert fatal_error == "", fatal_error
1151
1152 # For debugging after starting FRR daemons, uncomment the next line
1153 # CLI(net)
1154
1155
1156 def test_route_map():
1157 global fatal_error
1158 global net
1159
1160 if fatal_error != "":
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):
1169 refroutemap = "%s/r%s/show_route_map.ref" % (thisDir, i)
1170 if os.path.isfile(refroutemap):
1171 expected = open(refroutemap).read().rstrip()
1172 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
1173
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)
1178
1179 diff = topotest.get_textdiff(
1180 actual,
1181 expected,
1182 title1="actual show route-map",
1183 title2="expected show route-map",
1184 )
1185
1186 if diff:
1187 sys.stderr.write(
1188 "r%s failed show route-map command Check:\n%s\n" % (i, diff)
1189 )
1190 failures += 1
1191 else:
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)
1197
1198
1199 def test_nexthop_groups_with_route_maps():
1200 global fatal_error
1201 global net
1202
1203 # Skip if previous fatal error condition is raised
1204 if fatal_error != "":
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
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 )
1216
1217 ## Route-Map Proto Source
1218
1219 route_str = "2.2.2.1"
1220 src_str = "192.168.0.1"
1221
1222 net["r1"].cmd(
1223 'vtysh -c "c t" -c "route-map NH-SRC permit 111" -c "set src %s"' % src_str
1224 )
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"):
1233 output = net["r1"].cmd("ip route show %s/32" % route_str)
1234 match = re.search(r"src %s" % src_str, output)
1235 assert match is not None, "Route %s/32 not installed with src %s" % (
1236 route_str,
1237 src_str,
1238 )
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"')
1243 net["r1"].cmd(
1244 'vtysh -c "c t" -c "no route-map NH-SRC permit 111" -c "set src %s"' % src_str
1245 )
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
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 )
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
1263 net["r1"].cmd(
1264 'vtysh -c "sharp install routes %s nexthop-group test 1"' % permit_route_str
1265 )
1266
1267 verify_route_nexthop_group("%s/32" % permit_route_str)
1268
1269 # This route should be denied
1270 net["r1"].cmd(
1271 'vtysh -c "sharp install routes %s nexthop-group test 1"' % deny_route_str
1272 )
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"')
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
1295
1296 def test_nexthop_group_replace():
1297 global fatal_error
1298 global net
1299
1300 # Skip if previous fatal error condition is raised
1301 if fatal_error != "":
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
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 )
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
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 )
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
1328
1329 def test_mpls_interfaces():
1330 global fatal_error
1331 global net
1332
1333 # Skip if previous fatal error condition is raised
1334 if fatal_error != "":
1335 pytest.skip(fatal_error)
1336
1337 # Skip if no LDP installed or old kernel
1338 if net["r1"].daemon_available("ldpd") == False:
1339 pytest.skip("No MPLS or kernel < 4.5")
1340
1341 thisDir = os.path.dirname(os.path.realpath(__file__))
1342
1343 print("\n\n** Verifying MPLS Interfaces")
1344 print("******************************************\n")
1345 failures = 0
1346 for i in range(1, 2):
1347 refTableFile = "%s/r%s/show_mpls_ldp_interface.ref" % (thisDir, i)
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)
1352 expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
1353
1354 # Actual output from router
1355 actual = (
1356 net["r%s" % i]
1357 .cmd('vtysh -c "show mpls ldp interface" 2> /dev/null')
1358 .rstrip()
1359 )
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)
1363 actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
1364
1365 # Generate Diff
1366 diff = topotest.get_textdiff(
1367 actual,
1368 expected,
1369 title1="actual MPLS LDP interface status",
1370 title2="expected MPLS LDP interface status",
1371 )
1372
1373 # Empty string if it matches, otherwise diff contains unified diff
1374 if diff:
1375 sys.stderr.write(
1376 "r%s failed MPLS LDP Interface status Check:\n%s\n" % (i, diff)
1377 )
1378 failures += 1
1379 else:
1380 print("r%s ok" % i)
1381
1382 if failures > 0:
1383 fatal_error = "MPLS LDP Interface status failed"
1384
1385 assert (
1386 failures == 0
1387 ), "MPLS LDP Interface status failed for router r%s:\n%s" % (i, diff)
1388
1389 # Make sure that all daemons are running
1390 for i in range(1, 2):
1391 fatal_error = net["r%s" % i].checkRouterRunning()
1392 assert fatal_error == "", fatal_error
1393
1394 # For debugging after starting FRR daemons, uncomment the next line
1395 # CLI(net)
1396
1397
1398 def test_shutdown_check_stderr():
1399 global fatal_error
1400 global net
1401
1402 # Skip if previous fatal error condition is raised
1403 if fatal_error != "":
1404 pytest.skip(fatal_error)
1405
1406 print("\n\n** Verifying unexpected STDERR output from daemons")
1407 print("******************************************\n")
1408
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")
1414
1415 thisDir = os.path.dirname(os.path.realpath(__file__))
1416
1417 print("thisDir=" + thisDir)
1418
1419 net["r1"].stopRouter()
1420
1421 log = net["r1"].getStdErr("ripd")
1422 if log:
1423 print("\nRIPd StdErr Log:\n" + log)
1424 log = net["r1"].getStdErr("ripngd")
1425 if log:
1426 print("\nRIPngd StdErr Log:\n" + log)
1427 log = net["r1"].getStdErr("ospfd")
1428 if log:
1429 print("\nOSPFd StdErr Log:\n" + log)
1430 log = net["r1"].getStdErr("ospf6d")
1431 if log:
1432 print("\nOSPF6d StdErr Log:\n" + log)
1433 log = net["r1"].getStdErr("isisd")
1434 if log:
1435 print("\nISISd StdErr Log:\n" + log)
1436 log = net["r1"].getStdErr("bgpd")
1437 if log:
1438 print("\nBGPd StdErr Log:\n" + log)
1439
1440 log = net["r1"].getStdErr("nhrpd")
1441 if log:
1442 print("\nNHRPd StdErr Log:\n" + log)
1443
1444 log = net["r1"].getStdErr("pbrd")
1445 if log:
1446 print("\nPBRd StdErr Log:\n" + log)
1447
1448 log = net["r1"].getStdErr("babeld")
1449 if log:
1450 print("\nBABELd StdErr Log:\n" + log)
1451
1452 if net["r1"].daemon_available("ldpd"):
1453 log = net["r1"].getStdErr("ldpd")
1454 if log:
1455 print("\nLDPd StdErr Log:\n" + log)
1456 log = net["r1"].getStdErr("zebra")
1457 if log:
1458 print("\nZebra StdErr Log:\n" + log)
1459
1460
1461 def test_shutdown_check_memleak():
1462 global fatal_error
1463 global net
1464
1465 # Skip if previous fatal error condition is raised
1466 if fatal_error != "":
1467 pytest.skip(fatal_error)
1468
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
1475 thisDir = os.path.dirname(os.path.realpath(__file__))
1476
1477 for i in range(1, 2):
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 )
1482
1483
1484 if __name__ == "__main__":
1485
1486 setLogLevel("info")
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)