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);