]>
Commit | Line | Data |
---|---|---|
9687c500 RW |
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 | |
9687c500 | 70 | import tempfile |
9687c500 RW |
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__)) | |
9fa6ec14 | 75 | sys.path.append(os.path.join(CWD, "../")) |
9687c500 RW |
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. | |
9687c500 | 84 | |
6907ac7e DS |
85 | pytestmark = [pytest.mark.isisd] |
86 | ||
9687c500 RW |
87 | # Global multi-dimensional dictionary containing all expected outputs |
88 | outputs = {} | |
89 | ||
9fa6ec14 | 90 | |
8db751b8 CH |
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] = {} | |
f3529a55 | 147 | for step in range(1, 12 + 1): |
8db751b8 CH |
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() | |
9687c500 | 174 | |
5980ad0a | 175 | |
9687c500 RW |
176 | def setup_module(mod): |
177 | "Sets up the pytest environment" | |
e82b531d | 178 | tgen = Topogen(build_topo, mod.__name__) |
9687c500 RW |
179 | tgen.start_topology() |
180 | ||
181 | router_list = tgen.routers() | |
182 | ||
183 | # For all registered routers, load the zebra configuration file | |
ecff3c7a | 184 | for rname, router in router_list.items(): |
9687c500 | 185 | router.load_config( |
9fa6ec14 | 186 | TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) |
9687c500 RW |
187 | ) |
188 | router.load_config( | |
9fa6ec14 | 189 | TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname)) |
9687c500 RW |
190 | ) |
191 | ||
192 | tgen.start_router() | |
193 | ||
9fa6ec14 | 194 | |
9687c500 RW |
195 | def teardown_module(mod): |
196 | "Teardown the pytest environment" | |
197 | tgen = get_topogen() | |
198 | ||
199 | # This function tears down the whole topology. | |
200 | tgen.stop_topology() | |
201 | ||
9fa6ec14 | 202 | |
f3529a55 | 203 | def router_compare_json_output(rname, command, reference, count=120): |
9687c500 RW |
204 | "Compare router JSON output" |
205 | ||
206 | logger.info('Comparing router "%s" "%s" output', rname, command) | |
207 | ||
208 | tgen = get_topogen() | |
209 | expected = json.loads(reference) | |
210 | ||
211 | # Run test function until we get an result. Wait at most 60 seconds. | |
9fa6ec14 | 212 | test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected) |
f3529a55 | 213 | _, diff = topotest.run_and_expect(test_func, None, count=count, wait=0.5) |
9687c500 RW |
214 | assertmsg = '"{}" JSON output mismatches the expected result'.format(rname) |
215 | assert diff is None, assertmsg | |
216 | ||
9fa6ec14 | 217 | |
9687c500 RW |
218 | # |
219 | # Step 1 | |
220 | # | |
221 | # Test initial network convergence | |
222 | # | |
223 | def test_isis_adjacencies_step1(): | |
224 | logger.info("Test (step 1): check IS-IS adjacencies") | |
225 | tgen = get_topogen() | |
226 | ||
227 | # Skip if previous fatal error condition is raised | |
228 | if tgen.routers_have_failure(): | |
229 | pytest.skip(tgen.errors) | |
230 | ||
9fa6ec14 | 231 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
232 | router_compare_json_output( | |
233 | rname, | |
234 | "show yang operational-data /frr-interface:lib isisd", | |
235 | outputs[rname][1]["show_yang_interface_isis_adjacencies.ref"], | |
236 | ) | |
237 | ||
9687c500 RW |
238 | |
239 | def test_rib_ipv4_step1(): | |
240 | logger.info("Test (step 1): verify IPv4 RIB") | |
241 | tgen = get_topogen() | |
242 | ||
243 | # Skip if previous fatal error condition is raised | |
244 | if tgen.routers_have_failure(): | |
245 | pytest.skip(tgen.errors) | |
246 | ||
9fa6ec14 | 247 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
248 | router_compare_json_output( | |
249 | rname, "show ip route isis json", outputs[rname][1]["show_ip_route.ref"] | |
250 | ) | |
251 | ||
9687c500 RW |
252 | |
253 | def test_rib_ipv6_step1(): | |
254 | logger.info("Test (step 1): verify IPv6 RIB") | |
255 | tgen = get_topogen() | |
256 | ||
257 | # Skip if previous fatal error condition is raised | |
258 | if tgen.routers_have_failure(): | |
259 | pytest.skip(tgen.errors) | |
260 | ||
9fa6ec14 | 261 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
262 | router_compare_json_output( | |
263 | rname, "show ipv6 route isis json", outputs[rname][1]["show_ipv6_route.ref"] | |
264 | ) | |
265 | ||
9687c500 RW |
266 | |
267 | def test_mpls_lib_step1(): | |
268 | logger.info("Test (step 1): verify MPLS LIB") | |
269 | tgen = get_topogen() | |
270 | ||
271 | # Skip if previous fatal error condition is raised | |
272 | if tgen.routers_have_failure(): | |
273 | pytest.skip(tgen.errors) | |
274 | ||
9fa6ec14 | 275 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
276 | router_compare_json_output( | |
277 | rname, "show mpls table json", outputs[rname][1]["show_mpls_table.ref"] | |
278 | ) | |
279 | ||
9687c500 RW |
280 | |
281 | # | |
282 | # Step 2 | |
283 | # | |
284 | # Action(s): | |
285 | # -Disable TI-LFA link protection on rt2's eth-sw1 interface | |
286 | # | |
287 | # Expected changes: | |
288 | # -rt2 should uninstall the backup nexthops from destinations reachable over eth-sw1. | |
289 | # | |
290 | def test_rib_ipv4_step2(): | |
291 | logger.info("Test (step 2): verify IPv4 RIB") | |
292 | tgen = get_topogen() | |
293 | ||
294 | # Skip if previous fatal error condition is raised | |
295 | if tgen.routers_have_failure(): | |
296 | pytest.skip(tgen.errors) | |
297 | ||
9fa6ec14 | 298 | logger.info("Disabling TI-LFA link protection on rt2's eth-sw1 interface") |
299 | tgen.net["rt2"].cmd( | |
300 | 'vtysh -c "conf t" -c "interface eth-sw1" -c "no isis fast-reroute ti-lfa"' | |
301 | ) | |
302 | ||
303 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: | |
304 | router_compare_json_output( | |
305 | rname, "show ip route isis json", outputs[rname][2]["show_ip_route.ref"] | |
306 | ) | |
9687c500 | 307 | |
9687c500 RW |
308 | |
309 | def test_rib_ipv6_step2(): | |
310 | logger.info("Test (step 2): verify IPv6 RIB") | |
311 | tgen = get_topogen() | |
312 | ||
313 | # Skip if previous fatal error condition is raised | |
314 | if tgen.routers_have_failure(): | |
315 | pytest.skip(tgen.errors) | |
316 | ||
9fa6ec14 | 317 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
318 | router_compare_json_output( | |
319 | rname, "show ipv6 route isis json", outputs[rname][2]["show_ipv6_route.ref"] | |
320 | ) | |
321 | ||
9687c500 RW |
322 | |
323 | def test_mpls_lib_step2(): | |
324 | logger.info("Test (step 2): verify MPLS LIB") | |
325 | tgen = get_topogen() | |
326 | ||
327 | # Skip if previous fatal error condition is raised | |
328 | if tgen.routers_have_failure(): | |
329 | pytest.skip(tgen.errors) | |
330 | ||
9fa6ec14 | 331 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
332 | router_compare_json_output( | |
333 | rname, "show mpls table json", outputs[rname][2]["show_mpls_table.ref"] | |
334 | ) | |
335 | ||
9687c500 RW |
336 | |
337 | # | |
338 | # Step 3 | |
339 | # | |
340 | # Action(s): | |
341 | # -Enable TI-LFA link protection on rt2's eth-sw1 interface | |
342 | # | |
343 | # Expected changes: | |
344 | # -rt2 should install backup nexthops for destinations reachable over eth-sw1. | |
345 | # | |
346 | def test_rib_ipv4_step3(): | |
347 | logger.info("Test (step 3): verify IPv4 RIB") | |
348 | tgen = get_topogen() | |
349 | ||
350 | # Skip if previous fatal error condition is raised | |
351 | if tgen.routers_have_failure(): | |
352 | pytest.skip(tgen.errors) | |
353 | ||
9fa6ec14 | 354 | logger.info("Enabling TI-LFA link protection on rt2's eth-sw1 interface") |
355 | tgen.net["rt2"].cmd( | |
356 | 'vtysh -c "conf t" -c "interface eth-sw1" -c "isis fast-reroute ti-lfa"' | |
357 | ) | |
358 | ||
359 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: | |
360 | router_compare_json_output( | |
361 | rname, "show ip route isis json", outputs[rname][3]["show_ip_route.ref"] | |
362 | ) | |
9687c500 | 363 | |
9687c500 RW |
364 | |
365 | def test_rib_ipv6_step3(): | |
366 | logger.info("Test (step 3): verify IPv6 RIB") | |
367 | tgen = get_topogen() | |
368 | ||
369 | # Skip if previous fatal error condition is raised | |
370 | if tgen.routers_have_failure(): | |
371 | pytest.skip(tgen.errors) | |
372 | ||
9fa6ec14 | 373 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
374 | router_compare_json_output( | |
375 | rname, "show ipv6 route isis json", outputs[rname][3]["show_ipv6_route.ref"] | |
376 | ) | |
377 | ||
9687c500 RW |
378 | |
379 | def test_mpls_lib_step3(): | |
380 | logger.info("Test (step 3): verify MPLS LIB") | |
381 | tgen = get_topogen() | |
382 | ||
383 | # Skip if previous fatal error condition is raised | |
384 | if tgen.routers_have_failure(): | |
385 | pytest.skip(tgen.errors) | |
386 | ||
9fa6ec14 | 387 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
388 | router_compare_json_output( | |
389 | rname, "show mpls table json", outputs[rname][3]["show_mpls_table.ref"] | |
390 | ) | |
391 | ||
9687c500 RW |
392 | |
393 | # | |
394 | # Step 4 | |
395 | # | |
396 | # Action(s): | |
397 | # -Disable SR on rt4 | |
398 | # | |
399 | # Expected changes: | |
400 | # -rt4 should uninstall all Prefix-SIDs from the network | |
401 | # -rt4 should uninstall all TI-LFA backup nexthops | |
402 | # -All routers should uninstall rt4's Prefix-SIDs | |
403 | # -All routers should uninstall all SR labels for destinations whose nexthop is rt4 | |
404 | # -All routers should uninstall all TI-LFA backup nexthops that point to rt4 | |
405 | # -All routers should uninstall all TI-LFA backup nexthops that use rt4's Prefix-SIDs | |
406 | # | |
407 | def test_rib_ipv4_step4(): | |
408 | logger.info("Test (step 4): verify IPv4 RIB") | |
409 | tgen = get_topogen() | |
410 | ||
411 | # Skip if previous fatal error condition is raised | |
412 | if tgen.routers_have_failure(): | |
413 | pytest.skip(tgen.errors) | |
414 | ||
9fa6ec14 | 415 | logger.info("Disabling SR on rt4") |
416 | tgen.net["rt4"].cmd( | |
417 | 'vtysh -c "conf t" -c "router isis 1" -c "no segment-routing on"' | |
418 | ) | |
419 | ||
420 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: | |
421 | router_compare_json_output( | |
422 | rname, "show ip route isis json", outputs[rname][4]["show_ip_route.ref"] | |
423 | ) | |
9687c500 | 424 | |
9687c500 RW |
425 | |
426 | def test_rib_ipv6_step4(): | |
427 | logger.info("Test (step 4): verify IPv6 RIB") | |
428 | tgen = get_topogen() | |
429 | ||
430 | # Skip if previous fatal error condition is raised | |
431 | if tgen.routers_have_failure(): | |
432 | pytest.skip(tgen.errors) | |
433 | ||
9fa6ec14 | 434 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
435 | router_compare_json_output( | |
436 | rname, "show ipv6 route isis json", outputs[rname][4]["show_ipv6_route.ref"] | |
437 | ) | |
438 | ||
9687c500 RW |
439 | |
440 | def test_mpls_lib_step4(): | |
441 | logger.info("Test (step 4): verify MPLS LIB") | |
442 | tgen = get_topogen() | |
443 | ||
444 | # Skip if previous fatal error condition is raised | |
445 | if tgen.routers_have_failure(): | |
446 | pytest.skip(tgen.errors) | |
447 | ||
9fa6ec14 | 448 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
449 | router_compare_json_output( | |
450 | rname, "show mpls table json", outputs[rname][4]["show_mpls_table.ref"] | |
451 | ) | |
452 | ||
9687c500 RW |
453 | |
454 | # | |
455 | # Step 5 | |
456 | # | |
457 | # Action(s): | |
458 | # -Enable SR on rt4 | |
459 | # | |
460 | # Expected changes: | |
461 | # -Reverse all changes done on the previous step | |
462 | # | |
463 | def test_rib_ipv4_step5(): | |
464 | logger.info("Test (step 5): verify IPv4 RIB") | |
465 | tgen = get_topogen() | |
466 | ||
467 | # Skip if previous fatal error condition is raised | |
468 | if tgen.routers_have_failure(): | |
469 | pytest.skip(tgen.errors) | |
470 | ||
9fa6ec14 | 471 | logger.info("Enabling SR on rt4") |
472 | tgen.net["rt4"].cmd('vtysh -c "conf t" -c "router isis 1" -c "segment-routing on"') | |
473 | ||
474 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: | |
475 | router_compare_json_output( | |
476 | rname, "show ip route isis json", outputs[rname][5]["show_ip_route.ref"] | |
477 | ) | |
9687c500 | 478 | |
9687c500 RW |
479 | |
480 | def test_rib_ipv6_step5(): | |
481 | logger.info("Test (step 5): verify IPv6 RIB") | |
482 | tgen = get_topogen() | |
483 | ||
484 | # Skip if previous fatal error condition is raised | |
485 | if tgen.routers_have_failure(): | |
486 | pytest.skip(tgen.errors) | |
487 | ||
9fa6ec14 | 488 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
489 | router_compare_json_output( | |
490 | rname, "show ipv6 route isis json", outputs[rname][5]["show_ipv6_route.ref"] | |
491 | ) | |
492 | ||
9687c500 RW |
493 | |
494 | def test_mpls_lib_step5(): | |
495 | logger.info("Test (step 5): verify MPLS LIB") | |
496 | tgen = get_topogen() | |
497 | ||
498 | # Skip if previous fatal error condition is raised | |
499 | if tgen.routers_have_failure(): | |
500 | pytest.skip(tgen.errors) | |
501 | ||
9fa6ec14 | 502 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
503 | router_compare_json_output( | |
504 | rname, "show mpls table json", outputs[rname][5]["show_mpls_table.ref"] | |
505 | ) | |
506 | ||
9687c500 RW |
507 | |
508 | # | |
509 | # Step 6 | |
510 | # | |
511 | # Action(s): | |
512 | # -Change rt5's SRGB | |
513 | # | |
514 | # Expected changes: | |
515 | # -All routers should update all SR labels for destinations whose primary or backup nexthop is rt5 | |
516 | # | |
517 | def test_rib_ipv4_step6(): | |
518 | logger.info("Test (step 6): verify IPv4 RIB") | |
519 | tgen = get_topogen() | |
520 | ||
521 | # Skip if previous fatal error condition is raised | |
522 | if tgen.routers_have_failure(): | |
523 | pytest.skip(tgen.errors) | |
524 | ||
9fa6ec14 | 525 | logger.info("Changing rt5's SRGB") |
526 | tgen.net["rt5"].cmd( | |
527 | 'vtysh -c "conf t" -c "router isis 1" -c "segment-routing global-block 30000 37999"' | |
528 | ) | |
529 | ||
530 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: | |
531 | router_compare_json_output( | |
532 | rname, "show ip route isis json", outputs[rname][6]["show_ip_route.ref"] | |
533 | ) | |
9687c500 | 534 | |
9687c500 RW |
535 | |
536 | def test_rib_ipv6_step6(): | |
537 | logger.info("Test (step 6): verify IPv6 RIB") | |
538 | tgen = get_topogen() | |
539 | ||
540 | # Skip if previous fatal error condition is raised | |
541 | if tgen.routers_have_failure(): | |
542 | pytest.skip(tgen.errors) | |
543 | ||
9fa6ec14 | 544 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
545 | router_compare_json_output( | |
546 | rname, "show ipv6 route isis json", outputs[rname][6]["show_ipv6_route.ref"] | |
547 | ) | |
548 | ||
9687c500 RW |
549 | |
550 | def test_mpls_lib_step6(): | |
551 | logger.info("Test (step 6): verify MPLS LIB") | |
552 | tgen = get_topogen() | |
553 | ||
554 | # Skip if previous fatal error condition is raised | |
555 | if tgen.routers_have_failure(): | |
556 | pytest.skip(tgen.errors) | |
557 | ||
9fa6ec14 | 558 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
559 | router_compare_json_output( | |
560 | rname, "show mpls table json", outputs[rname][6]["show_mpls_table.ref"] | |
561 | ) | |
562 | ||
9687c500 RW |
563 | |
564 | # | |
565 | # Step 7 | |
566 | # | |
567 | # Action(s): | |
568 | # -Delete rt5's Prefix-SIDs | |
569 | # | |
570 | # Expected changes: | |
571 | # -All routers should uninstall rt5's Prefix-SIDs | |
572 | # -All routers should uninstall all TI-LFA backup nexthops that use rt5's Prefix-SIDs | |
573 | # | |
574 | def test_rib_ipv4_step7(): | |
575 | logger.info("Test (step 7): verify IPv4 RIB") | |
576 | tgen = get_topogen() | |
577 | ||
578 | # Skip if previous fatal error condition is raised | |
579 | if tgen.routers_have_failure(): | |
580 | pytest.skip(tgen.errors) | |
581 | ||
9fa6ec14 | 582 | logger.info("Deleting rt5's Prefix-SIDs") |
583 | tgen.net["rt5"].cmd( | |
584 | 'vtysh -c "conf t" -c "router isis 1" -c "no segment-routing prefix 5.5.5.5/32 index 50"' | |
585 | ) | |
586 | tgen.net["rt5"].cmd( | |
587 | 'vtysh -c "conf t" -c "router isis 1" -c "no segment-routing prefix 2001:db8:1000::5/128 index 51"' | |
588 | ) | |
589 | ||
590 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: | |
591 | router_compare_json_output( | |
592 | rname, "show ip route isis json", outputs[rname][7]["show_ip_route.ref"] | |
593 | ) | |
9687c500 | 594 | |
9687c500 RW |
595 | |
596 | def test_rib_ipv6_step7(): | |
597 | logger.info("Test (step 7): verify IPv6 RIB") | |
598 | tgen = get_topogen() | |
599 | ||
600 | # Skip if previous fatal error condition is raised | |
601 | if tgen.routers_have_failure(): | |
602 | pytest.skip(tgen.errors) | |
603 | ||
9fa6ec14 | 604 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
605 | router_compare_json_output( | |
606 | rname, "show ipv6 route isis json", outputs[rname][7]["show_ipv6_route.ref"] | |
607 | ) | |
608 | ||
9687c500 RW |
609 | |
610 | def test_mpls_lib_step7(): | |
611 | logger.info("Test (step 7): verify MPLS LIB") | |
612 | tgen = get_topogen() | |
613 | ||
614 | # Skip if previous fatal error condition is raised | |
615 | if tgen.routers_have_failure(): | |
616 | pytest.skip(tgen.errors) | |
617 | ||
9fa6ec14 | 618 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
619 | router_compare_json_output( | |
620 | rname, "show mpls table json", outputs[rname][7]["show_mpls_table.ref"] | |
621 | ) | |
622 | ||
9687c500 RW |
623 | |
624 | # | |
625 | # Step 8 | |
626 | # | |
627 | # Action(s): | |
628 | # -Re-add rt5's Prefix-SIDs | |
629 | # | |
630 | # Expected changes: | |
631 | # -Reverse all changes done on the previous step | |
632 | # | |
633 | def test_rib_ipv4_step8(): | |
634 | logger.info("Test (step 8): verify IPv4 RIB") | |
635 | tgen = get_topogen() | |
636 | ||
637 | # Skip if previous fatal error condition is raised | |
638 | if tgen.routers_have_failure(): | |
639 | pytest.skip(tgen.errors) | |
640 | ||
9fa6ec14 | 641 | logger.info("Re-adding rt5's Prefix-SIDs") |
642 | tgen.net["rt5"].cmd( | |
643 | 'vtysh -c "conf t" -c "router isis 1" -c "segment-routing prefix 5.5.5.5/32 index 50"' | |
644 | ) | |
645 | tgen.net["rt5"].cmd( | |
646 | 'vtysh -c "conf t" -c "router isis 1" -c "segment-routing prefix 2001:db8:1000::5/128 index 51"' | |
647 | ) | |
648 | ||
649 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: | |
650 | router_compare_json_output( | |
651 | rname, "show ip route isis json", outputs[rname][8]["show_ip_route.ref"] | |
652 | ) | |
9687c500 | 653 | |
9687c500 RW |
654 | |
655 | def test_rib_ipv6_step8(): | |
656 | logger.info("Test (step 8): verify IPv6 RIB") | |
657 | tgen = get_topogen() | |
658 | ||
659 | # Skip if previous fatal error condition is raised | |
660 | if tgen.routers_have_failure(): | |
661 | pytest.skip(tgen.errors) | |
662 | ||
9fa6ec14 | 663 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
664 | router_compare_json_output( | |
665 | rname, "show ipv6 route isis json", outputs[rname][8]["show_ipv6_route.ref"] | |
666 | ) | |
667 | ||
9687c500 RW |
668 | |
669 | def test_mpls_lib_step8(): | |
670 | logger.info("Test (step 8): verify MPLS LIB") | |
671 | tgen = get_topogen() | |
672 | ||
673 | # Skip if previous fatal error condition is raised | |
674 | if tgen.routers_have_failure(): | |
675 | pytest.skip(tgen.errors) | |
676 | ||
9fa6ec14 | 677 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
678 | router_compare_json_output( | |
679 | rname, "show mpls table json", outputs[rname][8]["show_mpls_table.ref"] | |
680 | ) | |
681 | ||
9687c500 RW |
682 | |
683 | # | |
684 | # Step 9 | |
685 | # | |
686 | # Action(s): | |
687 | # -Change rt5's Prefix-SIDs | |
688 | # | |
689 | # Expected changes: | |
690 | # -All routers should update rt5's Prefix-SIDs | |
691 | # -All routers should update all TI-LFA backup nexthops that use rt5's Prefix-SIDs | |
692 | # | |
693 | def test_rib_ipv4_step9(): | |
694 | logger.info("Test (step 9): verify IPv4 RIB") | |
695 | tgen = get_topogen() | |
696 | ||
697 | # Skip if previous fatal error condition is raised | |
698 | if tgen.routers_have_failure(): | |
699 | pytest.skip(tgen.errors) | |
700 | ||
9fa6ec14 | 701 | logger.info("Re-adding rt5's Prefix-SIDs") |
702 | tgen.net["rt5"].cmd( | |
703 | 'vtysh -c "conf t" -c "router isis 1" -c "segment-routing prefix 5.5.5.5/32 index 500"' | |
704 | ) | |
705 | tgen.net["rt5"].cmd( | |
706 | 'vtysh -c "conf t" -c "router isis 1" -c "segment-routing prefix 2001:db8:1000::5/128 index 501"' | |
707 | ) | |
708 | ||
709 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: | |
710 | router_compare_json_output( | |
711 | rname, "show ip route isis json", outputs[rname][9]["show_ip_route.ref"] | |
712 | ) | |
9687c500 | 713 | |
9687c500 RW |
714 | |
715 | def test_rib_ipv6_step9(): | |
716 | logger.info("Test (step 9): verify IPv6 RIB") | |
717 | tgen = get_topogen() | |
718 | ||
719 | # Skip if previous fatal error condition is raised | |
720 | if tgen.routers_have_failure(): | |
721 | pytest.skip(tgen.errors) | |
722 | ||
9fa6ec14 | 723 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
724 | router_compare_json_output( | |
725 | rname, "show ipv6 route isis json", outputs[rname][9]["show_ipv6_route.ref"] | |
726 | ) | |
727 | ||
9687c500 RW |
728 | |
729 | def test_mpls_lib_step9(): | |
730 | logger.info("Test (step 9): verify MPLS LIB") | |
731 | tgen = get_topogen() | |
732 | ||
733 | # Skip if previous fatal error condition is raised | |
734 | if tgen.routers_have_failure(): | |
735 | pytest.skip(tgen.errors) | |
736 | ||
9fa6ec14 | 737 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: |
738 | router_compare_json_output( | |
739 | rname, "show mpls table json", outputs[rname][9]["show_mpls_table.ref"] | |
740 | ) | |
741 | ||
9687c500 | 742 | |
f3529a55 LS |
743 | # |
744 | # Step 10 | |
745 | # | |
746 | # Action(s): | |
747 | # - Setting spf-delay-ietf init-delay of 15s | |
748 | # | |
749 | # Expected changes: | |
750 | # - No routing table change | |
751 | # - At the end of test, SPF reacts to a failure in 15s | |
752 | # | |
753 | def test_rib_ipv4_step10(): | |
754 | logger.info("Test (step 10): verify IPv4 RIB") | |
755 | tgen = get_topogen() | |
756 | ||
757 | # Skip if previous fatal error condition is raised | |
758 | if tgen.routers_have_failure(): | |
759 | pytest.skip(tgen.errors) | |
760 | ||
761 | logger.info("Setting spf-delay-ietf init-delay of 15s") | |
762 | tgen.net["rt6"].cmd( | |
763 | '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"' | |
764 | ) | |
765 | ||
766 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: | |
767 | router_compare_json_output( | |
768 | rname, "show ip route isis json", outputs[rname][10]["show_ip_route.ref"] | |
769 | ) | |
770 | ||
771 | ||
772 | def test_rib_ipv6_step10(): | |
773 | logger.info("Test (step 10): verify IPv6 RIB") | |
774 | tgen = get_topogen() | |
775 | ||
776 | # Skip if previous fatal error condition is raised | |
777 | if tgen.routers_have_failure(): | |
778 | pytest.skip(tgen.errors) | |
779 | ||
780 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: | |
781 | router_compare_json_output( | |
782 | rname, | |
783 | "show ipv6 route isis json", | |
784 | outputs[rname][10]["show_ipv6_route.ref"], | |
785 | ) | |
786 | ||
787 | ||
788 | def test_mpls_lib_step10(): | |
789 | logger.info("Test (step 10): verify MPLS LIB") | |
790 | tgen = get_topogen() | |
791 | ||
792 | # Skip if previous fatal error condition is raised | |
793 | if tgen.routers_have_failure(): | |
794 | pytest.skip(tgen.errors) | |
795 | ||
796 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: | |
797 | router_compare_json_output( | |
798 | rname, "show mpls table json", outputs[rname][10]["show_mpls_table.ref"] | |
799 | ) | |
800 | ||
801 | ||
802 | # | |
803 | # Step 11 | |
804 | # | |
805 | # Action(s): | |
806 | # - shut the eth-rt5 interface on rt6 | |
807 | # | |
808 | # Expected changes: | |
809 | # - Route switchover of routes via eth-rt5 | |
810 | # | |
811 | def test_rt6_step11(): | |
812 | logger.info( | |
813 | "Test (step 11): Check IPv4/6 RIB and MPLS table after a LFA switchover" | |
814 | ) | |
815 | tgen = get_topogen() | |
816 | ||
817 | # Skip if previous fatal error condition is raised | |
818 | if tgen.routers_have_failure(): | |
819 | pytest.skip(tgen.errors) | |
820 | ||
821 | logger.info( | |
822 | "Shut a rt6 interface to rt5 from the switch side and check fast-reroute" | |
823 | ) | |
824 | tgen.net.cmd_raises("ip link set %s down" % tgen.net["s8"].intfs[1]) | |
825 | ||
826 | rname = "rt6" | |
827 | router_compare_json_output( | |
828 | rname, | |
829 | "show ip route isis json", | |
830 | outputs[rname][11]["show_ip_route.ref"], | |
831 | count=1, | |
832 | ) | |
833 | router_compare_json_output( | |
834 | rname, | |
835 | "show ipv6 route isis json", | |
836 | outputs[rname][11]["show_ipv6_route.ref"], | |
837 | count=1, | |
838 | ) | |
839 | router_compare_json_output( | |
840 | rname, | |
841 | "show mpls table json", | |
842 | outputs[rname][11]["show_mpls_table.ref"], | |
843 | count=1, | |
844 | ) | |
845 | ||
846 | ||
847 | # | |
848 | # Step 12 | |
849 | # | |
850 | # Action(s): wait for the convergence and SPF computation on rt6 | |
851 | # | |
852 | # Expected changes: | |
853 | # - convergence of IPv4/6 RIB and MPLS table | |
854 | # | |
855 | def test_rib_ipv4_step12(): | |
856 | logger.info("Test (step 12): verify IPv4 RIB") | |
857 | tgen = get_topogen() | |
858 | ||
859 | # Skip if previous fatal error condition is raised | |
860 | if tgen.routers_have_failure(): | |
861 | pytest.skip(tgen.errors) | |
862 | ||
863 | logger.info("Check SPF convergence") | |
864 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: | |
865 | router_compare_json_output( | |
866 | rname, | |
867 | "show ip route isis json", | |
868 | outputs[rname][12]["show_ip_route.ref"], | |
869 | ) | |
870 | ||
871 | ||
872 | def test_rib_ipv6_step12(): | |
873 | logger.info("Test (step 12): verify IPv6 RIB") | |
874 | tgen = get_topogen() | |
875 | ||
876 | # Skip if previous fatal error condition is raised | |
877 | if tgen.routers_have_failure(): | |
878 | pytest.skip(tgen.errors) | |
879 | ||
880 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: | |
881 | router_compare_json_output( | |
882 | rname, | |
883 | "show ipv6 route isis json", | |
884 | outputs[rname][12]["show_ipv6_route.ref"], | |
885 | ) | |
886 | ||
887 | ||
888 | def test_mpls_lib_step12(): | |
889 | logger.info("Test (step 12): verify MPLS LIB") | |
890 | tgen = get_topogen() | |
891 | ||
892 | # Skip if previous fatal error condition is raised | |
893 | if tgen.routers_have_failure(): | |
894 | pytest.skip(tgen.errors) | |
895 | ||
896 | for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]: | |
897 | router_compare_json_output( | |
898 | rname, | |
899 | "show mpls table json", | |
900 | outputs[rname][12]["show_mpls_table.ref"], | |
901 | ) | |
902 | ||
903 | ||
9687c500 RW |
904 | # Memory leak test template |
905 | def test_memory_leak(): | |
906 | "Run the memory leak test and report results." | |
907 | tgen = get_topogen() | |
908 | if not tgen.is_memleak_enabled(): | |
9fa6ec14 | 909 | pytest.skip("Memory leak test/report is disabled") |
9687c500 RW |
910 | |
911 | tgen.report_memory_leaks() | |
912 | ||
9fa6ec14 | 913 | |
914 | if __name__ == "__main__": | |
9687c500 RW |
915 | args = ["-s"] + sys.argv[1:] |
916 | sys.exit(pytest.main(args)) |