Description
rt vpn both <ASN>:<NN> under router bgp <ASN> vrf <NAME> / address-family <ipv4|ipv6> unicast gets silently split into mismatched rt vpn import / rt vpn export lines, with the export half incorrectly set to this router's own rd vpn export value instead of retaining the configured shared RT.
Reproduced on 3 of 4 PEs in a lab, on separate occasions, via one trigger: restarting the daemon/container. The on-disk frr.conf shows rt vpn both 65000:100 before and after the restart, unchanged. Once bgpd reloads it at startup, though, show running-config shows the split/broken form instead. The save itself is fine; the reload is what breaks it.
Effect: the export RT no longer matches what other PEs import on, so the route silently stops being importable anywhere else in the VPN. There are no logs or error messages. A remote PE's show bgp vrf <NAME> <afi> unicast just shows zero routes.
Related issue
This looks like the same underlying bug as #18987 ("Export Route Target Overwritten on Startup"), which was auto-closed by the stale-issue bot in June 2026. The last activity was the reporter sharing a patch in December 2025. That issue evolved across versions: originally the export RT got overwritten with a VRF interface's IP address (10.3.1), then later with the RD itself (10.5, per a comment from the reporter on 2025-11-13). That's exactly what's reproduced here on 10.6.1.
The reporter's diagnosis: "The problem seems to be with the auto derivation code overwriting RT when router-id changes." That matches this report's trigger: router-id gets freshly determined at daemon startup, and something in that path unconditionally re-derives and overwrites the export RT with no check for whether it was explicitly configured via CLI.
The attached patch (https://github.com/user-attachments/files/23884283/bgp_fix.txt) confirms this. It adds a BGP_VPN_POLICY_TOVPN_RT_CLI_SET flag, set when rt vpn export/both is configured via CLI, and gates the auto-derivation in vpn_handle_router_id_update() (bgpd/bgp_mplsvpn.c) on that flag being unset. That single missing check appears to be the entire bug.
Filing this as a new issue rather than commenting on #18987 since it's closed and would likely get skipped in normal triage. Wanted to flag that this looks like the same bug, still present on the current 10.6.1 GA release, with a full reproduction below.
Version
FRRouting 10.6.1_git (pe1) on Linux(7.0.11-orbstack-00360-gc9bc4d96ac70).
Copyright 1996-2005 Kunihiro Ishiguro, et al.
configured with:
'--prefix=/usr' '--sysconfdir=/etc' '--localstatedir=/var' '--sbindir=/usr/lib/frr' '--libdir=/usr/lib' '--enable-rpki' '--enable-vtysh' '--enable-multipath=64' '--enable-vty-group=frrvty' '--enable-user=frr' '--enable-group=frr' '--enable-pcre2posix' '--enable-scripting' 'CC=cc' 'CXX=c++'
Deployed via quay.io/frrouting/frr:10.6.1 (containerlab / Docker), kernel 7.0.11-orbstack (OrbStack Linux VM on macOS, arm64).
Topology / setup
SRv6 L3VPN lab: 4 PE routers (pe1-pe4) in a full iBGP mesh over loopbacks, 2 P routers as pure IS-IS/SRv6 underlay transit, one shared customer VRF (cust1) across all four PEs tied together with a shared RT (65000:100) and per-PE RDs (65000:6/7/8/9). Probably not SRv6-specific, looks like generic VPN RT handling, but haven't tested it against a plain MPLS L3VPN VRF yet.
How to reproduce
- Configure a VRF-scoped BGP instance with a shared RT via
both:
router bgp 65000 vrf cust1
sid vpn per-vrf export auto
!
address-family ipv4 unicast
redistribute connected
rd vpn export 65000:6
nexthop vpn export 5f00:0:6::1
rt vpn both 65000:100
export vpn
import vpn
exit-address-family
!
address-family ipv6 unicast
redistribute connected
rd vpn export 65000:6
nexthop vpn export 5f00:0:6::1
rt vpn both 65000:100
export vpn
import vpn
exit-address-family
exit
(Base instance also has ipv4 vpn / ipv6 vpn activated for VPN route exchange, and segment-routing srv6 / locator IGP bound for per-VRF SID allocation. Included for completeness, probably unrelated.)
write memory. Confirm the on-disk file is correct:
# grep "rt vpn" /etc/frr/frr.conf
rt vpn both 65000:100
rt vpn both 65000:100
- Restart bgpd. Here, via
containerlab deploy --reconfigure, which recreates the container and forces bgpd to reload frr.conf from scratch.
- Compare
show running-config against the (unchanged) on-disk file.
Expected behavior
After restart, show running-config should match the on-disk config: rt vpn both 65000:100 on both address-families, unchanged from what was saved.
Actual behavior
On-disk file (confirmed unchanged, still correct):
router bgp 65000 vrf cust1
sid vpn per-vrf export auto
!
address-family ipv4 unicast
redistribute connected
rd vpn export 65000:6
nexthop vpn export 5f00:X::X
rt vpn both 65000:100
export vpn
import vpn
exit-address-family
!
address-family ipv6 unicast
redistribute connected
rd vpn export 65000:6
nexthop vpn export 5f00:X::X
rt vpn both 65000:100
export vpn
import vpn
exit-address-family
exit
show running-config after the restart, same section:
router bgp 65000 vrf cust1
sid vpn per-vrf export auto
!
address-family ipv4 unicast
redistribute connected
rd vpn export 65000:6
nexthop vpn export 5f00:X::X
rt vpn import 65000:100
rt vpn export 65000:6 <-- wrong: matches "rd vpn export", not the configured "rt vpn both" value
export vpn
import vpn
exit-address-family
!
address-family ipv6 unicast
redistribute connected
rd vpn export 65000:6
nexthop vpn export 5f00:X::X
rt vpn import 65000:100
rt vpn export 65000:6 <-- same wrong value here
export vpn
import vpn
exit-address-family
exit
Both address-families get hit identically, and the wrong export value (65000:6) exactly matches this router's own rd vpn export 65000:6. Looks like the export RT is getting re-derived from the RD as a fallback during reload, instead of keeping the configured both value.
Workaround
Re-issuing rt vpn both 65000:100 live after the fact fixes it until the next restart:
configure terminal
router bgp 65000 vrf cust1
address-family ipv4 unicast
rt vpn both 65000:100
exit-address-family
address-family ipv6 unicast
rt vpn both 65000:100
exit-address-family
end
write memory
Has to be reapplied after every restart. It doesn't stick, since the on-disk file was never actually wrong; every reload just re-triggers the same split.
Additional context
Reproduced on 3 of 4 PEs across multiple redeploys this session. pe2, otherwise identically configured, hasn't shown it once. Given the router-id-change trigger described in #18987, this is probably just luck: router-id here is auto-derived from an interface IP that Docker reassigns somewhat unpredictably across container recreations, so pe2 may simply not have gotten a genuine router-id change on the redeploys where the others did.
Description
rt vpn both <ASN>:<NN>underrouter bgp <ASN> vrf <NAME> / address-family <ipv4|ipv6> unicastgets silently split into mismatchedrt vpn import/rt vpn exportlines, with the export half incorrectly set to this router's ownrd vpn exportvalue instead of retaining the configured shared RT.Reproduced on 3 of 4 PEs in a lab, on separate occasions, via one trigger: restarting the daemon/container. The on-disk
frr.confshowsrt vpn both 65000:100before and after the restart, unchanged. Once bgpd reloads it at startup, though,show running-configshows the split/broken form instead. The save itself is fine; the reload is what breaks it.Effect: the export RT no longer matches what other PEs import on, so the route silently stops being importable anywhere else in the VPN. There are no logs or error messages. A remote PE's
show bgp vrf <NAME> <afi> unicastjust shows zero routes.Related issue
This looks like the same underlying bug as #18987 ("Export Route Target Overwritten on Startup"), which was auto-closed by the stale-issue bot in June 2026. The last activity was the reporter sharing a patch in December 2025. That issue evolved across versions: originally the export RT got overwritten with a VRF interface's IP address (10.3.1), then later with the RD itself (10.5, per a comment from the reporter on 2025-11-13). That's exactly what's reproduced here on 10.6.1.
The reporter's diagnosis: "The problem seems to be with the auto derivation code overwriting RT when router-id changes." That matches this report's trigger: router-id gets freshly determined at daemon startup, and something in that path unconditionally re-derives and overwrites the export RT with no check for whether it was explicitly configured via CLI.
The attached patch (https://github.com/user-attachments/files/23884283/bgp_fix.txt) confirms this. It adds a
BGP_VPN_POLICY_TOVPN_RT_CLI_SETflag, set whenrt vpn export/bothis configured via CLI, and gates the auto-derivation invpn_handle_router_id_update()(bgpd/bgp_mplsvpn.c) on that flag being unset. That single missing check appears to be the entire bug.Filing this as a new issue rather than commenting on #18987 since it's closed and would likely get skipped in normal triage. Wanted to flag that this looks like the same bug, still present on the current 10.6.1 GA release, with a full reproduction below.
Version
Deployed via
quay.io/frrouting/frr:10.6.1(containerlab / Docker), kernel7.0.11-orbstack(OrbStack Linux VM on macOS, arm64).Topology / setup
SRv6 L3VPN lab: 4 PE routers (
pe1-pe4) in a full iBGP mesh over loopbacks, 2 P routers as pure IS-IS/SRv6 underlay transit, one shared customer VRF (cust1) across all four PEs tied together with a shared RT (65000:100) and per-PE RDs (65000:6/7/8/9). Probably not SRv6-specific, looks like generic VPN RT handling, but haven't tested it against a plain MPLS L3VPN VRF yet.How to reproduce
both:ipv4 vpn/ipv6 vpnactivated for VPN route exchange, andsegment-routing srv6 / locator IGPbound for per-VRF SID allocation. Included for completeness, probably unrelated.)write memory. Confirm the on-disk file is correct:containerlab deploy --reconfigure, which recreates the container and forces bgpd to reloadfrr.conffrom scratch.show running-configagainst the (unchanged) on-disk file.Expected behavior
After restart,
show running-configshould match the on-disk config:rt vpn both 65000:100on both address-families, unchanged from what was saved.Actual behavior
On-disk file (confirmed unchanged, still correct):
show running-configafter the restart, same section:Both address-families get hit identically, and the wrong export value (
65000:6) exactly matches this router's ownrd vpn export 65000:6. Looks like the export RT is getting re-derived from the RD as a fallback during reload, instead of keeping the configuredbothvalue.Workaround
Re-issuing
rt vpn both 65000:100live after the fact fixes it until the next restart:Has to be reapplied after every restart. It doesn't stick, since the on-disk file was never actually wrong; every reload just re-triggers the same split.
Additional context
Reproduced on 3 of 4 PEs across multiple redeploys this session.
pe2, otherwise identically configured, hasn't shown it once. Given the router-id-change trigger described in #18987, this is probably just luck: router-id here is auto-derived from an interface IP that Docker reassigns somewhat unpredictably across container recreations, sope2may simply not have gotten a genuine router-id change on the redeploys where the others did.