Commit 797335942d for frr

commit 797335942d8d6eb526f5e7904d65686934979535
Author: Philippe Guibert <philippe.guibert@6wind.com>
Date:   Tue Nov 10 10:53:23 2026 +0100

    bgpd: track the color of vrf leaked paths in nexthop tracking

    A colored L3VPN route imported in a VRF does not follow the state of the
    SR-TE policy of its color. A 'set sr-te color 1' route-map is applied on
    the VPN routes received from 4.4.4.4, and the SR policy color 1 to
    4.4.4.4 is created by a PCE after the route of 10.200.0.0/24 is imported
    in vrf l3vrf1. The route stays resolved over the IGP prefix-SID of
    4.4.4.4, without the segment list of the policy:

    > north# show ip route vrf l3vrf1
    > [..]
    > B>  10.200.0.0/24 [200/0] via 4.4.4.4 (vrf default) (recursive), SR-TE color 1, label 102, weight 1, 00:09:39
    >   *                         via 10.125.0.2, ntfp3 (vrf default), label 1044/102, weight 1, 00:09:39

    The opposite happens when the policy goes down: the route keeps the
    labels of the segment list that is no more valid.

    The VRF route is tracked by the colorless nexthop, while only the VPN
    route is tracked by the colored nexthop:

    > north# show bgp nexthop detail
    > Current BGP nexthop cache:
    >  4.4.4.4 valid [IGP metric 40], #paths 1, peer 4.4.4.4
    >   Resolved prefix 4.4.4.4/32
    >   gate 10.125.0.2, if ntfp3, ifindex 5
    >   Last update: Tue Nov 10 10:20:21 2026
    >   Paths:
    >     1/1 10.200.0.0/24 VRF l3vrf1 flags 0x4018
    >  SR-TE color 1 - 4.4.4.4 valid [IGP metric 40], #paths 1
    >   Resolved prefix 4.4.4.4/32
    >   gate 10.125.0.2, if ntfp3, ifindex 5
    >   Last update: Tue Nov 10 10:20:21 2026
    >   Paths:
    >     1/3 10.200.0.0/24 RD 444:2 VRF default flags 0x418

    When the policy state changes, zebra notifies the colored nexthop only:
    the VPN route is evaluated again, but the VRF route is not reinstalled,
    and zebra does not resolve it again. A 'clear bgp *' fixes the route.

    Since commit 9d23a3a58a, the SR-TE color is stored in the
    bgp_path_info_extra structure, and no more in the attribute. In
    leak_update(), leak_update_nexthop_valid() registers the nexthop of the
    leaked path before bgp_path_info_extra_propagate() copies the color
    from the source path. bgp_find_or_add_nexthop() reads the color with
    bgp_path_info_get_srte_color(), and finds no color yet: the leaked path
    is attached to the colorless nexthop. The color is copied just after,
    so the route is installed in zebra with the color. When the color was
    in the attribute, it was already present at nexthop registration.

    Fix this by copying the color before registering the nexthop, for the
    new leaked paths and for the updated ones. When the policy goes down,
    the VRF path is now evaluated with the colored nexthop:

    > BGP: VRF default(0): Rcvd NH update 4.4.4.4/32(0)(1) - metric 40/0 #nhops 1/1 flags Valid Reg Label Valid  redistributing protocol isis
    > BGP:     nhop via 10.125.0.2 if 5 (I) (1 labels)
    > BGP: NH update for 4.4.4.4/32(0)(1)(VRF default) - flags Valid Reg Label Valid  chgflags Changed Metric - evaluate paths
    > BGP: ... eval path 1/1 10.200.0.0/24 VRF l3vrf1 flags 0x4018
    > BGP: ... eval path 1/3 10.200.0.0/24 RD 444:2 VRF default flags 0x418

    Fixes: 9d23a3a58a ("bgpd: Move srte_color from attr struct to bgp_path_info_extra")
    Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>

diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 9d2e8caa87..6ff9a0ef96 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -1409,6 +1409,11 @@ static struct bgp_path_info *leak_update(struct bgp *to_bgp, struct bgp_dest *bn
 		if (CHECK_FLAG(source_bpi->flags, BGP_PATH_ACCEPT_OWN))
 			bgp_path_info_set_flag(bn, bpi, BGP_PATH_ACCEPT_OWN);

+		/* Carry srte_color from the leaked source path (or the
+		 * rmap-modified copy when a vpn-policy route-map ran).
+		 */
+		bgp_path_info_extra_propagate(bpi, rmap_bpi ? rmap_bpi : source_bpi);
+
 		if (leak_update_nexthop_valid(to_bgp, bn, new_attr, afi, safi,
 					      source_bpi, bpi, bgp_orig, p,
 					      debug))
@@ -1416,11 +1421,6 @@ static struct bgp_path_info *leak_update(struct bgp *to_bgp, struct bgp_dest *bn
 		else
 			bgp_path_info_unset_flag(bn, bpi, BGP_PATH_VALID);

-		/* Carry srte_color from the leaked source path (or the
-		 * rmap-modified copy when a vpn-policy route-map ran).
-		 */
-		bgp_path_info_extra_propagate(bpi, rmap_bpi ? rmap_bpi : source_bpi);
-
 		/* Process change. */
 		bgp_aggregate_increment(to_bgp, p, bpi, afi, safi);
 		bgp_process(to_bgp, bn, bpi, afi, safi);
@@ -1483,6 +1483,11 @@ static struct bgp_path_info *leak_update(struct bgp *to_bgp, struct bgp_dest *bn
 	if (nexthop_orig)
 		new->extra->vrfleak->nexthop_orig = *nexthop_orig;

+	/* Carry srte_color from the leaked source path (or the
+	 * rmap-modified copy when a vpn-policy route-map ran).
+	 */
+	bgp_path_info_extra_propagate(new, rmap_bpi ? rmap_bpi : source_bpi);
+
 	if (leak_update_nexthop_valid(to_bgp, bn, static_attr, afi, safi, source_bpi, new,
 				      bgp_orig, p, debug)) {
 		bgp_path_info_set_flag(bn, new, BGP_PATH_VALID);
@@ -1491,11 +1496,6 @@ static struct bgp_path_info *leak_update(struct bgp *to_bgp, struct bgp_dest *bn
 		bgp_path_info_unset_flag(bn, new, BGP_PATH_VALID);
 	new->attr = bgp_attr_intern(static_attr);

-	/* Carry srte_color from the leaked source path (or the
-	 * rmap-modified copy when a vpn-policy route-map ran).
-	 */
-	bgp_path_info_extra_propagate(new, rmap_bpi ? rmap_bpi : source_bpi);
-
 	bgp_path_info_add(bn, new);
 	bgp_aggregate_increment(to_bgp, p, new, afi, safi);