Index | Thread | Search

From:
Theo Buehler <tb@theobuehler.org>
Subject:
Re: bgpd: fix adj-rib-out cache issue with add-path
To:
tech@openbsd.org
Date:
Mon, 20 Jul 2026 16:41:20 +0200

Download raw body.

Thread
On Mon, Jul 20, 2026 at 04:31:30PM +0200, Claudio Jeker wrote:
> The adj-rib-out remains cached when a peer goes down.
> When the session is reestablished the code checks if the sync is still
> valid or if a full peer_dump is needed. This depends also on the
> capabilities of the session.
> 
> If a session drops from add-path send X to no add-path send then the
> adj-rib-out is a bit desynced and up_generate_updates() does not all the
> required cleanup.
> 
> In the EVAL_SYNC case up_generate_updates() should check if the
> adjout_prefix (p) returned was for an add-path path. This is the case if
> path_id_tx is not 0. In that case withdraw all paths before calling
> up_process_prefix().
> 
> The add-path side already does this by default.
> Most other cases where the adj-rib-out gets desynced is during config
> reloads (e.g. switching export modes). There the code already does a
> RIB flush and the resync.

Makes sense and reads fine

ok tb with a small nit

> 
> -- 
> :wq Claudio
> 
> Index: rde_update.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde_update.c,v
> diff -u -p -r1.202 rde_update.c
> --- rde_update.c	20 Jul 2026 13:25:49 -0000	1.202
> +++ rde_update.c	20 Jul 2026 14:22:36 -0000
> @@ -228,6 +228,18 @@ up_generate_updates(struct rde_peer *pee
>  
>  	p = adjout_prefix_first(re->prefix, peer->adjout_bid);
>  
> +	/*
> +	 * In case the peer switched from add-path send to no add-path,
> +	 * flush all the cached prefixes during initial sync.
> +	 */
> +	if (mode == EVAL_SYNC && p != NULL && p->path_id_tx != 0) {
> +		do {
> +			adjout_prefix_withdraw(peer, re->prefix, p, 1);
> +			p = adjout_prefix_next(re->prefix,
> +			    peer->adjout_bid, p);
> +		} while(p != NULL);

I think style(9) wants a space before (:

		} while (p != NULL);

> +	}
> +
>  	new = prefix_best(re);
>  	while (new != NULL) {
>  		switch (up_process_prefix(peer, new, p, mode)) {
>