Commit 68e6e5af4e for frr
commit 68e6e5af4ef0fce0ca91c58d5259d25efaf0dc3f
Author: Donald Sharp <sharpd@nvidia.com>
Date: Thu Nov 5 09:45:38 2026 -0500
tests: Make test_bgp_evpn_type5_vrf_leak_state.py wait until conditions are correct
The test is not checking that state has reached remote peers before moving on in
the test. This creates a timing window where the test is in the wrong state
when new commands are issued and bgpd correctly never reaches the intended state.
Make the test be patient.
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
diff --git a/tests/topotests/bgp_evpn_type5_vrf_leak_stale/test_bgp_evpn_type5_vrf_leak_stale.py b/tests/topotests/bgp_evpn_type5_vrf_leak_stale/test_bgp_evpn_type5_vrf_leak_stale.py
index 1dc4b612ab..ca7ee92448 100644
--- a/tests/topotests/bgp_evpn_type5_vrf_leak_stale/test_bgp_evpn_type5_vrf_leak_stale.py
+++ b/tests/topotests/bgp_evpn_type5_vrf_leak_stale/test_bgp_evpn_type5_vrf_leak_stale.py
@@ -99,6 +99,7 @@ MULTI_SOURCE_GREEN_PREFIX = "192.168.100.1/32"
MULTI_SOURCE_BLUE_PREFIX = "192.168.101.1/32"
INITIAL_IMPORT_PREFIX = "192.168.102.1/32"
PE_VRFS = ("GREEN", "BLUE", "PURPLE")
+GREEN_L3VNI = 101
BLUE_L3VNI = 102
PURPLE_L3VNI = 103
# Fabric sessions live in the default instance; the tenant VRFs have no peers.
@@ -1517,30 +1518,30 @@ def test_skip_evpn_imported_preserves_mixed_local_and_evpn_paths():
for vrf in PE_VRFS:
_configure_skip_evpn_imported(router, vrf, False)
+ # r1's origin and r2's leaks of its local BLUE static must stay advertised.
+ # r3 has no local copy: its BLUE and PURPLE Type-5s are leaks of the EVPN
+ # import and are the routes suppression must withdraw. r3 GREEN only holds
+ # the direct import, which is not re-exported.
+ local_rds = {
+ _evpn_l3vni_rd(r1, GREEN_L3VNI),
+ _evpn_l3vni_rd(r2, GREEN_L3VNI),
+ _evpn_l3vni_rd(r2, BLUE_L3VNI),
+ _evpn_l3vni_rd(r2, PURPLE_L3VNI),
+ }
+ evpn_derived_rds = {
+ _evpn_l3vni_rd(r3, BLUE_L3VNI),
+ _evpn_l3vni_rd(r3, PURPLE_L3VNI),
+ }
+
logger.info("Install the same prefix as an origin and a local BLUE route")
_configure_static_route(r1, "GREEN", MIXED_PATH_PREFIX, True)
_configure_static_route(r2, "BLUE", MIXED_PATH_PREFIX, True)
_wait_bgp_valid_path_count_at_least(r2, "BLUE", MIXED_PATH_PREFIX, 2)
- _wait_evpn_type5_prefix_count_at_least(r1, MIXED_PATH_PREFIX, 2)
- before_rds = set(evpn_type5_route_distinguishers(r1, MIXED_PATH_PREFIX))
- assert (
- len(before_rds) >= 2
- ), "r1 {0}: expected at least 2 Type-5 RDs, actual={1}\n{2}".format(
- MIXED_PATH_PREFIX,
- before_rds,
- r1.vtysh_cmd("show bgp l2vpn evpn route type 5"),
- )
-
- # The RD r2 exports its local BLUE route under. Suppression must leave
- # this one advertised while the EVPN-derived copies are withdrawn.
- blue_rd = _evpn_l3vni_rd(r2, BLUE_L3VNI)
- assert (
- blue_rd in before_rds
- ), "r1 {0}: expected r2 BLUE export {1} in baseline {2}\n{3}".format(
- MIXED_PATH_PREFIX,
- blue_rd,
- sorted(before_rds),
- r1.vtysh_cmd("show bgp l2vpn evpn route type 5"),
+ # Two Type-5 paths can be r1 plus r2 BLUE, before r3 has advertised.
+ # Enabling suppression at that point keeps r3 from ever exporting, so the
+ # RD set never shrinks. Wait until r3's re-exports are actually present.
+ _wait_evpn_type5_rds(
+ r1, MIXED_PATH_PREFIX, present=local_rds | evpn_derived_rds
)
logger.info("Suppress EVPN-derived paths while retaining the local path")
@@ -1549,36 +1550,24 @@ def test_skip_evpn_imported_preserves_mixed_local_and_evpn_paths():
_configure_skip_evpn_imported(router, vrf, True)
_wait_bgp_route(r2, "BLUE", MIXED_PATH_PREFIX, True)
- current_rds = set()
-
- def _type5_exports_reduced():
- nonlocal current_rds
- current_rds = set(evpn_type5_route_distinguishers(r1, MIXED_PATH_PREFIX))
- return current_rds < before_rds and blue_rd in current_rds
-
- topotest.run_and_expect(_type5_exports_reduced, True, count=60, wait=1)
- route_output = r2.vtysh_cmd(
- "show bgp vrf BLUE ipv4 unicast {0}".format(MIXED_PATH_PREFIX)
+ current_rds = _wait_evpn_type5_rds(
+ r1,
+ MIXED_PATH_PREFIX,
+ present=local_rds,
+ absent=evpn_derived_rds | {_evpn_l3vni_rd(r3, GREEN_L3VNI)},
)
type5_output = r1.vtysh_cmd("show bgp l2vpn evpn route type 5")
- assert current_rds < before_rds, (
- "r1 {0}: expected Type-5 RDs to be a proper subset of baseline; "
- "before={1}, after={2}\n{3}".format(
+ assert current_rds == local_rds, (
+ "r1 {0}: expected only the local-origin Type-5 RDs to remain; "
+ "expected={1}, actual={2}\n{3}".format(
MIXED_PATH_PREFIX,
- sorted(before_rds),
+ sorted(local_rds),
sorted(current_rds),
type5_output,
)
)
- # Shrinking alone would also be satisfied by wrongly dropping r2's own
- # export, so require the RD carrying it to survive.
- assert (
- blue_rd in current_rds
- ), "r1 {0}: expected r2 BLUE export {1} to survive; after={2}\n{3}".format(
- MIXED_PATH_PREFIX,
- blue_rd,
- sorted(current_rds),
- type5_output,
+ route_output = r2.vtysh_cmd(
+ "show bgp vrf BLUE ipv4 unicast {0}".format(MIXED_PATH_PREFIX)
)
assert (
"weight 32768, valid" in route_output