]> git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/isis_tilfa_topo1/test_isis_tilfa_topo1.py
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / tests / topotests / isis_tilfa_topo1 / test_isis_tilfa_topo1.py
1 #!/usr/bin/env python
2 # SPDX-License-Identifier: ISC
3
4 #
5 # test_isis_tilfa_topo1.py
6 # Part of NetDEF Topology Tests
7 #
8 # Copyright (c) 2020 by
9 # Network Device Education Foundation, Inc. ("NetDEF")
10 #
11
12 """
13 test_isis_tilfa_topo1.py:
14
15 +---------+
16 | |
17 | RT1 |
18 | 1.1.1.1 |
19 | |
20 +---------+
21 |eth-sw1
22 |
23 |
24 |
25 +---------+ | +---------+
26 | | | | |
27 | RT2 |eth-sw1 | eth-sw1| RT3 |
28 | 2.2.2.2 +----------+----------+ 3.3.3.3 |
29 | | 10.0.1.0/24 | |
30 +---------+ +---------+
31 eth-rt4-1| |eth-rt4-2 eth-rt5-1| |eth-rt5-2
32 | | | |
33 10.0.2.0/24| |10.0.3.0/24 10.0.4.0/24| |10.0.5.0/24
34 | | | |
35 eth-rt2-1| |eth-rt2-2 eth-rt3-1| |eth-rt3-2
36 +---------+ +---------+
37 | | | |
38 | RT4 | 10.0.6.0/24 | RT5 |
39 | 4.4.4.4 +---------------------+ 5.5.5.5 |
40 | |eth-rt5 eth-rt4| |
41 +---------+ +---------+
42 eth-rt6| |eth-rt6
43 | |
44 10.0.7.0/24| |10.0.8.0/24
45 | +---------+ |
46 | | | |
47 | | RT6 | |
48 +----------+ 6.6.6.6 +-----------+
49 eth-rt4| |eth-rt5
50 +---------+
51 """
52
53 import os
54 import sys
55 import pytest
56 import json
57 import tempfile
58 from functools import partial
59
60 # Save the Current Working Directory to find configuration files.
61 CWD = os.path.dirname(os.path.realpath(__file__))
62 sys.path.append(os.path.join(CWD, "../"))
63
64 # pylint: disable=C0413
65 # Import topogen and topotest helpers
66 from lib import topotest
67 from lib.topogen import Topogen, TopoRouter, get_topogen
68 from lib.topolog import logger
69
70 # Required to instantiate the topology builder class.
71
72 pytestmark = [pytest.mark.isisd]
73
74 # Global multi-dimensional dictionary containing all expected outputs
75 outputs = {}
76
77
78 def build_topo(tgen):
79 "Build function"
80
81 #
82 # Define FRR Routers
83 #
84 for router in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
85 tgen.add_router(router)
86
87 #
88 # Define connections
89 #
90 switch = tgen.add_switch("s1")
91 switch.add_link(tgen.gears["rt1"], nodeif="eth-sw1")
92 switch.add_link(tgen.gears["rt2"], nodeif="eth-sw1")
93 switch.add_link(tgen.gears["rt3"], nodeif="eth-sw1")
94
95 switch = tgen.add_switch("s2")
96 switch.add_link(tgen.gears["rt2"], nodeif="eth-rt4-1")
97 switch.add_link(tgen.gears["rt4"], nodeif="eth-rt2-1")
98
99 switch = tgen.add_switch("s3")
100 switch.add_link(tgen.gears["rt2"], nodeif="eth-rt4-2")
101 switch.add_link(tgen.gears["rt4"], nodeif="eth-rt2-2")
102
103 switch = tgen.add_switch("s4")
104 switch.add_link(tgen.gears["rt3"], nodeif="eth-rt5-1")
105 switch.add_link(tgen.gears["rt5"], nodeif="eth-rt3-1")
106
107 switch = tgen.add_switch("s5")
108 switch.add_link(tgen.gears["rt3"], nodeif="eth-rt5-2")
109 switch.add_link(tgen.gears["rt5"], nodeif="eth-rt3-2")
110
111 switch = tgen.add_switch("s6")
112 switch.add_link(tgen.gears["rt4"], nodeif="eth-rt5")
113 switch.add_link(tgen.gears["rt5"], nodeif="eth-rt4")
114
115 switch = tgen.add_switch("s7")
116 switch.add_link(tgen.gears["rt4"], nodeif="eth-rt6")
117 switch.add_link(tgen.gears["rt6"], nodeif="eth-rt4")
118
119 switch = tgen.add_switch("s8")
120 switch.add_link(tgen.gears["rt5"], nodeif="eth-rt6")
121 switch.add_link(tgen.gears["rt6"], nodeif="eth-rt5")
122
123 #
124 # Populate multi-dimensional dictionary containing all expected outputs
125 #
126 files = [
127 "show_ip_route.ref",
128 "show_ipv6_route.ref",
129 "show_mpls_table.ref",
130 "show_yang_interface_isis_adjacencies.ref",
131 ]
132 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
133 outputs[rname] = {}
134 for step in range(1, 12 + 1):
135 outputs[rname][step] = {}
136 for file in files:
137 if step == 1:
138 # Get snapshots relative to the expected initial network convergence
139 filename = "{}/{}/step{}/{}".format(CWD, rname, step, file)
140 outputs[rname][step][file] = open(filename).read()
141 else:
142 if file == "show_yang_interface_isis_adjacencies.ref":
143 continue
144
145 # Get diff relative to the previous step
146 filename = "{}/{}/step{}/{}.diff".format(CWD, rname, step, file)
147
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])
151 f_in.flush()
152 f_out = tempfile.NamedTemporaryFile(mode="r")
153 os.system(
154 "patch -s -o %s %s %s" % (f_out.name, f_in.name, filename)
155 )
156
157 # Store the updated snapshot and remove the temporary files
158 outputs[rname][step][file] = open(f_out.name).read()
159 f_in.close()
160 f_out.close()
161
162
163 def setup_module(mod):
164 "Sets up the pytest environment"
165 tgen = Topogen(build_topo, mod.__name__)
166 tgen.start_topology()
167
168 router_list = tgen.routers()
169
170 # For all registered routers, load the zebra configuration file
171 for rname, router in router_list.items():
172 router.load_config(
173 TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
174 )
175 router.load_config(
176 TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
177 )
178 router.load_config(
179 TopoRouter.RD_BFD, os.path.join(CWD, "/dev/null".format(rname))
180 )
181
182 tgen.start_router()
183
184
185 def teardown_module(mod):
186 "Teardown the pytest environment"
187 tgen = get_topogen()
188
189 # This function tears down the whole topology.
190 tgen.stop_topology()
191
192
193 def router_compare_json_output(rname, command, reference, count=120, wait=0.5):
194 "Compare router JSON output"
195
196 logger.info('Comparing router "%s" "%s" output', rname, command)
197
198 tgen = get_topogen()
199 expected = json.loads(reference)
200
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
206
207
208 #
209 # Step 1
210 #
211 # Test initial network convergence
212 #
213 def test_isis_adjacencies_step1():
214 logger.info("Test (step 1): check IS-IS adjacencies")
215 tgen = get_topogen()
216
217 # Skip if previous fatal error condition is raised
218 if tgen.routers_have_failure():
219 pytest.skip(tgen.errors)
220
221 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
222 router_compare_json_output(
223 rname,
224 "show yang operational-data /frr-interface:lib isisd",
225 outputs[rname][1]["show_yang_interface_isis_adjacencies.ref"],
226 )
227
228
229 def test_rib_ipv4_step1():
230 logger.info("Test (step 1): verify IPv4 RIB")
231 tgen = get_topogen()
232
233 # Skip if previous fatal error condition is raised
234 if tgen.routers_have_failure():
235 pytest.skip(tgen.errors)
236
237 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
238 router_compare_json_output(
239 rname, "show ip route isis json", outputs[rname][1]["show_ip_route.ref"]
240 )
241
242
243 def test_rib_ipv6_step1():
244 logger.info("Test (step 1): verify IPv6 RIB")
245 tgen = get_topogen()
246
247 # Skip if previous fatal error condition is raised
248 if tgen.routers_have_failure():
249 pytest.skip(tgen.errors)
250
251 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
252 router_compare_json_output(
253 rname, "show ipv6 route isis json", outputs[rname][1]["show_ipv6_route.ref"]
254 )
255
256
257 def test_mpls_lib_step1():
258 logger.info("Test (step 1): verify MPLS LIB")
259 tgen = get_topogen()
260
261 # Skip if previous fatal error condition is raised
262 if tgen.routers_have_failure():
263 pytest.skip(tgen.errors)
264
265 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
266 router_compare_json_output(
267 rname, "show mpls table json", outputs[rname][1]["show_mpls_table.ref"]
268 )
269
270
271 #
272 # Step 2
273 #
274 # Action(s):
275 # -Disable TI-LFA link protection on rt2's eth-sw1 interface
276 #
277 # Expected changes:
278 # -rt2 should uninstall the backup nexthops from destinations reachable over eth-sw1.
279 #
280 def test_rib_ipv4_step2():
281 logger.info("Test (step 2): verify IPv4 RIB")
282 tgen = get_topogen()
283
284 # Skip if previous fatal error condition is raised
285 if tgen.routers_have_failure():
286 pytest.skip(tgen.errors)
287
288 logger.info("Disabling TI-LFA link protection on rt2's eth-sw1 interface")
289 tgen.net["rt2"].cmd(
290 'vtysh -c "conf t" -c "interface eth-sw1" -c "no isis fast-reroute ti-lfa"'
291 )
292
293 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
294 router_compare_json_output(
295 rname, "show ip route isis json", outputs[rname][2]["show_ip_route.ref"]
296 )
297
298
299 def test_rib_ipv6_step2():
300 logger.info("Test (step 2): verify IPv6 RIB")
301 tgen = get_topogen()
302
303 # Skip if previous fatal error condition is raised
304 if tgen.routers_have_failure():
305 pytest.skip(tgen.errors)
306
307 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
308 router_compare_json_output(
309 rname, "show ipv6 route isis json", outputs[rname][2]["show_ipv6_route.ref"]
310 )
311
312
313 def test_mpls_lib_step2():
314 logger.info("Test (step 2): verify MPLS LIB")
315 tgen = get_topogen()
316
317 # Skip if previous fatal error condition is raised
318 if tgen.routers_have_failure():
319 pytest.skip(tgen.errors)
320
321 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
322 router_compare_json_output(
323 rname, "show mpls table json", outputs[rname][2]["show_mpls_table.ref"]
324 )
325
326
327 #
328 # Step 3
329 #
330 # Action(s):
331 # -Enable TI-LFA link protection on rt2's eth-sw1 interface
332 #
333 # Expected changes:
334 # -rt2 should install backup nexthops for destinations reachable over eth-sw1.
335 #
336 def test_rib_ipv4_step3():
337 logger.info("Test (step 3): verify IPv4 RIB")
338 tgen = get_topogen()
339
340 # Skip if previous fatal error condition is raised
341 if tgen.routers_have_failure():
342 pytest.skip(tgen.errors)
343
344 logger.info("Enabling TI-LFA link protection on rt2's eth-sw1 interface")
345 tgen.net["rt2"].cmd(
346 'vtysh -c "conf t" -c "interface eth-sw1" -c "isis fast-reroute ti-lfa"'
347 )
348
349 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
350 router_compare_json_output(
351 rname, "show ip route isis json", outputs[rname][3]["show_ip_route.ref"]
352 )
353
354
355 def test_rib_ipv6_step3():
356 logger.info("Test (step 3): verify IPv6 RIB")
357 tgen = get_topogen()
358
359 # Skip if previous fatal error condition is raised
360 if tgen.routers_have_failure():
361 pytest.skip(tgen.errors)
362
363 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
364 router_compare_json_output(
365 rname, "show ipv6 route isis json", outputs[rname][3]["show_ipv6_route.ref"]
366 )
367
368
369 def test_mpls_lib_step3():
370 logger.info("Test (step 3): verify MPLS LIB")
371 tgen = get_topogen()
372
373 # Skip if previous fatal error condition is raised
374 if tgen.routers_have_failure():
375 pytest.skip(tgen.errors)
376
377 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
378 router_compare_json_output(
379 rname, "show mpls table json", outputs[rname][3]["show_mpls_table.ref"]
380 )
381
382
383 #
384 # Step 4
385 #
386 # Action(s):
387 # -Disable SR on rt4
388 #
389 # Expected changes:
390 # -rt4 should uninstall all Prefix-SIDs from the network
391 # -rt4 should uninstall all TI-LFA backup nexthops
392 # -All routers should uninstall rt4's Prefix-SIDs
393 # -All routers should uninstall all SR labels for destinations whose nexthop is rt4
394 # -All routers should uninstall all TI-LFA backup nexthops that point to rt4
395 # -All routers should uninstall all TI-LFA backup nexthops that use rt4's Prefix-SIDs
396 #
397 def test_rib_ipv4_step4():
398 logger.info("Test (step 4): verify IPv4 RIB")
399 tgen = get_topogen()
400
401 # Skip if previous fatal error condition is raised
402 if tgen.routers_have_failure():
403 pytest.skip(tgen.errors)
404
405 logger.info("Disabling SR on rt4")
406 tgen.net["rt4"].cmd(
407 'vtysh -c "conf t" -c "router isis 1" -c "no segment-routing on"'
408 )
409
410 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
411 router_compare_json_output(
412 rname, "show ip route isis json", outputs[rname][4]["show_ip_route.ref"]
413 )
414
415
416 def test_rib_ipv6_step4():
417 logger.info("Test (step 4): verify IPv6 RIB")
418 tgen = get_topogen()
419
420 # Skip if previous fatal error condition is raised
421 if tgen.routers_have_failure():
422 pytest.skip(tgen.errors)
423
424 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
425 router_compare_json_output(
426 rname, "show ipv6 route isis json", outputs[rname][4]["show_ipv6_route.ref"]
427 )
428
429
430 def test_mpls_lib_step4():
431 logger.info("Test (step 4): verify MPLS LIB")
432 tgen = get_topogen()
433
434 # Skip if previous fatal error condition is raised
435 if tgen.routers_have_failure():
436 pytest.skip(tgen.errors)
437
438 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
439 router_compare_json_output(
440 rname, "show mpls table json", outputs[rname][4]["show_mpls_table.ref"]
441 )
442
443
444 #
445 # Step 5
446 #
447 # Action(s):
448 # -Enable SR on rt4
449 #
450 # Expected changes:
451 # -Reverse all changes done on the previous step
452 #
453 def test_rib_ipv4_step5():
454 logger.info("Test (step 5): verify IPv4 RIB")
455 tgen = get_topogen()
456
457 # Skip if previous fatal error condition is raised
458 if tgen.routers_have_failure():
459 pytest.skip(tgen.errors)
460
461 logger.info("Enabling SR on rt4")
462 tgen.net["rt4"].cmd('vtysh -c "conf t" -c "router isis 1" -c "segment-routing on"')
463
464 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
465 router_compare_json_output(
466 rname, "show ip route isis json", outputs[rname][5]["show_ip_route.ref"]
467 )
468
469
470 def test_rib_ipv6_step5():
471 logger.info("Test (step 5): verify IPv6 RIB")
472 tgen = get_topogen()
473
474 # Skip if previous fatal error condition is raised
475 if tgen.routers_have_failure():
476 pytest.skip(tgen.errors)
477
478 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
479 router_compare_json_output(
480 rname, "show ipv6 route isis json", outputs[rname][5]["show_ipv6_route.ref"]
481 )
482
483
484 def test_mpls_lib_step5():
485 logger.info("Test (step 5): verify MPLS LIB")
486 tgen = get_topogen()
487
488 # Skip if previous fatal error condition is raised
489 if tgen.routers_have_failure():
490 pytest.skip(tgen.errors)
491
492 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
493 router_compare_json_output(
494 rname, "show mpls table json", outputs[rname][5]["show_mpls_table.ref"]
495 )
496
497
498 #
499 # Step 6
500 #
501 # Action(s):
502 # -Change rt5's SRGB
503 #
504 # Expected changes:
505 # -All routers should update all SR labels for destinations whose primary or backup nexthop is rt5
506 #
507 def test_rib_ipv4_step6():
508 logger.info("Test (step 6): verify IPv4 RIB")
509 tgen = get_topogen()
510
511 # Skip if previous fatal error condition is raised
512 if tgen.routers_have_failure():
513 pytest.skip(tgen.errors)
514
515 logger.info("Changing rt5's SRGB")
516 tgen.net["rt5"].cmd(
517 'vtysh -c "conf t" -c "router isis 1" -c "segment-routing global-block 30000 37999"'
518 )
519
520 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
521 router_compare_json_output(
522 rname, "show ip route isis json", outputs[rname][6]["show_ip_route.ref"]
523 )
524
525
526 def test_rib_ipv6_step6():
527 logger.info("Test (step 6): verify IPv6 RIB")
528 tgen = get_topogen()
529
530 # Skip if previous fatal error condition is raised
531 if tgen.routers_have_failure():
532 pytest.skip(tgen.errors)
533
534 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
535 router_compare_json_output(
536 rname, "show ipv6 route isis json", outputs[rname][6]["show_ipv6_route.ref"]
537 )
538
539
540 def test_mpls_lib_step6():
541 logger.info("Test (step 6): verify MPLS LIB")
542 tgen = get_topogen()
543
544 # Skip if previous fatal error condition is raised
545 if tgen.routers_have_failure():
546 pytest.skip(tgen.errors)
547
548 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
549 router_compare_json_output(
550 rname, "show mpls table json", outputs[rname][6]["show_mpls_table.ref"]
551 )
552
553
554 #
555 # Step 7
556 #
557 # Action(s):
558 # -Delete rt5's Prefix-SIDs
559 #
560 # Expected changes:
561 # -All routers should uninstall rt5's Prefix-SIDs
562 # -All routers should uninstall all TI-LFA backup nexthops that use rt5's Prefix-SIDs
563 #
564 def test_rib_ipv4_step7():
565 logger.info("Test (step 7): verify IPv4 RIB")
566 tgen = get_topogen()
567
568 # Skip if previous fatal error condition is raised
569 if tgen.routers_have_failure():
570 pytest.skip(tgen.errors)
571
572 logger.info("Deleting rt5's Prefix-SIDs")
573 tgen.net["rt5"].cmd(
574 'vtysh -c "conf t" -c "router isis 1" -c "no segment-routing prefix 5.5.5.5/32 index 50"'
575 )
576 tgen.net["rt5"].cmd(
577 'vtysh -c "conf t" -c "router isis 1" -c "no segment-routing prefix 2001:db8:1000::5/128 index 51"'
578 )
579
580 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
581 router_compare_json_output(
582 rname, "show ip route isis json", outputs[rname][7]["show_ip_route.ref"]
583 )
584
585
586 def test_rib_ipv6_step7():
587 logger.info("Test (step 7): verify IPv6 RIB")
588 tgen = get_topogen()
589
590 # Skip if previous fatal error condition is raised
591 if tgen.routers_have_failure():
592 pytest.skip(tgen.errors)
593
594 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
595 router_compare_json_output(
596 rname, "show ipv6 route isis json", outputs[rname][7]["show_ipv6_route.ref"]
597 )
598
599
600 def test_mpls_lib_step7():
601 logger.info("Test (step 7): verify MPLS LIB")
602 tgen = get_topogen()
603
604 # Skip if previous fatal error condition is raised
605 if tgen.routers_have_failure():
606 pytest.skip(tgen.errors)
607
608 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
609 router_compare_json_output(
610 rname, "show mpls table json", outputs[rname][7]["show_mpls_table.ref"]
611 )
612
613
614 #
615 # Step 8
616 #
617 # Action(s):
618 # -Re-add rt5's Prefix-SIDs
619 #
620 # Expected changes:
621 # -Reverse all changes done on the previous step
622 #
623 def test_rib_ipv4_step8():
624 logger.info("Test (step 8): verify IPv4 RIB")
625 tgen = get_topogen()
626
627 # Skip if previous fatal error condition is raised
628 if tgen.routers_have_failure():
629 pytest.skip(tgen.errors)
630
631 logger.info("Re-adding rt5's Prefix-SIDs")
632 tgen.net["rt5"].cmd(
633 'vtysh -c "conf t" -c "router isis 1" -c "segment-routing prefix 5.5.5.5/32 index 50"'
634 )
635 tgen.net["rt5"].cmd(
636 'vtysh -c "conf t" -c "router isis 1" -c "segment-routing prefix 2001:db8:1000::5/128 index 51"'
637 )
638
639 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
640 router_compare_json_output(
641 rname, "show ip route isis json", outputs[rname][8]["show_ip_route.ref"]
642 )
643
644
645 def test_rib_ipv6_step8():
646 logger.info("Test (step 8): verify IPv6 RIB")
647 tgen = get_topogen()
648
649 # Skip if previous fatal error condition is raised
650 if tgen.routers_have_failure():
651 pytest.skip(tgen.errors)
652
653 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
654 router_compare_json_output(
655 rname, "show ipv6 route isis json", outputs[rname][8]["show_ipv6_route.ref"]
656 )
657
658
659 def test_mpls_lib_step8():
660 logger.info("Test (step 8): verify MPLS LIB")
661 tgen = get_topogen()
662
663 # Skip if previous fatal error condition is raised
664 if tgen.routers_have_failure():
665 pytest.skip(tgen.errors)
666
667 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
668 router_compare_json_output(
669 rname, "show mpls table json", outputs[rname][8]["show_mpls_table.ref"]
670 )
671
672
673 #
674 # Step 9
675 #
676 # Action(s):
677 # -Change rt5's Prefix-SIDs
678 #
679 # Expected changes:
680 # -All routers should update rt5's Prefix-SIDs
681 # -All routers should update all TI-LFA backup nexthops that use rt5's Prefix-SIDs
682 #
683 def test_rib_ipv4_step9():
684 logger.info("Test (step 9): verify IPv4 RIB")
685 tgen = get_topogen()
686
687 # Skip if previous fatal error condition is raised
688 if tgen.routers_have_failure():
689 pytest.skip(tgen.errors)
690
691 logger.info("Re-adding rt5's Prefix-SIDs")
692 tgen.net["rt5"].cmd(
693 'vtysh -c "conf t" -c "router isis 1" -c "segment-routing prefix 5.5.5.5/32 index 500"'
694 )
695 tgen.net["rt5"].cmd(
696 'vtysh -c "conf t" -c "router isis 1" -c "segment-routing prefix 2001:db8:1000::5/128 index 501"'
697 )
698
699 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
700 router_compare_json_output(
701 rname, "show ip route isis json", outputs[rname][9]["show_ip_route.ref"]
702 )
703
704
705 def test_rib_ipv6_step9():
706 logger.info("Test (step 9): verify IPv6 RIB")
707 tgen = get_topogen()
708
709 # Skip if previous fatal error condition is raised
710 if tgen.routers_have_failure():
711 pytest.skip(tgen.errors)
712
713 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
714 router_compare_json_output(
715 rname, "show ipv6 route isis json", outputs[rname][9]["show_ipv6_route.ref"]
716 )
717
718
719 def test_mpls_lib_step9():
720 logger.info("Test (step 9): verify MPLS LIB")
721 tgen = get_topogen()
722
723 # Skip if previous fatal error condition is raised
724 if tgen.routers_have_failure():
725 pytest.skip(tgen.errors)
726
727 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
728 router_compare_json_output(
729 rname, "show mpls table json", outputs[rname][9]["show_mpls_table.ref"]
730 )
731
732
733 #
734 # Step 10
735 #
736 # Action(s):
737 # - Setting spf-delay-ietf init-delay of 15s
738 #
739 # Expected changes:
740 # - No routing table change
741 # - At the end of test, SPF reacts to a failure in 15s
742 #
743 def test_rib_ipv4_step10():
744 logger.info("Test (step 10): verify IPv4 RIB")
745 tgen = get_topogen()
746
747 # Skip if previous fatal error condition is raised
748 if tgen.routers_have_failure():
749 pytest.skip(tgen.errors)
750
751 logger.info("Setting spf-delay-ietf init-delay of 15s")
752 tgen.net["rt6"].cmd(
753 '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"'
754 )
755
756 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
757 router_compare_json_output(
758 rname, "show ip route isis json", outputs[rname][10]["show_ip_route.ref"]
759 )
760
761
762 def test_rib_ipv6_step10():
763 logger.info("Test (step 10): verify IPv6 RIB")
764 tgen = get_topogen()
765
766 # Skip if previous fatal error condition is raised
767 if tgen.routers_have_failure():
768 pytest.skip(tgen.errors)
769
770 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
771 router_compare_json_output(
772 rname,
773 "show ipv6 route isis json",
774 outputs[rname][10]["show_ipv6_route.ref"],
775 )
776
777
778 def test_mpls_lib_step10():
779 logger.info("Test (step 10): verify MPLS LIB")
780 tgen = get_topogen()
781
782 # Skip if previous fatal error condition is raised
783 if tgen.routers_have_failure():
784 pytest.skip(tgen.errors)
785
786 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
787 router_compare_json_output(
788 rname, "show mpls table json", outputs[rname][10]["show_mpls_table.ref"]
789 )
790
791
792 #
793 # Step 11
794 #
795 # Action(s):
796 # - shut the eth-rt5 interface on rt6
797 #
798 # Expected changes:
799 # - Route switchover of routes via eth-rt5
800 #
801 def test_rt6_step11():
802 logger.info(
803 "Test (step 11): Check IPv4/6 RIB and MPLS table after a LFA switchover"
804 )
805 tgen = get_topogen()
806
807 # Skip if previous fatal error condition is raised
808 if tgen.routers_have_failure():
809 pytest.skip(tgen.errors)
810
811 logger.info(
812 "Shut a rt6 interface to rt5 from the switch side and check fast-reroute"
813 )
814 tgen.net.cmd_raises("ip link set %s down" % tgen.net["s8"].intfs[1])
815
816 rname = "rt6"
817 router_compare_json_output(
818 rname,
819 "show ip route isis json",
820 outputs[rname][11]["show_ip_route.ref"],
821 count=10,
822 )
823 router_compare_json_output(
824 rname,
825 "show ipv6 route isis json",
826 outputs[rname][11]["show_ipv6_route.ref"],
827 count=10,
828 )
829 router_compare_json_output(
830 rname,
831 "show mpls table json",
832 outputs[rname][11]["show_mpls_table.ref"],
833 count=10,
834 )
835
836
837 #
838 # Step 12
839 #
840 # Action(s): wait for the convergence and SPF computation on rt6
841 #
842 # Expected changes:
843 # - convergence of IPv4/6 RIB and MPLS table
844 #
845 def test_rib_ipv4_step12():
846 logger.info("Test (step 12): verify IPv4 RIB")
847 tgen = get_topogen()
848
849 # Skip if previous fatal error condition is raised
850 if tgen.routers_have_failure():
851 pytest.skip(tgen.errors)
852
853 logger.info("Check SPF convergence")
854 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
855 router_compare_json_output(
856 rname,
857 "show ip route isis json",
858 outputs[rname][12]["show_ip_route.ref"],
859 )
860
861
862 def test_rib_ipv6_step12():
863 logger.info("Test (step 12): verify IPv6 RIB")
864 tgen = get_topogen()
865
866 # Skip if previous fatal error condition is raised
867 if tgen.routers_have_failure():
868 pytest.skip(tgen.errors)
869
870 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
871 router_compare_json_output(
872 rname,
873 "show ipv6 route isis json",
874 outputs[rname][12]["show_ipv6_route.ref"],
875 )
876
877
878 def test_mpls_lib_step12():
879 logger.info("Test (step 12): verify MPLS LIB")
880 tgen = get_topogen()
881
882 # Skip if previous fatal error condition is raised
883 if tgen.routers_have_failure():
884 pytest.skip(tgen.errors)
885
886 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
887 router_compare_json_output(
888 rname,
889 "show mpls table json",
890 outputs[rname][12]["show_mpls_table.ref"],
891 )
892
893
894 #
895 # Step 13
896 #
897 # Action(s):
898 # - unshut the rt6 to rt5 interface
899 # - Setup BFD
900 #
901 # Expected changes:
902 # - All route tables go back to previous state situation
903 # - At the end of test, next SPF is scheduled in approximatively 15s
904 #
905 def test_rib_ipv4_step13():
906 logger.info("Test (step 13): verify IPv4 RIB")
907 tgen = get_topogen()
908
909 # Skip if previous fatal error condition is raised
910 if tgen.routers_have_failure():
911 pytest.skip(tgen.errors)
912
913 logger.info("Unsetting spf-delay-ietf init-delay of 15s")
914 tgen.net["rt6"].cmd('vtysh -c "conf t" -c "router isis 1" -c "no spf-delay-ietf"')
915
916 logger.info(
917 "Unshut the rt6 interface to rt5 from the switch side and check fast-reroute"
918 )
919 tgen.net.cmd_raises("ip link set %s up" % tgen.net["s8"].intfs[1])
920
921 logger.info("Setup BFD on rt5 and rt6")
922 for rname in ["rt5", "rt6"]:
923 conf_file = os.path.join(CWD, "{}/bfdd.conf".format(rname))
924 tgen.net[rname].cmd("vtysh -f {}".format(conf_file))
925
926 expect = (
927 '[{"multihop":false,"peer":"10.0.8.5","interface":"eth-rt5","status":"up"}]'
928 )
929 router_compare_json_output("rt6", "show bfd peers json", expect)
930
931 # Unset link detection. We want zebra to consider linkdow as operationaly up
932 # in order that BFD triggers LFA instead of the interface down
933
934 # reset spf-interval
935 logger.info("Set spf-interval to 15s")
936 tgen.net["rt6"].cmd(
937 '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"'
938 )
939
940 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
941 router_compare_json_output(
942 rname, "show ip route isis json", outputs[rname][10]["show_ip_route.ref"]
943 )
944
945 logger.info("Set ISIS BFD")
946 tgen.net["rt5"].cmd('vtysh -c "conf t" -c "int eth-rt6" -c "isis bfd"')
947 tgen.net["rt6"].cmd('vtysh -c "conf t" -c "int eth-rt5" -c "isis bfd"')
948
949
950 def test_rib_ipv6_step13():
951 logger.info("Test (step 13): verify IPv6 RIB")
952 tgen = get_topogen()
953
954 # Skip if previous fatal error condition is raised
955 if tgen.routers_have_failure():
956 pytest.skip(tgen.errors)
957
958 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
959 router_compare_json_output(
960 rname,
961 "show ipv6 route isis json",
962 outputs[rname][10]["show_ipv6_route.ref"],
963 )
964
965
966 def test_mpls_lib_step13():
967 logger.info("Test (step 13): verify MPLS LIB")
968 tgen = get_topogen()
969
970 # Skip if previous fatal error condition is raised
971 if tgen.routers_have_failure():
972 pytest.skip(tgen.errors)
973
974 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
975 router_compare_json_output(
976 rname, "show mpls table json", outputs[rname][10]["show_mpls_table.ref"]
977 )
978
979
980 #
981 # Step 14
982 #
983 # Action(s):
984 # - drop traffic between rt5 and rt6 by shutting down the bridge between
985 # the routers. Interfaces on rt5 and rt6 stay up.
986 #
987 # Expected changes:
988 # - Route switchover of routes via eth-rt5
989 #
990 def test_rt6_step14():
991 logger.info("Test (step 14): verify IPv4/6 RIB and MPLS table")
992 tgen = get_topogen()
993
994 # Skip if previous fatal error condition is raised
995 if tgen.routers_have_failure():
996 pytest.skip(tgen.errors)
997
998 logger.info("Drop traffic between rt5 and rt6")
999 tgen.net.cmd_raises("ip link set s8 down")
1000
1001 rname = "rt6"
1002
1003 expect = (
1004 '[{"multihop":false,"peer":"10.0.8.5","interface":"eth-rt5","status":"down"}]'
1005 )
1006 router_compare_json_output(
1007 rname,
1008 "show bfd peers json",
1009 expect,
1010 count=40,
1011 wait=0.5,
1012 )
1013
1014 router_compare_json_output(
1015 rname,
1016 "show ip route isis json",
1017 outputs[rname][11]["show_ip_route.ref"],
1018 count=10,
1019 )
1020 router_compare_json_output(
1021 rname,
1022 "show ipv6 route isis json",
1023 outputs[rname][11]["show_ipv6_route.ref"],
1024 count=10,
1025 )
1026 router_compare_json_output(
1027 rname,
1028 "show mpls table json",
1029 outputs[rname][11]["show_mpls_table.ref"],
1030 count=10,
1031 )
1032
1033
1034 #
1035 # Step 15
1036 #
1037 # Action(s): wait for the convergence and SPF computation on rt6
1038 #
1039 # Expected changes:
1040 # - convergence of IPv4/6 RIB and MPLS table
1041 #
1042 def test_rib_ipv4_step15():
1043 logger.info("Test (step 15): verify IPv4 RIB")
1044 tgen = get_topogen()
1045
1046 # Skip if previous fatal error condition is raised
1047 if tgen.routers_have_failure():
1048 pytest.skip(tgen.errors)
1049
1050 logger.info("Check SPF convergence")
1051 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
1052 router_compare_json_output(
1053 rname,
1054 "show ip route isis json",
1055 outputs[rname][12]["show_ip_route.ref"],
1056 )
1057
1058
1059 def test_rib_ipv6_step15():
1060 logger.info("Test (step 15): verify IPv6 RIB")
1061 tgen = get_topogen()
1062
1063 # Skip if previous fatal error condition is raised
1064 if tgen.routers_have_failure():
1065 pytest.skip(tgen.errors)
1066
1067 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
1068 router_compare_json_output(
1069 rname,
1070 "show ipv6 route isis json",
1071 outputs[rname][12]["show_ipv6_route.ref"],
1072 )
1073
1074
1075 def test_mpls_lib_step15():
1076 logger.info("Test (step 15): verify MPLS LIB")
1077 tgen = get_topogen()
1078
1079 # Skip if previous fatal error condition is raised
1080 if tgen.routers_have_failure():
1081 pytest.skip(tgen.errors)
1082
1083 for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
1084 router_compare_json_output(
1085 rname,
1086 "show mpls table json",
1087 outputs[rname][12]["show_mpls_table.ref"],
1088 )
1089
1090
1091 # Memory leak test template
1092 def test_memory_leak():
1093 "Run the memory leak test and report results."
1094 tgen = get_topogen()
1095 if not tgen.is_memleak_enabled():
1096 pytest.skip("Memory leak test/report is disabled")
1097
1098 tgen.report_memory_leaks()
1099
1100
1101 if __name__ == "__main__":
1102 args = ["-s"] + sys.argv[1:]
1103 sys.exit(pytest.main(args))