]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/isis_lfa_topo1/test_isis_lfa_topo1.py
4 # test_isis_tilfa_topo1.py
5 # Part of NetDEF Topology Tests
7 # Copyright (c) 2020 by
8 # Network Device Education Foundation, Inc. ("NetDEF")
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
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
26 test_isis_lfa_topo1.py:
30 +--------------------------------+ RT1 +-------------------------------+
31 | +-------------+ +-------------+ |
37 +----+----+ +----+----+ +----+----+ +----+----+ +----+----+
39 | RT2 | 5 | RT3 | | RT4 | | RT5 | | RT6 |
40 | +--------+ | | | | | | |
42 +----+----+ +----+----+ +----+----+ +----+----+ +----+----+
48 | +-------------+ RT7 +-------------+ |
49 +--------------------------------+ +-------------------------------+
60 from functools
import partial
62 # Save the Current Working Directory to find configuration files.
63 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
64 sys
.path
.append(os
.path
.join(CWD
, "../"))
66 # pylint: disable=C0413
67 # Import topogen and topotest helpers
68 from lib
import topotest
69 from lib
.topogen
import Topogen
, TopoRouter
, get_topogen
70 from lib
.topolog
import logger
72 # Required to instantiate the topology builder class.
74 pytestmark
= [pytest
.mark
.isisd
]
76 # Global multi-dimensional dictionary containing all expected outputs
86 for router
in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7"]:
87 tgen
.add_router(router
)
92 switch
= tgen
.add_switch("s1")
93 switch
.add_link(tgen
.gears
["rt1"], nodeif
="eth-rt2")
94 switch
.add_link(tgen
.gears
["rt2"], nodeif
="eth-rt1")
95 switch
= tgen
.add_switch("s2")
96 switch
.add_link(tgen
.gears
["rt2"], nodeif
="eth-rt3")
97 switch
.add_link(tgen
.gears
["rt3"], nodeif
="eth-rt2")
98 switch
= tgen
.add_switch("s3")
99 switch
.add_link(tgen
.gears
["rt1"], nodeif
="eth-rt3")
100 switch
.add_link(tgen
.gears
["rt3"], nodeif
="eth-rt1")
101 switch
= tgen
.add_switch("s4")
102 switch
.add_link(tgen
.gears
["rt1"], nodeif
="eth-rt4")
103 switch
.add_link(tgen
.gears
["rt4"], nodeif
="eth-rt1")
104 switch
= tgen
.add_switch("s5")
105 switch
.add_link(tgen
.gears
["rt1"], nodeif
="eth-rt5")
106 switch
.add_link(tgen
.gears
["rt5"], nodeif
="eth-rt1")
107 switch
= tgen
.add_switch("s6")
108 switch
.add_link(tgen
.gears
["rt1"], nodeif
="eth-rt6")
109 switch
.add_link(tgen
.gears
["rt6"], nodeif
="eth-rt1")
110 switch
= tgen
.add_switch("s7")
111 switch
.add_link(tgen
.gears
["rt2"], nodeif
="eth-rt7")
112 switch
.add_link(tgen
.gears
["rt7"], nodeif
="eth-rt2")
113 switch
= tgen
.add_switch("s8")
114 switch
.add_link(tgen
.gears
["rt3"], nodeif
="eth-rt7")
115 switch
.add_link(tgen
.gears
["rt7"], nodeif
="eth-rt3")
116 switch
= tgen
.add_switch("s9")
117 switch
.add_link(tgen
.gears
["rt4"], nodeif
="eth-rt7")
118 switch
.add_link(tgen
.gears
["rt7"], nodeif
="eth-rt4")
119 switch
= tgen
.add_switch("s10")
120 switch
.add_link(tgen
.gears
["rt5"], nodeif
="eth-rt7")
121 switch
.add_link(tgen
.gears
["rt7"], nodeif
="eth-rt5")
122 switch
= tgen
.add_switch("s11")
123 switch
.add_link(tgen
.gears
["rt6"], nodeif
="eth-rt7")
124 switch
.add_link(tgen
.gears
["rt7"], nodeif
="eth-rt6")
127 # Populate multi-dimensional dictionary containing all expected outputs
129 files
= ["show_ipv6_route.ref", "show_yang_interface_isis_adjacencies.ref"]
130 for rname
in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7"]:
132 for step
in range(1, 16 + 1):
133 outputs
[rname
][step
] = {}
136 # Get snapshots relative to the expected initial network convergence
137 filename
= "{}/{}/step{}/{}".format(CWD
, rname
, step
, file)
138 outputs
[rname
][step
][file] = open(filename
).read()
142 if file == "show_yang_interface_isis_adjacencies.ref":
145 # Get diff relative to the previous step
146 filename
= "{}/{}/step{}/{}.diff".format(CWD
, rname
, step
, file)
148 # Create temporary files in order to apply the diff
149 f_in
= tempfile
.NamedTemporaryFile(mode
="w")
150 f_in
.write(outputs
[rname
][step
- 1][file])
152 f_out
= tempfile
.NamedTemporaryFile(mode
="r")
154 "patch -s -o %s %s %s" % (f_out
.name
, f_in
.name
, filename
)
157 # Store the updated snapshot and remove the temporary files
158 outputs
[rname
][step
][file] = open(f_out
.name
).read()
163 def setup_module(mod
):
164 "Sets up the pytest environment"
165 tgen
= Topogen(build_topo
, mod
.__name
__)
166 tgen
.start_topology()
168 router_list
= tgen
.routers()
170 # For all registered routers, load the zebra configuration file
171 for rname
, router
in router_list
.items():
173 TopoRouter
.RD_ZEBRA
, os
.path
.join(CWD
, "{}/zebra.conf".format(rname
))
176 TopoRouter
.RD_ISIS
, os
.path
.join(CWD
, "{}/isisd.conf".format(rname
))
179 TopoRouter
.RD_BFD
, os
.path
.join(CWD
, "/dev/null".format(rname
))
185 def teardown_module(mod
):
186 "Teardown the pytest environment"
189 # This function tears down the whole topology.
193 def router_compare_json_output(rname
, command
, reference
, wait
=0.5, count
=120):
194 "Compare router JSON output"
196 logger
.info('Comparing router "%s" "%s" output', rname
, command
)
199 expected
= json
.loads(reference
)
201 # Run test function until we get an result. Wait at most 60 seconds.
202 test_func
= partial(topotest
.router_json_cmp
, tgen
.gears
[rname
], command
, expected
)
203 _
, diff
= topotest
.run_and_expect(test_func
, None, count
=count
, wait
=wait
)
204 assertmsg
= '"{}" JSON output mismatches the expected result'.format(rname
)
205 assert diff
is None, assertmsg
211 # Test initial network convergence
213 def test_isis_adjacencies_step1():
214 logger
.info("Test (step 1): check IS-IS adjacencies")
217 # Skip if previous fatal error condition is raised
218 if tgen
.routers_have_failure():
219 pytest
.skip(tgen
.errors
)
221 for rname
in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7"]:
222 router_compare_json_output(
224 "show yang operational-data /frr-interface:lib isisd",
225 outputs
[rname
][1]["show_yang_interface_isis_adjacencies.ref"],
229 def test_rib_ipv6_step1():
230 logger
.info("Test (step 1): verify IPv6 RIB")
233 # Skip if previous fatal error condition is raised
234 if tgen
.routers_have_failure():
235 pytest
.skip(tgen
.errors
)
237 for rname
in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "rt7"]:
238 router_compare_json_output(
239 rname
, "show ipv6 route isis json", outputs
[rname
][1]["show_ipv6_route.ref"]
247 # -Disable LFA protection on all interfaces
250 # -rt1 should uninstall all backup nexthops from all routes
252 def test_rib_ipv6_step2():
253 logger
.info("Test (step 2): verify IPv6 RIB")
256 # Skip if previous fatal error condition is raised
257 if tgen
.routers_have_failure():
258 pytest
.skip(tgen
.errors
)
260 logger
.info("Disabling LFA protection on all rt1 interfaces")
262 'vtysh -c "conf t" -c "interface eth-rt2" -c "no isis fast-reroute lfa"'
265 'vtysh -c "conf t" -c "interface eth-rt3" -c "no isis fast-reroute lfa"'
268 'vtysh -c "conf t" -c "interface eth-rt4" -c "no isis fast-reroute lfa"'
271 'vtysh -c "conf t" -c "interface eth-rt5" -c "no isis fast-reroute lfa"'
274 'vtysh -c "conf t" -c "interface eth-rt6" -c "no isis fast-reroute lfa"'
277 for rname
in ["rt1"]:
278 router_compare_json_output(
279 rname
, "show ipv6 route isis json", outputs
[rname
][2]["show_ipv6_route.ref"]
287 # -Re-enable LFA protection on all interfaces
290 # -Revert changes from the previous step
292 def test_rib_ipv6_step3():
293 logger
.info("Test (step 3): verify IPv6 RIB")
296 # Skip if previous fatal error condition is raised
297 if tgen
.routers_have_failure():
298 pytest
.skip(tgen
.errors
)
300 logger
.info("Re-enabling LFA protection on all rt1 interfaces")
302 'vtysh -c "conf t" -c "interface eth-rt2" -c "isis fast-reroute lfa"'
305 'vtysh -c "conf t" -c "interface eth-rt3" -c "isis fast-reroute lfa"'
308 'vtysh -c "conf t" -c "interface eth-rt4" -c "isis fast-reroute lfa"'
311 'vtysh -c "conf t" -c "interface eth-rt5" -c "isis fast-reroute lfa"'
314 'vtysh -c "conf t" -c "interface eth-rt6" -c "isis fast-reroute lfa"'
317 for rname
in ["rt1"]:
318 router_compare_json_output(
319 rname
, "show ipv6 route isis json", outputs
[rname
][3]["show_ipv6_route.ref"]
327 # -Disable LFA load-sharing
330 # -rt1 should use at most one backup nexthop for each route
332 def test_rib_ipv6_step4():
333 logger
.info("Test (step 4): verify IPv6 RIB")
336 # Skip if previous fatal error condition is raised
337 if tgen
.routers_have_failure():
338 pytest
.skip(tgen
.errors
)
340 logger
.info("Disabling LFA load-sharing on rt1")
342 'vtysh -c "conf t" -c "router isis 1" -c "fast-reroute load-sharing disable"'
345 for rname
in ["rt1"]:
346 router_compare_json_output(
347 rname
, "show ipv6 route isis json", outputs
[rname
][4]["show_ipv6_route.ref"]
355 # -Re-enable LFA load-sharing
358 # -Revert changes from the previous step
360 def test_rib_ipv6_step5():
361 logger
.info("Test (step 5): verify IPv6 RIB")
364 # Skip if previous fatal error condition is raised
365 if tgen
.routers_have_failure():
366 pytest
.skip(tgen
.errors
)
368 logger
.info("Re-enabling LFA load-sharing on rt1")
370 'vtysh -c "conf t" -c "router isis 1" -c "no fast-reroute load-sharing disable"'
373 for rname
in ["rt1"]:
374 router_compare_json_output(
375 rname
, "show ipv6 route isis json", outputs
[rname
][5]["show_ipv6_route.ref"]
383 # -Limit backup computation to critical priority prefixes only
386 # -rt1 should uninstall all backup nexthops from all routes
388 def test_rib_ipv6_step6():
389 logger
.info("Test (step 6): verify IPv6 RIB")
392 # Skip if previous fatal error condition is raised
393 if tgen
.routers_have_failure():
394 pytest
.skip(tgen
.errors
)
396 logger
.info("Limiting backup computation to critical priority prefixes only")
398 'vtysh -c "conf t" -c "router isis 1" -c "fast-reroute priority-limit critical"'
401 for rname
in ["rt1"]:
402 router_compare_json_output(
403 rname
, "show ipv6 route isis json", outputs
[rname
][6]["show_ipv6_route.ref"]
411 # -Configure a prefix priority list to classify rt7's loopback as a
412 # critical-priority prefix
415 # -rt1 should install backup nexthops for rt7's loopback route.
417 def test_rib_ipv6_step7():
418 logger
.info("Test (step 7): verify IPv6 RIB")
421 # Skip if previous fatal error condition is raised
422 if tgen
.routers_have_failure():
423 pytest
.skip(tgen
.errors
)
425 logger
.info("Configuring a prefix priority list")
427 'vtysh -c "conf t" -c "router isis 1" -c "spf prefix-priority critical CRITICAL_DESTINATIONS"'
430 'vtysh -c "conf t" -c "ipv6 access-list CRITICAL_DESTINATIONS seq 5 permit 2001:db8:1000::7/128"'
433 for rname
in ["rt1"]:
434 router_compare_json_output(
435 rname
, "show ipv6 route isis json", outputs
[rname
][7]["show_ipv6_route.ref"]
443 # -Revert previous changes related to prefix priorities
446 # -Revert changes from the previous two steps
448 def test_rib_ipv6_step8():
449 logger
.info("Test (step 8): verify IPv6 RIB")
452 # Skip if previous fatal error condition is raised
453 if tgen
.routers_have_failure():
454 pytest
.skip(tgen
.errors
)
456 logger
.info("Reverting previous changes related to prefix priorities")
458 'vtysh -c "conf t" -c "no ipv6 access-list CRITICAL_DESTINATIONS seq 5 permit 2001:db8:1000::7/128"'
461 'vtysh -c "conf t" -c "router isis 1" -c "no fast-reroute priority-limit critical"'
464 'vtysh -c "conf t" -c "router isis 1" -c "no spf prefix-priority critical CRITICAL_DESTINATIONS"'
467 for rname
in ["rt1"]:
468 router_compare_json_output(
469 rname
, "show ipv6 route isis json", outputs
[rname
][8]["show_ipv6_route.ref"]
477 # -Exclude eth-rt6 from LFA computation for eth-rt2's failure
480 # -Uninstall the eth-rt2 protecting backup nexthops that go through eth-rt6
482 def test_rib_ipv6_step9():
483 logger
.info("Test (step 9): verify IPv6 RIB")
486 # Skip if previous fatal error condition is raised
487 if tgen
.routers_have_failure():
488 pytest
.skip(tgen
.errors
)
490 logger
.info("Excluding eth-rt6 from LFA computation for eth-rt2's failure")
492 'vtysh -c "conf t" -c "interface eth-rt2" -c "isis fast-reroute lfa exclude interface eth-rt6"'
495 for rname
in ["rt1"]:
496 router_compare_json_output(
497 rname
, "show ipv6 route isis json", outputs
[rname
][9]["show_ipv6_route.ref"]
505 # -Remove exclusion of eth-rt6 from LFA computation for eth-rt2's failure
508 # -Revert changes from the previous step
510 def test_rib_ipv6_step10():
511 logger
.info("Test (step 10): verify IPv6 RIB")
514 # Skip if previous fatal error condition is raised
515 if tgen
.routers_have_failure():
516 pytest
.skip(tgen
.errors
)
519 "Removing exclusion of eth-rt6 from LFA computation for eth-rt2's failure"
522 'vtysh -c "conf t" -c "interface eth-rt2" -c "no isis fast-reroute lfa exclude interface eth-rt6"'
525 for rname
in ["rt1"]:
526 router_compare_json_output(
528 "show ipv6 route isis json",
529 outputs
[rname
][10]["show_ipv6_route.ref"],
537 # -Add LFA tiebreaker: prefer node protecting backup path
540 # -rt1 should prefer backup nexthops that provide node protection
542 def test_rib_ipv6_step11():
543 logger
.info("Test (step 11): verify IPv6 RIB")
546 # Skip if previous fatal error condition is raised
547 if tgen
.routers_have_failure():
548 pytest
.skip(tgen
.errors
)
550 logger
.info("Adding LFA tiebreaker: prefer node protecting backup path")
552 'vtysh -c "conf t" -c "router isis 1" -c "fast-reroute lfa tiebreaker node-protecting index 10"'
555 for rname
in ["rt1"]:
556 router_compare_json_output(
558 "show ipv6 route isis json",
559 outputs
[rname
][11]["show_ipv6_route.ref"],
567 # -Add LFA tiebreaker: prefer backup path via downstream node
570 # -rt1 should prefer backup nexthops that satisfy the downstream condition
572 def test_rib_ipv6_step12():
573 logger
.info("Test (step 12): verify IPv6 RIB")
576 # Skip if previous fatal error condition is raised
577 if tgen
.routers_have_failure():
578 pytest
.skip(tgen
.errors
)
580 logger
.info("Adding LFA tiebreaker: prefer backup path via downstream node")
582 'vtysh -c "conf t" -c "router isis 1" -c "fast-reroute lfa tiebreaker downstream index 20"'
585 for rname
in ["rt1"]:
586 router_compare_json_output(
588 "show ipv6 route isis json",
589 outputs
[rname
][12]["show_ipv6_route.ref"],
597 # -Add LFA tiebreaker: prefer backup path with lowest total metric
600 # -rt1 should prefer backup nexthops that have the best metric
602 def test_rib_ipv6_step13():
603 logger
.info("Test (step 13): verify IPv6 RIB")
606 # Skip if previous fatal error condition is raised
607 if tgen
.routers_have_failure():
608 pytest
.skip(tgen
.errors
)
610 logger
.info("Adding LFA tiebreaker: prefer backup path with lowest total metric")
612 'vtysh -c "conf t" -c "router isis 1" -c "fast-reroute lfa tiebreaker lowest-backup-metric index 30"'
615 for rname
in ["rt1"]:
616 router_compare_json_output(
618 "show ipv6 route isis json",
619 outputs
[rname
][13]["show_ipv6_route.ref"],
627 # - Setting spf-delay-ietf init-delay of 15s
630 # - No routing table change
631 # - At the end of test, SPF reacts to a failure in 15s
633 def test_rib_ipv6_step14():
634 logger
.info("Test (step 14): verify IPv6 RIB")
637 # Skip if previous fatal error condition is raised
638 if tgen
.routers_have_failure():
639 pytest
.skip(tgen
.errors
)
641 logger
.info("Setting spf-delay-ietf init-delay of 15s")
643 'vtysh -c "conf t" -c "router isis 1" -c "spf-delay-ietf init-delay 15000 short-delay 0 long-delay 0 holddown 0 time-to-learn 0"'
646 for rname
in ["rt1"]:
647 router_compare_json_output(
649 "show ipv6 route isis json",
650 outputs
[rname
][14]["show_ipv6_route.ref"],
658 # - shut the eth-rt2 interface on rt1
661 # - Route switchover of routes via eth-rt2
663 def test_rib_ipv6_step15():
664 logger
.info("Test (step 15): verify IPv6 RIB")
667 # Skip if previous fatal error condition is raised
668 if tgen
.routers_have_failure():
669 pytest
.skip(tgen
.errors
)
671 logger
.info("Shut the interface to rt2 from the switch side and check fast-reroute")
672 tgen
.net
.cmd_raises("ip link set %s down" % tgen
.net
["s1"].intfs
[0])
674 for rname
in ["rt1"]:
675 router_compare_json_output(
677 "show ipv6 route isis json",
678 outputs
[rname
][15]["show_ipv6_route.ref"],
687 # Action(s): wait for the convergence and SPF computation on rt1
690 # - convergence of IPv6 RIB
692 def test_rib_ipv6_step16():
693 logger
.info("Test (step 16): verify IPv6 RIB")
696 # Skip if previous fatal error condition is raised
697 if tgen
.routers_have_failure():
698 pytest
.skip(tgen
.errors
)
700 logger
.info("Check SPF convergence")
702 for rname
in ["rt1"]:
703 router_compare_json_output(
705 "show ipv6 route isis json",
706 outputs
[rname
][16]["show_ipv6_route.ref"],
714 # - Unshut the interface to rt2 from the switch sid
717 # - The routing table converges
719 def test_rib_ipv6_step17():
720 logger
.info("Test (step 17): verify IPv6 RIB")
723 # Skip if previous fatal error condition is raised
724 if tgen
.routers_have_failure():
725 pytest
.skip(tgen
.errors
)
729 logger
.info("Unsetting spf-delay-ietf init-delay of 15s")
730 tgen
.net
[rname
].cmd('vtysh -c "conf t" -c "router isis 1" -c "no spf-delay-ietf"')
733 "Unshut the interface to rt2 from the switch side and check fast-reroute"
735 tgen
.net
.cmd_raises("ip link set %s up" % tgen
.net
["s1"].intfs
[0])
737 logger
.info("Setting spf-delay-ietf init-delay of 15s")
739 'vtysh -c "conf t" -c "router isis 1" -c "spf-delay-ietf init-delay 15000 short-delay 0 long-delay 0 holddown 0 time-to-learn 0"'
742 router_compare_json_output(
744 "show ipv6 route isis json",
745 outputs
[rname
][14]["show_ipv6_route.ref"],
753 # - drop traffic between rt1 and rt2 by shutting down the bridge between
754 # the routers. Interfaces on rt1 and rt2 stay up.
758 # - Route switchover of routes via eth-rt2
760 def test_rib_ipv6_step18():
761 def _rt2_neigh_down(router
):
762 output
= json
.loads(router
.vtysh_cmd("show isis neighbor rt2 json"))
782 "topo-0":"ipv6-unicast"
784 "snpa":"2020.2020.2020",
789 "ipv6":"fe80::ac19:a8ff:fee5:f48f"
833 return topotest
.json_cmp(output
, expected
, exact
=True)
835 logger
.info("Test (step 18): verify IPv6 RIB")
838 # Skip if previous fatal error condition is raised
839 if tgen
.routers_have_failure():
840 pytest
.skip(tgen
.errors
)
842 logger
.info("Drop traffic between rt1 and rt2")
843 tgen
.net
.cmd_raises("ip link set s1 down")
846 router
= tgen
.gears
[rname
]
847 test_func
= partial(_rt2_neigh_down
, router
)
848 success
, result
= topotest
.run_and_expect(test_func
, None, count
=200, wait
=0.05)
849 assert result
is None, 'rt2 neighbor is still present on "{}"'.format(router
)
851 router_compare_json_output(
853 "show ipv6 route isis json",
854 outputs
[rname
][15]["show_ipv6_route.ref"],
863 # Action(s): wait for the convergence and SPF computation on rt1
866 # - convergence of IPv6 RIB
868 def test_rib_ipv6_step19():
869 logger
.info("Test (step 19): verify IPv6 RIB")
872 # Skip if previous fatal error condition is raised
873 if tgen
.routers_have_failure():
874 pytest
.skip(tgen
.errors
)
876 logger
.info("Check SPF convergence")
878 for rname
in ["rt1"]:
879 router_compare_json_output(
881 "show ipv6 route isis json",
882 outputs
[rname
][16]["show_ipv6_route.ref"],
890 # - Unshut the switch from rt1 to rt2
893 # - The routing table goes back to the nominal state
895 def test_rib_ipv6_step20():
896 logger
.info("Test (step 20): verify IPv6 RIB")
899 # Skip if previous fatal error condition is raised
900 if tgen
.routers_have_failure():
901 pytest
.skip(tgen
.errors
)
905 logger
.info("Unsetting spf-delay-ietf init-delay of 15s")
906 tgen
.net
[rname
].cmd('vtysh -c "conf t" -c "router isis 1" -c "no spf-delay-ietf"')
909 "Unshut the interface to rt2 from the switch side and check fast-reroute"
911 tgen
.net
.cmd_raises("ip link set s1 up")
913 logger
.info("Setting spf-delay-ietf init-delay of 15s")
915 'vtysh -c "conf t" -c "router isis 1" -c "spf-delay-ietf init-delay 15000 short-delay 0 long-delay 0 holddown 0 time-to-learn 0"'
918 router_compare_json_output(
920 "show ipv6 route isis json",
921 outputs
[rname
][14]["show_ipv6_route.ref"],
929 # - clear the rt2 ISIS neighbor on rt1
932 # - Route switchover of routes via eth-rt2
934 def test_rib_ipv6_step21():
935 logger
.info("Test (step 21): verify IPv6 RIB")
938 # Skip if previous fatal error condition is raised
939 if tgen
.routers_have_failure():
940 pytest
.skip(tgen
.errors
)
944 logger
.info("Clear the rt2 ISIS neighbor on rt1 and check fast-reroute")
945 tgen
.gears
[rname
].vtysh_cmd("clear isis neighbor rt2")
947 router_compare_json_output(
949 "show ipv6 route isis json",
950 outputs
[rname
][15]["show_ipv6_route.ref"],
959 # Action(s): wait for the convergence and SPF computation on rt1
962 # - convergence of IPv6 RIB
964 def test_rib_ipv6_step22():
965 logger
.info("Test (step 22): verify IPv6 RIB")
968 # Skip if previous fatal error condition is raised
969 if tgen
.routers_have_failure():
970 pytest
.skip(tgen
.errors
)
972 logger
.info("Check SPF convergence")
974 for rname
in ["rt1"]:
975 router_compare_json_output(
977 "show ipv6 route isis json",
978 outputs
[rname
][16]["show_ipv6_route.ref"],
989 # - No routing table change
992 def test_rib_ipv6_step23():
993 logger
.info("Test (step 23): verify IPv6 RIB")
996 # Skip if previous fatal error condition is raised
997 if tgen
.routers_have_failure():
998 pytest
.skip(tgen
.errors
)
1000 logger
.info("Setup BFD on rt1 and rt2")
1001 for rname
in ["rt1", "rt2"]:
1002 conf_file
= os
.path
.join(CWD
, "{}/bfdd.conf".format(rname
))
1003 tgen
.net
[rname
].cmd("vtysh -f {}".format(conf_file
))
1005 logger
.info("Set ISIS BFD")
1006 tgen
.net
["rt1"].cmd('vtysh -c "conf t" -c "int eth-rt2" -c "isis bfd"')
1007 tgen
.net
["rt2"].cmd('vtysh -c "conf t" -c "int eth-rt1" -c "isis bfd"')
1010 expect
= '[{"multihop":false,"interface":"eth-rt2","status":"up"}]'
1011 router_compare_json_output(rname
, "show bfd peers json", expect
)
1013 router_compare_json_output(
1015 "show ipv6 route isis json",
1016 outputs
[rname
][14]["show_ipv6_route.ref"],
1024 # - drop traffic between rt1 and rt2 by shutting down the bridge between
1025 # the routers. Interfaces on rt1 and rt2 stay up.
1028 # - BFD comes down before IS-IS
1029 # - Route switchover of routes via eth-rt2
1031 def test_rib_ipv6_step24():
1032 def _bfd_down(router
):
1033 output
= json
.loads(router
.vtysh_cmd("show bfd peers json"))
1035 return topotest
.json_cmp(output
, expected
, exact
=True)
1037 logger
.info("Test (step 24): verify IPv6 RIB")
1038 tgen
= get_topogen()
1040 # Skip if previous fatal error condition is raised
1041 if tgen
.routers_have_failure():
1042 pytest
.skip(tgen
.errors
)
1044 logger
.info("Shut the interface to rt2 from the switch side and check fast-reroute")
1045 tgen
.net
.cmd_raises("ip link set s1 down")
1048 router
= tgen
.gears
[rname
]
1049 test_func
= partial(_bfd_down
, router
)
1050 success
, result
= topotest
.run_and_expect(test_func
, None, count
=30, wait
=0.3)
1051 assert result
is None, 'BFD session is still up on "{}"'.format(router
)
1053 router_compare_json_output(
1055 "show ipv6 route isis json",
1056 outputs
[rname
][15]["show_ipv6_route.ref"],
1064 # Action(s): wait for the convergence and SPF computation on rt1
1067 # - convergence of IPv6 RIB
1069 def test_rib_ipv6_step25():
1070 logger
.info("Test (step 25): verify IPv6 RIB")
1071 tgen
= get_topogen()
1073 # Skip if previous fatal error condition is raised
1074 if tgen
.routers_have_failure():
1075 pytest
.skip(tgen
.errors
)
1077 logger
.info("Check SPF convergence")
1079 for rname
in ["rt1"]:
1080 router_compare_json_output(
1082 "show ipv6 route isis json",
1083 outputs
[rname
][16]["show_ipv6_route.ref"],
1087 # Memory leak test template
1088 def test_memory_leak():
1089 "Run the memory leak test and report results."
1090 tgen
= get_topogen()
1091 if not tgen
.is_memleak_enabled():
1092 pytest
.skip("Memory leak test/report is disabled")
1094 tgen
.report_memory_leaks()
1097 if __name__
== "__main__":
1098 args
= ["-s"] + sys
.argv
[1:]
1099 sys
.exit(pytest
.main(args
))