]>
git.proxmox.com Git - mirror_frr.git/blob - tests/topotests/isis_sr_te_topo1/test_isis_sr_te_topo1.py
4 # test_isis_sr_topo1.py
5 # Part of NetDEF Topology Tests
7 # Copyright (c) 2019 by
8 # Network Device Education Foundation, Inc. ("NetDEF")
10 # Permission to use, copy, modify, and/or distribute this software
11 # for any purpose with or without fee is hereby granted, provided
12 # that the above copyright notice and this permission notice appear
15 # THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
16 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
18 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
19 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
21 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
26 test_isis_sr_te_topo1.py:
38 +---------+ | +---------+
40 | RT2 |eth-sw1 | eth-sw1| RT3 |
41 | 2.2.2.2 +----------+----------+ 3.3.3.3 |
43 +---------+ +---------+
44 eth-rt4-1| |eth-rt4-2 eth-rt5-1| |eth-rt5-2
46 10.0.2.0/24| |10.0.3.0/24 10.0.4.0/24| |10.0.5.0/24
48 eth-rt2-1| |eth-rt2-2 eth-rt3-1| |eth-rt3-2
49 +---------+ +---------+
51 | RT4 | 10.0.6.0/24 | RT5 |
52 | 4.4.4.4 +---------------------+ 5.5.5.5 |
54 +---------+ +---------+
57 10.0.7.0/24| |10.0.8.0/24
61 +----------+ 6.6.6.6 +-----------+
82 from functools
import partial
84 # Save the Current Working Directory to find configuration files.
85 CWD
= os
.path
.dirname(os
.path
.realpath(__file__
))
86 sys
.path
.append(os
.path
.join(CWD
, "../"))
88 # pylint: disable=C0413
89 # Import topogen and topotest helpers
90 from lib
import topotest
91 from lib
.topogen
import Topogen
, TopoRouter
, get_topogen
92 from lib
.topolog
import logger
94 # Required to instantiate the topology builder class.
96 pytestmark
= [pytest
.mark
.bgpd
, pytest
.mark
.isisd
, pytest
.mark
.pathd
]
105 for router
in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "dst"]:
106 tgen
.add_router(router
)
111 switch
= tgen
.add_switch("s1")
112 switch
.add_link(tgen
.gears
["rt1"], nodeif
="eth-sw1")
113 switch
.add_link(tgen
.gears
["rt2"], nodeif
="eth-sw1")
114 switch
.add_link(tgen
.gears
["rt3"], nodeif
="eth-sw1")
116 switch
= tgen
.add_switch("s2")
117 switch
.add_link(tgen
.gears
["rt2"], nodeif
="eth-rt4-1")
118 switch
.add_link(tgen
.gears
["rt4"], nodeif
="eth-rt2-1")
120 switch
= tgen
.add_switch("s3")
121 switch
.add_link(tgen
.gears
["rt2"], nodeif
="eth-rt4-2")
122 switch
.add_link(tgen
.gears
["rt4"], nodeif
="eth-rt2-2")
124 switch
= tgen
.add_switch("s4")
125 switch
.add_link(tgen
.gears
["rt3"], nodeif
="eth-rt5-1")
126 switch
.add_link(tgen
.gears
["rt5"], nodeif
="eth-rt3-1")
128 switch
= tgen
.add_switch("s5")
129 switch
.add_link(tgen
.gears
["rt3"], nodeif
="eth-rt5-2")
130 switch
.add_link(tgen
.gears
["rt5"], nodeif
="eth-rt3-2")
132 switch
= tgen
.add_switch("s6")
133 switch
.add_link(tgen
.gears
["rt4"], nodeif
="eth-rt5")
134 switch
.add_link(tgen
.gears
["rt5"], nodeif
="eth-rt4")
136 switch
= tgen
.add_switch("s7")
137 switch
.add_link(tgen
.gears
["rt4"], nodeif
="eth-rt6")
138 switch
.add_link(tgen
.gears
["rt6"], nodeif
="eth-rt4")
140 switch
= tgen
.add_switch("s8")
141 switch
.add_link(tgen
.gears
["rt5"], nodeif
="eth-rt6")
142 switch
.add_link(tgen
.gears
["rt6"], nodeif
="eth-rt5")
144 switch
= tgen
.add_switch("s9")
145 switch
.add_link(tgen
.gears
["rt6"], nodeif
="eth-dst")
146 switch
.add_link(tgen
.gears
["dst"], nodeif
="eth-rt6")
149 def setup_module(mod
):
150 "Sets up the pytest environment"
152 tgen
= Topogen(build_topo
, mod
.__name
__)
154 frrdir
= tgen
.config
.get(tgen
.CONFIG_SECTION
, "frrdir")
155 if not os
.path
.isfile(os
.path
.join(frrdir
, "pathd")):
156 pytest
.skip("pathd daemon wasn't built")
158 tgen
.start_topology()
160 router_list
= tgen
.routers()
162 # For all registered routers, load the zebra configuration file
163 for rname
, router
in router_list
.items():
165 TopoRouter
.RD_ZEBRA
, os
.path
.join(CWD
, "{}/zebra.conf".format(rname
))
168 TopoRouter
.RD_ISIS
, os
.path
.join(CWD
, "{}/isisd.conf".format(rname
))
171 TopoRouter
.RD_PATH
, os
.path
.join(CWD
, "{}/pathd.conf".format(rname
))
174 TopoRouter
.RD_BGP
, os
.path
.join(CWD
, "{}/bgpd.conf".format(rname
))
180 def teardown_module(mod
):
181 "Teardown the pytest environment"
184 # This function tears down the whole topology.
188 def setup_testcase(msg
):
192 # Skip if previous fatal error condition is raised
193 if tgen
.routers_have_failure():
194 pytest
.skip(tgen
.errors
)
199 def print_cmd_result(rname
, command
):
200 print(get_topogen().gears
[rname
].vtysh_cmd(command
, isjson
=False))
203 def compare_json_test(router
, command
, reference
, exact
):
204 output
= router
.vtysh_cmd(command
, isjson
=True)
205 result
= topotest
.json_cmp(output
, reference
)
207 # Note: topotest.json_cmp() just checks on inclusion of keys.
208 # For exact matching also compare the other way around.
209 if not result
and exact
:
210 return topotest
.json_cmp(reference
, output
)
215 def cmp_json_output(rname
, command
, reference
, exact
=False):
216 "Compare router JSON output"
218 logger
.info('Comparing router "%s" "%s" output', rname
, command
)
221 filename
= "{}/{}/{}".format(CWD
, rname
, reference
)
222 expected
= json
.loads(open(filename
).read())
224 # Run test function until we get an result. Wait at most 60 seconds.
225 test_func
= partial(compare_json_test
, tgen
.gears
[rname
], command
, expected
, exact
)
226 _
, diff
= topotest
.run_and_expect(test_func
, None, count
=120, wait
=0.5)
227 assertmsg
= '"{}" JSON output mismatches the expected result'.format(rname
)
228 assert diff
is None, assertmsg
231 def cmp_json_output_exact(rname
, command
, reference
):
232 return cmp_json_output(rname
, command
, reference
, True)
235 def add_candidate_path(rname
, endpoint
, pref
, name
, segment_list
="default"):
236 get_topogen().net
[rname
].cmd(
239 -c "segment-routing" \
241 -c "policy color 1 endpoint """
244 -c "candidate-path preference """
248 + """ explicit segment-list """
254 def delete_candidate_path(rname
, endpoint
, pref
):
255 get_topogen().net
[rname
].cmd(
258 -c "segment-routing" \
260 -c "policy color 1 endpoint """
263 -c "no candidate-path preference """
269 def add_segment(rname
, name
, index
, label
):
270 get_topogen().net
[rname
].cmd(
273 -c "segment-routing" \
286 def delete_segment(rname
, name
, index
):
287 get_topogen().net
[rname
].cmd(
290 -c "segment-routing" \
301 def create_sr_policy(rname
, endpoint
, bsid
):
302 get_topogen().net
[rname
].cmd(
305 -c "segment-routing" \
307 -c "policy color 1 endpoint """
317 def delete_sr_policy(rname
, endpoint
):
318 get_topogen().net
[rname
].cmd(
321 -c "segment-routing" \
323 -c "no policy color 1 endpoint """
329 def create_prefix_sid(rname
, prefix
, sid
):
330 get_topogen().net
[rname
].cmd(
334 -c "segment-routing prefix """
342 def delete_prefix_sid(rname
, prefix
):
343 get_topogen().net
[rname
].cmd(
347 -c "no segment-routing prefix "'''
355 # Checking the MPLS table using a single SR Policy and a single Candidate Path
357 def test_srte_init_step1():
358 setup_testcase("Test (step 1): wait for IS-IS convergence / label distribution")
360 for rname
in ["rt1", "rt6"]:
362 rname
, "show mpls table json", "step1/show_mpls_table_without_candidate.ref"
366 def test_srte_add_candidate_check_mpls_table_step1():
367 setup_testcase("Test (step 1): check MPLS table regarding the added Candidate Path")
369 for rname
, endpoint
in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
370 add_candidate_path(rname
, endpoint
, 100, "default")
372 rname
, "show mpls table json", "step1/show_mpls_table_with_candidate.ref"
374 delete_candidate_path(rname
, endpoint
, 100)
377 def test_srte_reinstall_sr_policy_check_mpls_table_step1():
379 "Test (step 1): check MPLS table after the SR Policy was removed and reinstalled"
382 for rname
, endpoint
, bsid
in [("rt1", "6.6.6.6", 1111), ("rt6", "1.1.1.1", 6666)]:
383 add_candidate_path(rname
, endpoint
, 100, "default")
384 delete_sr_policy(rname
, endpoint
)
386 rname
, "show mpls table json", "step1/show_mpls_table_without_candidate.ref"
388 create_sr_policy(rname
, endpoint
, bsid
)
389 add_candidate_path(rname
, endpoint
, 100, "default")
391 rname
, "show mpls table json", "step1/show_mpls_table_with_candidate.ref"
393 delete_candidate_path(rname
, endpoint
, 100)
399 # Checking pathd operational data using a single SR Policy and a single Candidate Path
401 def test_srte_bare_policy_step2():
402 setup_testcase("Test (step 2): bare SR Policy should not be operational")
404 for rname
in ["rt1", "rt6"]:
405 cmp_json_output_exact(
407 "show yang operational-data /frr-pathd:pathd pathd",
408 "step2/show_operational_data.ref",
412 def test_srte_add_candidate_check_operational_data_step2():
414 "Test (step 2): add single Candidate Path, SR Policy should be operational"
417 for rname
, endpoint
in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
418 add_candidate_path(rname
, endpoint
, 100, "default")
421 "show yang operational-data /frr-pathd:pathd pathd",
422 "step2/show_operational_data_with_candidate.ref",
426 def test_srte_config_remove_candidate_check_operational_data_step2():
428 "Test (step 2): remove single Candidate Path, SR Policy should not be operational anymore"
431 for rname
, endpoint
in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
432 delete_candidate_path(rname
, endpoint
, 100)
433 cmp_json_output_exact(
435 "show yang operational-data /frr-pathd:pathd pathd",
436 "step2/show_operational_data.ref",
443 # Testing the Candidate Path selection
445 def test_srte_add_two_candidates_step3():
446 setup_testcase("Test (step 3): second Candidate Path has higher Priority")
448 for rname
, endpoint
in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
449 for pref
, cand_name
in [("100", "first"), ("200", "second")]:
450 add_candidate_path(rname
, endpoint
, pref
, cand_name
)
453 "show yang operational-data /frr-pathd:pathd pathd",
454 "step3/show_operational_data_with_two_candidates.ref",
458 for rname
, endpoint
in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
459 for pref
in ["100", "200"]:
460 delete_candidate_path(rname
, endpoint
, pref
)
463 def test_srte_add_two_candidates_with_reverse_priority_step3():
464 setup_testcase("Test (step 3): second Candidate Path has lower Priority")
466 # Use reversed priorities here
467 for rname
, endpoint
in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
468 for pref
, cand_name
in [("200", "first"), ("100", "second")]:
469 add_candidate_path(rname
, endpoint
, pref
, cand_name
)
472 "show yang operational-data /frr-pathd:pathd pathd",
473 "step3/show_operational_data_with_two_candidates.ref",
477 for rname
, endpoint
in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
478 for pref
in ["100", "200"]:
479 delete_candidate_path(rname
, endpoint
, pref
)
482 def test_srte_remove_best_candidate_step3():
483 setup_testcase("Test (step 3): delete the Candidate Path with higher priority")
485 for rname
, endpoint
in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
486 for pref
, cand_name
in [("100", "first"), ("200", "second")]:
487 add_candidate_path(rname
, endpoint
, pref
, cand_name
)
489 # Delete candidate with higher priority
490 for rname
, endpoint
in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
491 delete_candidate_path(rname
, endpoint
, 200)
493 # Candidate with lower priority should get active now
494 for rname
, endpoint
in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
497 "show yang operational-data /frr-pathd:pathd pathd",
498 "step3/show_operational_data_with_single_candidate.ref",
501 delete_candidate_path(rname
, endpoint
, 100)
507 # Checking MPLS table with a single SR Policy and a Candidate Path with different Segment Lists and other modifications
509 def test_srte_change_segment_list_check_mpls_table_step4():
510 setup_testcase("Test (step 4): check MPLS table for changed Segment List")
512 for rname
, endpoint
in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
513 add_candidate_path(rname
, endpoint
, 100, "default")
514 # now change the segment list name
515 add_candidate_path(rname
, endpoint
, 100, "default", "test")
516 cmp_json_output(rname
, "show mpls table json", "step4/show_mpls_table.ref")
517 delete_candidate_path(rname
, endpoint
, 100)
520 def test_srte_segment_list_add_segment_check_mpls_table_step4():
522 "Test (step 4): check MPLS table for added (then changed and finally deleted) segment"
525 add_candidate_path("rt1", "6.6.6.6", 100, "default", "test")
527 # first add a new segment
528 add_segment("rt1", "test", 25, 16050)
530 "rt1", "show mpls table json", "step4/show_mpls_table_add_segment.ref"
533 # ... then change it ...
534 add_segment("rt1", "test", 25, 16030)
536 "rt1", "show mpls table json", "step4/show_mpls_table_change_segment.ref"
539 # ... and finally delete it
540 delete_segment("rt1", "test", 25)
541 cmp_json_output("rt1", "show mpls table json", "step4/show_mpls_table.ref")
542 delete_candidate_path("rt1", "6.6.6.6", 100)
548 # Checking the nexthop using a single SR Policy and a Candidate Path with configured route-map
550 def test_srte_route_map_with_sr_policy_check_nextop_step5():
552 "Test (step 5): recursive nexthop learned through BGP neighbour should be aligned with SR Policy from route-map"
555 # (re-)build the SR Policy two times to ensure that reinstalling still works
558 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_inactive_srte.ref"
561 delete_sr_policy("rt1", "6.6.6.6")
563 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_inactive_srte.ref"
566 create_sr_policy("rt1", "6.6.6.6", 1111)
568 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_inactive_srte.ref"
571 add_candidate_path("rt1", "6.6.6.6", 100, "default")
573 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
576 delete_candidate_path("rt1", "6.6.6.6", 100)
579 def test_srte_route_map_with_sr_policy_reinstall_prefix_sid_check_nextop_step5():
581 "Test (step 5): remove and re-install prefix SID on fist path element and check SR Policy activity"
584 # first add a candidate path so the SR Policy is active
585 add_candidate_path("rt1", "6.6.6.6", 100, "default")
588 "show yang operational-data /frr-pathd:pathd pathd",
589 "step5/show_operational_data_active.ref",
592 # delete prefix SID from first element of the configured path and check
593 # if the SR Policy is inactive since the label can't be resolved anymore
594 delete_prefix_sid("rt5", "5.5.5.5/32")
597 "show yang operational-data /frr-pathd:pathd pathd",
598 "step5/show_operational_data_inactive.ref",
601 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_inactive_srte.ref"
604 # re-create the prefix SID and check if the SR Policy is active
605 create_prefix_sid("rt5", "5.5.5.5/32", 50)
608 "show yang operational-data /frr-pathd:pathd pathd",
609 "step5/show_operational_data_active.ref",
612 "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
616 # Memory leak test template
617 def test_memory_leak():
618 "Run the memory leak test and report results."
620 if not tgen
.is_memleak_enabled():
621 pytest
.skip("Memory leak test/report is disabled")
623 tgen
.report_memory_leaks()
626 if __name__
== "__main__":
627 args
= ["-s"] + sys
.argv
[1:]
628 sys
.exit(pytest
.main(args
))