]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/isis_rlfa_topo1/test_isis_rlfa_topo1.py
2 # SPDX-License-Identifier: ISC
5 # test_isis_rlfa_topo1.py
6 # Part of NetDEF Topology Tests
8 # Copyright (c) 2020 by
9 # Network Device Education Foundation, Inc. ("NetDEF")
13 test_isis_rlfa_topo1.py:
15 +---------+ +---------+
18 | +---------------------+ |
20 +---+-----+ +------+--+
24 +---+-----+ +------+--+
29 +---+-----+ +------+--+
33 +---+-----+ +------+--+
38 +---+-----+ +------+--+
42 +---+-----+ +------+--+
45 | +---------------------+ |
47 +---------+ +---------+
55 from functools
import partial
57 # Save the Current Working Directory to find configuration files.
58 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
59 sys
.path
.append(os
.path
.join(CWD
, "../"))
61 # pylint: disable=C0413
62 # Import topogen and topotest helpers
63 from lib
import topotest
64 from lib
.topogen
import Topogen
, TopoRouter
, get_topogen
65 from lib
.topolog
import logger
67 # Required to instantiate the topology builder class.
69 pytestmark
= [pytest
.mark
.isisd
, pytest
.mark
.ldpd
]
71 # Global multi-dimensional dictionary containing all expected outputs
81 for router
in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7", "rt8"]:
82 tgen
.add_router(router
)
87 switch
= tgen
.add_switch("s1")
88 switch
.add_link(tgen
.gears
["rt1"], nodeif
="eth-rt2")
89 switch
.add_link(tgen
.gears
["rt2"], nodeif
="eth-rt1")
90 switch
= tgen
.add_switch("s2")
91 switch
.add_link(tgen
.gears
["rt1"], nodeif
="eth-rt3")
92 switch
.add_link(tgen
.gears
["rt3"], nodeif
="eth-rt1")
93 switch
= tgen
.add_switch("s3")
94 switch
.add_link(tgen
.gears
["rt2"], nodeif
="eth-rt4")
95 switch
.add_link(tgen
.gears
["rt4"], nodeif
="eth-rt2")
96 switch
= tgen
.add_switch("s4")
97 switch
.add_link(tgen
.gears
["rt3"], nodeif
="eth-rt5")
98 switch
.add_link(tgen
.gears
["rt5"], nodeif
="eth-rt3")
99 switch
= tgen
.add_switch("s5")
100 switch
.add_link(tgen
.gears
["rt4"], nodeif
="eth-rt6")
101 switch
.add_link(tgen
.gears
["rt6"], nodeif
="eth-rt4")
102 switch
= tgen
.add_switch("s6")
103 switch
.add_link(tgen
.gears
["rt5"], nodeif
="eth-rt7")
104 switch
.add_link(tgen
.gears
["rt7"], nodeif
="eth-rt5")
105 switch
= tgen
.add_switch("s7")
106 switch
.add_link(tgen
.gears
["rt6"], nodeif
="eth-rt8")
107 switch
.add_link(tgen
.gears
["rt8"], nodeif
="eth-rt6")
108 switch
= tgen
.add_switch("s8")
109 switch
.add_link(tgen
.gears
["rt7"], nodeif
="eth-rt8")
110 switch
.add_link(tgen
.gears
["rt8"], nodeif
="eth-rt7")
113 # Populate multi-dimensional dictionary containing all expected outputs
117 "show_ipv6_route.ref",
118 "show_yang_interface_isis_adjacencies.ref",
120 for rname
in ["rt1"]:
122 for step
in range(1, 10 + 1):
123 outputs
[rname
][step
] = {}
126 # Get snapshots relative to the expected initial network convergence
127 filename
= "{}/{}/step{}/{}".format(CWD
, rname
, step
, file)
128 outputs
[rname
][step
][file] = open(filename
).read()
130 if file == "show_yang_interface_isis_adjacencies.ref":
133 # Get diff relative to the previous step
134 filename
= "{}/{}/step{}/{}.diff".format(CWD
, rname
, step
, file)
136 # Create temporary files in order to apply the diff
137 f_in
= tempfile
.NamedTemporaryFile(mode
="w")
138 f_in
.write(outputs
[rname
][step
- 1][file])
140 f_out
= tempfile
.NamedTemporaryFile(mode
="r")
142 "patch -s -o %s %s %s" % (f_out
.name
, f_in
.name
, filename
)
145 # Store the updated snapshot and remove the temporary files
146 outputs
[rname
][step
][file] = open(f_out
.name
).read()
151 def setup_module(mod
):
152 "Sets up the pytest environment"
153 tgen
= Topogen(build_topo
, mod
.__name
__)
154 tgen
.start_topology()
156 router_list
= tgen
.routers()
158 # For all registered routers, load the zebra configuration file
159 for rname
, router
in router_list
.items():
161 TopoRouter
.RD_ZEBRA
, os
.path
.join(CWD
, "{}/zebra.conf".format(rname
))
164 TopoRouter
.RD_ISIS
, os
.path
.join(CWD
, "{}/isisd.conf".format(rname
))
167 TopoRouter
.RD_LDP
, os
.path
.join(CWD
, "{}/ldpd.conf".format(rname
))
173 def teardown_module(mod
):
174 "Teardown the pytest environment"
177 # This function tears down the whole topology.
181 def router_compare_json_output(rname
, command
, reference
):
182 "Compare router JSON output"
184 logger
.info('Comparing router "%s" "%s" output', rname
, command
)
187 expected
= json
.loads(reference
)
189 # Run test function until we get an result. Wait at most 60 seconds.
190 test_func
= partial(topotest
.router_json_cmp
, tgen
.gears
[rname
], command
, expected
)
191 _
, diff
= topotest
.run_and_expect(test_func
, None, count
=120, wait
=0.5)
192 assertmsg
= '"{}" JSON output mismatches the expected result'.format(rname
)
193 assert diff
is None, assertmsg
199 # Test initial network convergence
201 def test_isis_adjacencies_step1():
202 logger
.info("Test (step 1): check IS-IS adjacencies")
205 # Skip if previous fatal error condition is raised
206 if tgen
.routers_have_failure():
207 pytest
.skip(tgen
.errors
)
209 for rname
in ["rt1"]:
210 router_compare_json_output(
212 "show yang operational-data /frr-interface:lib isisd",
213 outputs
[rname
][1]["show_yang_interface_isis_adjacencies.ref"],
217 def test_rib_ipv4_step1():
218 logger
.info("Test (step 1): verify IPv4 RIB")
221 # Skip if previous fatal error condition is raised
222 if tgen
.routers_have_failure():
223 pytest
.skip(tgen
.errors
)
225 for rname
in ["rt1"]:
226 router_compare_json_output(
227 rname
, "show ip route isis json", outputs
[rname
][1]["show_ip_route.ref"]
231 def test_rib_ipv6_step1():
232 logger
.info("Test (step 1): verify IPv6 RIB")
235 # Skip if previous fatal error condition is raised
236 if tgen
.routers_have_failure():
237 pytest
.skip(tgen
.errors
)
239 for rname
in ["rt1"]:
240 router_compare_json_output(
241 rname
, "show ipv6 route isis json", outputs
[rname
][1]["show_ipv6_route.ref"]
249 # -Configure rt8 (rt1's PQ router) to not accept targeted hello messages
252 # -All rt1 backup routes should be uninstalled
254 def test_rib_ipv4_step2():
255 logger
.info("Test (step 2): verify IPv4 RIB")
258 # Skip if previous fatal error condition is raised
259 if tgen
.routers_have_failure():
260 pytest
.skip(tgen
.errors
)
262 logger
.info("Configuring rt8 to not accept targeted hello messages")
264 'vtysh -c "conf t" -c "mpls ldp" -c "address-family ipv4" -c "no discovery targeted-hello accept"'
267 for rname
in ["rt1"]:
268 router_compare_json_output(
269 rname
, "show ip route isis json", outputs
[rname
][2]["show_ip_route.ref"]
273 def test_rib_ipv6_step2():
274 logger
.info("Test (step 2): verify IPv6 RIB")
277 # Skip if previous fatal error condition is raised
278 if tgen
.routers_have_failure():
279 pytest
.skip(tgen
.errors
)
281 for rname
in ["rt1"]:
282 router_compare_json_output(
283 rname
, "show ipv6 route isis json", outputs
[rname
][2]["show_ipv6_route.ref"]
291 # -Configure rt8 (rt1's PQ router) to accept targeted hello messages
294 # -All rt1 previously uninstalled backup routes should be reinstalled
296 def test_rib_ipv4_step3():
297 logger
.info("Test (step 3): verify IPv4 RIB")
300 # Skip if previous fatal error condition is raised
301 if tgen
.routers_have_failure():
302 pytest
.skip(tgen
.errors
)
304 logger
.info("Configuring rt8 to accept targeted hello messages")
306 'vtysh -c "conf t" -c "mpls ldp" -c "address-family ipv4" -c "discovery targeted-hello accept"'
309 for rname
in ["rt1"]:
310 router_compare_json_output(
311 rname
, "show ip route isis json", outputs
[rname
][3]["show_ip_route.ref"]
315 def test_rib_ipv6_step3():
316 logger
.info("Test (step 3): verify IPv6 RIB")
319 # Skip if previous fatal error condition is raised
320 if tgen
.routers_have_failure():
321 pytest
.skip(tgen
.errors
)
323 for rname
in ["rt1"]:
324 router_compare_json_output(
325 rname
, "show ipv6 route isis json", outputs
[rname
][3]["show_ipv6_route.ref"]
333 # -Disable RLFA on rt1's eth-rt2 interface
336 # -All non-ECMP routes whose primary nexthop is eth-rt2 should lose their backup nexthops
338 def test_rib_ipv4_step4():
339 logger
.info("Test (step 4): verify IPv4 RIB")
342 # Skip if previous fatal error condition is raised
343 if tgen
.routers_have_failure():
344 pytest
.skip(tgen
.errors
)
346 logger
.info("Disabling RLFA on rt1's eth-rt2 interface")
348 'vtysh -c "conf t" -c "interface eth-rt2" -c "no isis fast-reroute remote-lfa tunnel mpls-ldp"'
351 for rname
in ["rt1"]:
352 router_compare_json_output(
353 rname
, "show ip route isis json", outputs
[rname
][4]["show_ip_route.ref"]
357 def test_rib_ipv6_step4():
358 logger
.info("Test (step 4): verify IPv6 RIB")
361 # Skip if previous fatal error condition is raised
362 if tgen
.routers_have_failure():
363 pytest
.skip(tgen
.errors
)
365 for rname
in ["rt1"]:
366 router_compare_json_output(
367 rname
, "show ipv6 route isis json", outputs
[rname
][4]["show_ipv6_route.ref"]
375 # -Disable RLFA on rt1's eth-rt3 interface
378 # -All non-ECMP routes whose primary nexthop is eth-rt3 should lose their backup nexthops
380 def test_rib_ipv4_step5():
381 logger
.info("Test (step 5): verify IPv4 RIB")
384 # Skip if previous fatal error condition is raised
385 if tgen
.routers_have_failure():
386 pytest
.skip(tgen
.errors
)
388 logger
.info("Disabling RLFA on rt1's eth-rt3 interface")
390 'vtysh -c "conf t" -c "interface eth-rt3" -c "no isis fast-reroute remote-lfa tunnel mpls-ldp"'
393 for rname
in ["rt1"]:
394 router_compare_json_output(
395 rname
, "show ip route isis json", outputs
[rname
][5]["show_ip_route.ref"]
399 def test_rib_ipv6_step5():
400 logger
.info("Test (step 5): verify IPv6 RIB")
403 # Skip if previous fatal error condition is raised
404 if tgen
.routers_have_failure():
405 pytest
.skip(tgen
.errors
)
407 for rname
in ["rt1"]:
408 router_compare_json_output(
409 rname
, "show ipv6 route isis json", outputs
[rname
][5]["show_ipv6_route.ref"]
417 # -Re-enable RLFA on rt1's eth-rt2 and eth-rt3 interfaces
420 # -Revert changes from the previous two steps (reinstall all backup routes)
422 def test_rib_ipv4_step6():
423 logger
.info("Test (step 6): verify IPv4 RIB")
426 # Skip if previous fatal error condition is raised
427 if tgen
.routers_have_failure():
428 pytest
.skip(tgen
.errors
)
430 logger
.info("Re-enabling RLFA on rt1's eth-rt2 and eth-rt3 interfaces")
432 'vtysh -c "conf t" -c "interface eth-rt2" -c "isis fast-reroute remote-lfa tunnel mpls-ldp"'
435 'vtysh -c "conf t" -c "interface eth-rt3" -c "isis fast-reroute remote-lfa tunnel mpls-ldp"'
438 for rname
in ["rt1"]:
439 router_compare_json_output(
440 rname
, "show ip route isis json", outputs
[rname
][6]["show_ip_route.ref"]
444 def test_rib_ipv6_step6():
445 logger
.info("Test (step 6): verify IPv6 RIB")
448 # Skip if previous fatal error condition is raised
449 if tgen
.routers_have_failure():
450 pytest
.skip(tgen
.errors
)
452 for rname
in ["rt1"]:
453 router_compare_json_output(
454 rname
, "show ipv6 route isis json", outputs
[rname
][6]["show_ipv6_route.ref"]
462 # -Configure a PQ node prefix-list filter
465 # -All backup routes should be uninstalled
467 def test_rib_ipv4_step7():
468 logger
.info("Test (step 7): verify IPv4 RIB")
471 # Skip if previous fatal error condition is raised
472 if tgen
.routers_have_failure():
473 pytest
.skip(tgen
.errors
)
475 logger
.info("Configuring a PQ node prefix-list filter")
477 'vtysh -c "conf t" -c "router isis 1" -c "fast-reroute remote-lfa prefix-list PLIST"'
480 for rname
in ["rt1"]:
481 router_compare_json_output(
482 rname
, "show ip route isis json", outputs
[rname
][7]["show_ip_route.ref"]
486 def test_rib_ipv6_step7():
487 logger
.info("Test (step 7): verify IPv6 RIB")
490 # Skip if previous fatal error condition is raised
491 if tgen
.routers_have_failure():
492 pytest
.skip(tgen
.errors
)
494 for rname
in ["rt1"]:
495 router_compare_json_output(
496 rname
, "show ipv6 route isis json", outputs
[rname
][7]["show_ipv6_route.ref"]
504 # -Configure a prefix-list allowing rt8 as a PQ node
507 # -All backup routes should be installed again
509 def test_rib_ipv4_step8():
510 logger
.info("Test (step 8): verify IPv4 RIB")
513 # Skip if previous fatal error condition is raised
514 if tgen
.routers_have_failure():
515 pytest
.skip(tgen
.errors
)
517 logger
.info("Configuring a prefix-list allowing rt8 as a PQ node")
519 'vtysh -c "conf t" -c "ip prefix-list PLIST seq 5 permit 10.0.255.8/32"'
522 for rname
in ["rt1"]:
523 router_compare_json_output(
524 rname
, "show ip route isis json", outputs
[rname
][8]["show_ip_route.ref"]
528 def test_rib_ipv6_step8():
529 logger
.info("Test (step 8): verify IPv6 RIB")
532 # Skip if previous fatal error condition is raised
533 if tgen
.routers_have_failure():
534 pytest
.skip(tgen
.errors
)
536 for rname
in ["rt1"]:
537 router_compare_json_output(
538 rname
, "show ipv6 route isis json", outputs
[rname
][8]["show_ipv6_route.ref"]
546 # -Change the maximum metric up to the PQ node to 30 on the eth-rt2 interface
549 # -All non-ECMP routes whose primary nexthop is eth-rt2 should lose their backup nexthops
551 def test_rib_ipv4_step9():
552 logger
.info("Test (step 9): verify IPv4 RIB")
555 # Skip if previous fatal error condition is raised
556 if tgen
.routers_have_failure():
557 pytest
.skip(tgen
.errors
)
560 "Changing the maximum metric up to the PQ node to 30 on the eth-rt2 interface"
563 'vtysh -c "conf t" -c "interface eth-rt2" -c "isis fast-reroute remote-lfa maximum-metric 30"'
566 for rname
in ["rt1"]:
567 router_compare_json_output(
568 rname
, "show ip route isis json", outputs
[rname
][9]["show_ip_route.ref"]
572 def test_rib_ipv6_step9():
573 logger
.info("Test (step 9): verify IPv6 RIB")
576 # Skip if previous fatal error condition is raised
577 if tgen
.routers_have_failure():
578 pytest
.skip(tgen
.errors
)
580 for rname
in ["rt1"]:
581 router_compare_json_output(
582 rname
, "show ipv6 route isis json", outputs
[rname
][9]["show_ipv6_route.ref"]
590 # -Change the maximum metric up to the PQ node to 40 on the eth-rt2 interface
593 # -All non-ECMP routes whose primary nexthop is eth-rt2 should recover their backup nexthops
595 def test_rib_ipv4_step10():
596 logger
.info("Test (step 10): verify IPv4 RIB")
599 # Skip if previous fatal error condition is raised
600 if tgen
.routers_have_failure():
601 pytest
.skip(tgen
.errors
)
604 "Changing the maximum metric up to the PQ node to 40 on the eth-rt2 interface"
607 'vtysh -c "conf t" -c "interface eth-rt2" -c "isis fast-reroute remote-lfa maximum-metric 40"'
610 for rname
in ["rt1"]:
611 router_compare_json_output(
612 rname
, "show ip route isis json", outputs
[rname
][10]["show_ip_route.ref"]
616 def test_rib_ipv6_step10():
617 logger
.info("Test (step 10): verify IPv6 RIB")
620 # Skip if previous fatal error condition is raised
621 if tgen
.routers_have_failure():
622 pytest
.skip(tgen
.errors
)
624 for rname
in ["rt1"]:
625 router_compare_json_output(
627 "show ipv6 route isis json",
628 outputs
[rname
][10]["show_ipv6_route.ref"],
632 # Memory leak test template
633 def test_memory_leak():
634 "Run the memory leak test and report results."
636 if not tgen
.is_memleak_enabled():
637 pytest
.skip("Memory leak test/report is disabled")
639 tgen
.report_memory_leaks()
642 if __name__
== "__main__":
643 args
= ["-s"] + sys
.argv
[1:]
644 sys
.exit(pytest
.main(args
))