Download raw body.
bgpd: trigger session down timer during graceful restart
When a peer goes down it can either call session_down() or go into
session_graceful_restart() to do a graceful reload.
In session_down the Timer_SessionDown timer is armed and will fire in 1h.
In the GR case this is not done. If the session fails to recover the
RDE will keep on syncing its Adj-RIB-Out which is not helpful. Also
templated peers are no longer cleaned up.
Now the maximum GR timeout is 4095 (since it is a 12bit field) and that is
longer than INTERVAL_SESSION_DOWN. So do a quick check to either use
INTERVAL_SESSION_DOWN or staletime + INTERVAL_SESSION_DOWN depending on
which one is bigger.
While there also update last_updown in the stats struct since the peer
either lost or flapped the session.
I switch the grestart.timeout in struct capabilities to uint16_t to
silence another signed vs unsigned warnings.
--
:wq Claudio
Index: bgpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/bgpd.h,v
diff -u -p -r1.540 bgpd.h
--- bgpd.h 5 May 2026 09:12:04 -0000 1.540
+++ bgpd.h 7 May 2026 13:31:04 -0000
@@ -437,10 +437,10 @@ struct auth_config {
struct capabilities {
struct {
- int16_t timeout; /* graceful restart timeout */
- int8_t flags[AID_MAX]; /* graceful restart per AID flags */
- int8_t restart; /* graceful restart, RFC 4724 */
- int8_t grnotification; /* graceful notification, RFC 8538 */
+ uint16_t timeout; /* gr restart timeout */
+ int8_t flags[AID_MAX]; /* gr restart per AID flags */
+ int8_t restart; /* gr restart, RFC 4724 */
+ int8_t grnotification; /* gr notification, RFC 8538 */
} grestart;
int8_t mp[AID_MAX]; /* multiprotocol extensions, RFC 4760 */
int8_t add_path[AID_MAX]; /* ADD_PATH, RFC 7911 */
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/parse.y,v
diff -u -p -r1.488 parse.y
--- parse.y 2 Mar 2026 09:51:48 -0000 1.488
+++ parse.y 7 May 2026 13:28:57 -0000
@@ -772,9 +772,9 @@ conf_main : AS as4number {
conf->min_holdtime = $3;
}
| STALETIME NUMBER {
- if ($2 < MIN_HOLDTIME || $2 > USHRT_MAX) {
+ if ($2 < MIN_HOLDTIME || $2 > CAPA_GR_TIMEMASK) {
yyerror("staletime must be between %u and %u",
- MIN_HOLDTIME, USHRT_MAX);
+ MIN_HOLDTIME, CAPA_GR_TIMEMASK);
YYERROR;
}
conf->staletime = $2;
@@ -1937,9 +1937,9 @@ peeropts : REMOTEAS as4number {
curpeer->conf.min_holdtime = $3;
}
| STALETIME NUMBER {
- if ($2 < MIN_HOLDTIME || $2 > USHRT_MAX) {
+ if ($2 < MIN_HOLDTIME || $2 > CAPA_GR_TIMEMASK) {
yyerror("staletime must be between %u and %u",
- MIN_HOLDTIME, USHRT_MAX);
+ MIN_HOLDTIME, CAPA_GR_TIMEMASK);
YYERROR;
}
curpeer->conf.staletime = $2;
Index: session.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/session.c,v
diff -u -p -r1.531 session.c
--- session.c 7 May 2026 09:17:27 -0000 1.531
+++ session.c 7 May 2026 13:34:11 -0000
@@ -1048,7 +1048,7 @@ void
session_graceful_restart(struct peer *p)
{
uint8_t i;
- uint16_t staletime = conf->staletime;
+ u_int staletime = conf->staletime;
if (p->conf.staletime)
staletime = p->conf.staletime;
@@ -1057,6 +1057,14 @@ session_graceful_restart(struct peer *p)
if (staletime > p->capa.neg.grestart.timeout)
staletime = p->capa.neg.grestart.timeout;
timer_set(&p->timers, Timer_RestartTimeout, staletime);
+
+ if (staletime < INTERVAL_SESSION_DOWN - INTERVAL_STALE)
+ staletime = INTERVAL_SESSION_DOWN - INTERVAL_STALE;
+
+ /* bits from session_down that are also needed here */
+ p->stats.last_updown = getmonotime();
+ timer_set(&p->timers, Timer_SessionDown,
+ staletime + INTERVAL_SESSION_DOWN);
for (i = AID_MIN; i < AID_MAX; i++) {
if (p->capa.neg.grestart.flags[i] & CAPA_GR_PRESENT) {
bgpd: trigger session down timer during graceful restart