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