set protocols bgp parameters graceful-restart on its own renders bgp graceful-restart (the router acts as restarter: it keeps its routes when its own bgpd restarts). Adding stalepath-time renders only bgp graceful-restart stalepath-time N, which in FRR is a different command that sets the timer; the plain bgp graceful-restart line disappears and the router is helper-only. So adding a timer silently turns restarter mode off.
Measured at about 2.8M paths (VyOS 1.5.1, FRR 10.5.2), bgpd restarted the way watchfrr restarts it:
- helper-only (stalepath-time 360 set, as now): zebra removed all 1,628,852 BGP routes; the forwarding table was empty after 125 s and back to normal after 548 s;
- restarter mode (graceful-restart enable on the peer groups): 0 routes removed, the forwarding table never emptied, normal again after 408 s.
This applies to a restart of bgpd alone (what watchfrr does). A full FRR restart (systemctl restart frr) also restarts zebra, which removes the routes from the kernel when it stops; there restarter mode made no difference (forwarding table empty from about +45 s to +611 s, against +43 s to +546 s helper-only).
Template: bgpd.frr.j2: bgp graceful-restart {{ 'stalepath-time ' ~ ... }}. Before the 2020 refactor (T2174, 7305a7172) only the stalepath-time line was rendered; the refactor merged both into one line.
Potential fix options:
- render bgp graceful-restart whenever parameters graceful-restart exists and stalepath-time on its own line. Small; configs with only stalepath-time become restarters after an upgrade (applied at boot, no live reset).
- add an explicit global mode (enable / disable / restart-helper, as the per-neighbor option); no change for existing configs.