From: Claudio Jeker Subject: Re: bgpd: trigger session down timer during graceful restart To: Theo Buehler Cc: tech@openbsd.org Date: Thu, 7 May 2026 20:00:04 +0200 On Thu, May 07, 2026 at 05:43:03PM +0200, Theo Buehler wrote: > On Thu, May 07, 2026 at 04:19:25PM +0200, Claudio Jeker wrote: > > 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. > > I think you mean "INTERVAL_SESSION_DOWN or staletime + INTERVAL_STALE" > ... (see below) > > > > > 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); > > ... and this should be: > > staletime + INTERVAL_STALE); > > then it's ok Thanks for spotting this. > > > > for (i = AID_MIN; i < AID_MAX; i++) { > > if (p->capa.neg.grestart.flags[i] & CAPA_GR_PRESENT) { > > > -- :wq Claudio