diff options
author | Russ White <russ@riw.us> | 2025-01-07 22:14:15 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-07 22:14:15 +0100 |
commit | 21fe1f4d83502ac1c2262913c1a98441ea89bf24 (patch) | |
tree | b31fb24ba651d3a52fc6d1b2dff584059d2c51e3 /tests | |
parent | Merge pull request #17772 from LabNConsulting/chopps/fix-oper-walk (diff) | |
parent | tests: ospf6_ecmp_inter_area, no shutdown r7/r8 eth3 (diff) | |
download | frr-21fe1f4d83502ac1c2262913c1a98441ea89bf24.tar.xz frr-21fe1f4d83502ac1c2262913c1a98441ea89bf24.zip |
Merge pull request #17707 from gromit1811/pr16811_rebased
tests: cleanup ospf6 ecmp inter area
Diffstat (limited to 'tests')
6 files changed, 448 insertions, 54 deletions
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r1/show_ipv6_routes_ospf6-1.json b/tests/topotests/ospf6_ecmp_inter_area/r1/show_ipv6_routes_ospf6-1.json new file mode 100644 index 000000000..ff2cf3119 --- /dev/null +++ b/tests/topotests/ospf6_ecmp_inter_area/r1/show_ipv6_routes_ospf6-1.json @@ -0,0 +1,155 @@ +{ + "2001:db8:2::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth0", + "active": true + } + ] + } + ], + "2001:db8:3::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth1", + "active": true + } + ] + } + ], + "2001:db8:4::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + } + ] + } + ], + "2001:db8:5::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth0", + "active": true + } + ] + } + ], + "2001:db8:6::/64": [ + { + "internalNextHopActiveNum": 2, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + }, + { + "fib": true, + "interfaceName": "r1-eth1", + "active": true + } + ] + } + ], + "2001:db8:7::/64": [ + { + "internalNextHopActiveNum": 3, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + }, + { + "fib": true, + "interfaceName": "r1-eth0", + "active": true + }, + { + "fib": true, + "interfaceName": "r1-eth1", + "active": true + } + ] + } + ], + "2001:db8:8::/64": [ + { + "internalNextHopActiveNum": 3, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + }, + { + "fib": true, + "interfaceName": "r1-eth0", + "active": true + }, + { + "fib": true, + "interfaceName": "r1-eth1", + "active": true + } + ] + } + ], + "2001:db8:8007::/64": [ + { + "internalNextHopActiveNum": 3, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + }, + { + "fib": true, + "interfaceName": "r1-eth0", + "active": true + }, + { + "fib": true, + "interfaceName": "r1-eth1", + "active": true + } + ] + } + ], + "2001:db8:8008::/64": [ + { + "internalNextHopActiveNum": 3, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + }, + { + "fib": true, + "interfaceName": "r1-eth0", + "active": true + }, + { + "fib": true, + "interfaceName": "r1-eth1", + "active": true + } + ] + } + ] +} diff --git a/tests/topotests/ospf6_ecmp_inter_area/r1/show_ipv6_routes_ospf6-2.json b/tests/topotests/ospf6_ecmp_inter_area/r1/show_ipv6_routes_ospf6-2.json new file mode 100644 index 000000000..8918feb96 --- /dev/null +++ b/tests/topotests/ospf6_ecmp_inter_area/r1/show_ipv6_routes_ospf6-2.json @@ -0,0 +1,130 @@ +{ + "2001:db8:2::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth0", + "active": true + } + ] + } + ], + "2001:db8:3::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth1", + "active": true + } + ] + } + ], + "2001:db8:4::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + } + ] + } + ], + "2001:db8:5::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth0", + "active": true + } + ] + } + ], + "2001:db8:6::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + } + ] + } + ], + "2001:db8:7::/64": [ + { + "internalNextHopActiveNum": 2, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + }, + { + "fib": true, + "interfaceName": "r1-eth0", + "active": true + } + ] + } + ], + "2001:db8:8::/64": [ + { + "internalNextHopActiveNum": 2, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + }, + { + "fib": true, + "interfaceName": "r1-eth0", + "active": true + } + ] + } + ], + "2001:db8:8007::/64": [ + { + "internalNextHopActiveNum": 2, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + }, + { + "fib": true, + "interfaceName": "r1-eth0", + "active": true + } + ] + } + ], + "2001:db8:8008::/64": [ + { + "internalNextHopActiveNum": 2, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + }, + { + "fib": true, + "interfaceName": "r1-eth0", + "active": true + } + ] + } + ] +} diff --git a/tests/topotests/ospf6_ecmp_inter_area/r1/show_ipv6_routes_ospf6-3.json b/tests/topotests/ospf6_ecmp_inter_area/r1/show_ipv6_routes_ospf6-3.json new file mode 100644 index 000000000..99ceb036d --- /dev/null +++ b/tests/topotests/ospf6_ecmp_inter_area/r1/show_ipv6_routes_ospf6-3.json @@ -0,0 +1,110 @@ +{ + "2001:db8:2::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth0", + "active": true + } + ] + } + ], + "2001:db8:3::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth1", + "active": true + } + ] + } + ], + "2001:db8:4::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + } + ] + } + ], + "2001:db8:5::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + } + ] + } + ], + "2001:db8:6::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + } + ] + } + ], + "2001:db8:7::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + } + ] + } + ], + "2001:db8:8::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + } + ] + } + ], + "2001:db8:8007::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + } + ] + } + ], + "2001:db8:8008::/64": [ + { + "internalNextHopActiveNum": 1, + "nexthops": [ + { + "fib": true, + "interfaceName": "r1-eth2", + "active": true + } + ] + } + ] +} diff --git a/tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf index 9b7756e83..451cf2f72 100644 --- a/tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf +++ b/tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf @@ -13,9 +13,6 @@ interface r7-eth2 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! -interface r7-eth3 - shutdown -! router ospf6 ospf6 router-id 10.254.254.7 redistribute connected diff --git a/tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf index 33c64979c..f8d8619bc 100644 --- a/tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf +++ b/tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf @@ -13,9 +13,6 @@ interface r8-eth2 ipv6 ospf6 hello-interval 2 ipv6 ospf6 dead-interval 10 ! -interface r8-eth3 - shutdown -! router ospf6 ospf6 router-id 10.254.254.8 redistribute connected diff --git a/tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py b/tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py index adf289e2d..6f1dd6a54 100644 --- a/tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py +++ b/tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py @@ -43,12 +43,13 @@ route each. With all links up, we expect 3 ECMP paths and 3 nexthops on R1 towards each of R7/8. Then we bring down the R3-R6 link, causing only 2 remaining paths and 2 nexthops on R1. Then we bring down the R2-R5 link, causing only -1 remaining path and 1 nexthop on R1. +1 remaining path and 1 nexthop on R1. -The test is successful if the number of nexthops for the routes on R1 is as -expected. +The test is successful if the number of nexthops and their interfaces for +the routes on R1 is as expected. """ +import json import os import sys from functools import partial @@ -62,7 +63,7 @@ sys.path.append(os.path.join(CWD, "../")) # Import topogen and topotest helpers from lib import topotest from lib.topogen import Topogen, TopoRouter, get_topogen -from lib.topolog import logger +from lib.common_config import write_test_header, write_test_footer, step # Required to instantiate the topology builder class. @@ -111,17 +112,42 @@ def setup_module(mod): tgen.start_router() -def test_wait_protocol_convergence(): +def expect_routes_json(router, exp_routes_json_fname, stepmsg): + "Wait until OSPFv3 routes match JSON spec" + step( + "waiting for OSPFv3 router '{}' routes/nexthops to match {} ({})".format( + router, exp_routes_json_fname, stepmsg + ) + ) + + json_file = "{}/{}/{}".format(CWD, router, exp_routes_json_fname) + expected = json.loads(open(json_file).read()) + tgen = get_topogen() + test_func = partial( + topotest.router_json_cmp, + tgen.gears[router], + "show ipv6 route ospf6 json", + expected, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5) + assertmsg = '"{}" JSON output mismatches ({})'.format(router, stepmsg) + assert result is None, assertmsg + + +def test_wait_protocol_convergence(request): "Wait for OSPFv3 to converge" + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() if tgen.routers_have_failure(): pytest.skip(tgen.errors) - logger.info("waiting for protocols to converge") + step("waiting for protocols to converge") def expect_neighbor_full(router, neighbor): "Wait until OSPFv3 neighborship is full" - logger.info( + step( "waiting for OSPFv3 router '{}' neighborship with '{}'".format( router, neighbor ) @@ -156,57 +182,31 @@ def test_wait_protocol_convergence(): expect_neighbor_full("r8", "10.254.254.5") expect_neighbor_full("r8", "10.254.254.6") + expect_routes_json("r1", "show_ipv6_routes_ospf6-1.json", "post-convergence") -def test_ecmp_inter_area(): + write_test_footer(tc_name) + + +def test_ecmp_inter_area(request): "Test whether OSPFv3 ECMP nexthops are properly updated for inter-area routes after link down" + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() if tgen.routers_have_failure(): pytest.skip(tgen.errors) - def num_nexthops(router): - # Careful: "show ipv6 ospf6 route json" doesn't work here. It will - # only list one route type per prefix and that might not necessarily - # be the best/selected route. "show ipv6 route ospf6 json" only - # lists selected routes, so that's more useful in this case. - routes = tgen.gears[router].vtysh_cmd("show ipv6 route ospf6 json", isjson=True) - route_prefixes_infos = sorted(routes.items()) - # Note: ri may contain one entry per routing protocol, but since - # we've explicitly requested only ospf6 above, we can count on ri[0] - # being the entry we're looking for. - return [ri[0]["internalNextHopActiveNum"] for rp, ri in route_prefixes_infos] - - def expect_num_nexthops(router, expected_num_nexthops, count): - "Wait until number of nexthops for routes matches expectation" - logger.info( - "waiting for OSPFv3 router '{}' nexthops {}".format( - router, expected_num_nexthops - ) - ) - test_func = partial(num_nexthops, router) - _, result = topotest.run_and_expect( - test_func, expected_num_nexthops, count=count, wait=3 - ) - assert ( - result == expected_num_nexthops - ), "'{}' wrong number of route nexthops".format(router) - - # Check nexthops pre link-down - # tgen.mininet_cli() - expect_num_nexthops("r1", [1, 1, 1, 1, 2, 3, 3, 3, 3], 4) - - logger.info("triggering R3-R6 link down") + step("triggering R3-R6 link down") tgen.gears["r3"].run("ip link set r3-eth1 down") - # tgen.mininet_cli() - # Check nexthops post link-down - expect_num_nexthops("r1", [1, 1, 1, 1, 1, 2, 2, 2, 2], 8) + expect_routes_json("r1", "show_ipv6_routes_ospf6-2.json", "post-R3-R6-link-down") - logger.info("triggering R2-R5 link down") + step("triggering R2-R5 link down") tgen.gears["r2"].run("ip link set r2-eth1 down") - # tgen.mininet_cli() - # Check nexthops post link-down - expect_num_nexthops("r1", [1, 1, 1, 1, 1, 1, 1, 1, 1], 8) + expect_routes_json("r1", "show_ipv6_routes_ospf6-3.json", "post-R2-R5-link-down") + + write_test_footer(tc_name) def teardown_module(_mod): @@ -215,14 +215,19 @@ def teardown_module(_mod): tgen.stop_topology() -def test_memory_leak(): +def test_memory_leak(request): "Run the memory leak test and report results." + tc_name = request.node.name + write_test_header(tc_name) + tgen = get_topogen() if not tgen.is_memleak_enabled(): pytest.skip("Memory leak test/report is disabled") tgen.report_memory_leaks() + write_test_footer(tc_name) + if __name__ == "__main__": args = ["-s"] + sys.argv[1:] |