Commit e4a080e1c1 for frr

commit e4a080e1c1a63db5b38e23e4128b497c33c2ac80
Author: Philippe Guibert <philippe.guibert@6wind.com>
Date:   Tue Nov 10 11:50:27 2026 +0100

    tests: check a colored l3vpn route follows the sr policy state

    Add a step 7 to isis_sr_te_topo1. rt6 exports 10.200.0.0/24 from vrf1
    to L3VPN, and rt1 imports it in vrf1, with the 'set sr-te color 1'
    route-map applied on the VPN routes received from rt6. The SR Policy
    color 1 to 6.6.6.6 comes up after the route is installed, then goes
    down. The VRF route must use the IGP path, then the segment list of
    the policy, then the IGP path again.

    Without the commit "bgpd: track the color of vrf leaked paths in nexthop
    tracking", the step fails when the SR Policy comes up:

    > topo: With the SR Policy up, the VRF route should use its segment list
    > topo: Function returned expected labels [16050, 16060] before the VPN label, got [[16060], [16060]]

    Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>

diff --git a/tests/topotests/isis_sr_te_topo1/test_isis_sr_te_topo1.py b/tests/topotests/isis_sr_te_topo1/test_isis_sr_te_topo1.py
index bd77c58154..846391342a 100755
--- a/tests/topotests/isis_sr_te_topo1/test_isis_sr_te_topo1.py
+++ b/tests/topotests/isis_sr_te_topo1/test_isis_sr_te_topo1.py
@@ -77,6 +77,7 @@ sys.path.append(os.path.join(CWD, "../"))
 from lib import topotest
 from lib.topogen import Topogen, TopoRouter, get_topogen
 from lib.topolog import logger
+from lib.common_config import retry

 # Required to instantiate the topology builder class.

@@ -1011,6 +1012,118 @@ def test_srte_color_extended_community_step6():
     set_route_map_color("rt1", 1)


+#
+# Step 7
+#
+# Checking a colored L3VPN route imported in a VRF, when the SR Policy
+# of its color comes up and goes down after the route is installed
+#
+def test_srte_l3vpn_vrf_route_follows_sr_policy_step7():
+    setup_testcase(
+        "Test (step 7): colored L3VPN route imported in a VRF follows the SR Policy state"
+    )
+
+    tgen = get_topogen()
+
+    @retry(retry_timeout=60)
+    def check_vrf_route_labels(expected_labels):
+        output = tgen.gears["rt1"].vtysh_cmd(
+            "show ip route vrf vrf1 10.200.0.0/24 json", isjson=True
+        )
+        routes = output.get("10.200.0.0/24")
+        if not routes:
+            return "10.200.0.0/24 not found in vrf1"
+        nexthops = routes[0].get("nexthops", [])
+        if not any(nh.get("srteColor") == 1 for nh in nexthops):
+            return "no nexthop with SR-TE color 1: {}".format(nexthops)
+        # the last label is the VPN label, allocated by rt6
+        labels = [nh["labels"][:-1] for nh in nexthops if nh.get("fib")]
+        if not labels or any(label != expected_labels for label in labels):
+            return "expected labels {} before the VPN label, got {}".format(
+                expected_labels, labels
+            )
+        return True
+
+    for rname in ["rt1", "rt6"]:
+        tgen.net[rname].cmd("ip link add vrf1 type vrf table 1001")
+        tgen.net[rname].cmd("ip link set vrf1 up")
+
+    tgen.gears["rt6"].vtysh_cmd(
+        """
+        configure terminal
+         router bgp 1
+          address-family ipv4 vpn
+           neighbor 1.1.1.1 activate
+          exit-address-family
+         exit
+         router bgp 1 vrf vrf1
+          no bgp network import-check
+          address-family ipv4 unicast
+           network 10.200.0.0/24
+           label vpn export auto
+           rd vpn export 6:1
+           rt vpn both 52:100
+           export vpn
+           import vpn
+          exit-address-family
+        """
+    )
+    tgen.gears["rt1"].vtysh_cmd(
+        """
+        configure terminal
+         router bgp 1
+          address-family ipv4 vpn
+           neighbor 6.6.6.6 activate
+           neighbor 6.6.6.6 route-map SET_SR_POLICY in
+          exit-address-family
+         exit
+         router bgp 1 vrf vrf1
+          address-family ipv4 unicast
+           rd vpn export 1:1
+           rt vpn both 52:100
+           export vpn
+           import vpn
+          exit-address-family
+        """
+    )
+
+    logger.info("Without SR Policy, the VRF route should use the IGP path")
+    result = check_vrf_route_labels([16060])
+    assert result is True, result
+
+    add_candidate_path("rt1", "6.6.6.6", 100, "default")
+    logger.info("With the SR Policy up, the VRF route should use its segment list")
+    result = check_vrf_route_labels([16050, 16060])
+    assert result is True, result
+
+    delete_candidate_path("rt1", "6.6.6.6", 100)
+    logger.info("With the SR Policy down, the VRF route should use the IGP path")
+    result = check_vrf_route_labels([16060])
+    assert result is True, result
+
+    tgen.gears["rt1"].vtysh_cmd(
+        """
+        configure terminal
+         no router bgp 1 vrf vrf1
+         router bgp 1
+          address-family ipv4 vpn
+           no neighbor 6.6.6.6 route-map SET_SR_POLICY in
+           no neighbor 6.6.6.6 activate
+        """
+    )
+    tgen.gears["rt6"].vtysh_cmd(
+        """
+        configure terminal
+         no router bgp 1 vrf vrf1
+         router bgp 1
+          address-family ipv4 vpn
+           no neighbor 1.1.1.1 activate
+        """
+    )
+    for rname in ["rt1", "rt6"]:
+        tgen.net[rname].cmd("ip link del vrf1")
+
+
 # Memory leak test template
 def test_memory_leak():
     "Run the memory leak test and report results."