Download raw body.
bgpd: rewrite adj-out-rib code
On Wed, Dec 17, 2025 at 03:58:46PM +0100, Claudio Jeker wrote:
> Fully rewrite the adj-rib-out code to not be per peer based but instead
> global with a peer bitmap to know which peer holds which prefix version.
>
> So a pt_entry now includes an array of struct adjout_prefix elements
> each entry is for a different path (different set of attributes) and
> includes a bitmap that tracks which peers include the prefix.
>
> This alters most of the adjout_prefix functions in some way or another.
>
> An optimisation on top of this is that the path_id_tx is forced to 0 for
> peers that have no add-path send enabled. This way the lookup for this
> common case is less deep.
>
> The peer_reaper is now replaced with a simple adjout_prefix_dump call.
>
> This is enough for a first step.
Mostly reads fine, but see below.
ok tb
> In general this reduces memory consumption by more than 50% especially if
> the outbound filters are producing the same path for many peers. My IXP
> test setup dropped from over 20G to below 5GB memory usage.
That's awesome.
> struct adjout_prefix *
> adjout_prefix_get(struct rde_peer *peer, uint32_t path_id_tx,
> struct pt_entry *pte)
> {
> - struct adjout_prefix xp;
> + struct adjout_prefix *p;
> + uint32_t i;
>
> - memset(&xp, 0, sizeof(xp));
> - xp.pt = pte;
> - xp.path_id_tx = path_id_tx;
> + for (i = 0; i < pte->adjoutlen; i++) {
> + p = &pte->adjout[i];
> + if (p->path_id_tx != path_id_tx)
> + continue;
I think you meant to check
if (p->path_id_tx < path_id_tx)
continue;
> + if (bitmap_test(&p->peermap, peer->adjout_bid))
> + return p;
> + if (p->path_id_tx > path_id_tx)
> + break;
Otherwise this break is unreachable.
> + }
>
> - return RB_FIND(prefix_index, &peer->adj_rib_out, &xp);
> + return NULL;
> +}
> +
> +/*
> + * Search for specified prefix in the pte adjout array that is for the
> + * specified path_id_tx and attrs. Returns NULL if not found.
> + */
> +static struct adjout_prefix *
> +adjout_prefix_with_attrs(struct pt_entry *pte, uint32_t path_id_tx,
> + struct adjout_attr *attrs)
> +{
> + struct adjout_prefix *p;
> + uint32_t i;
> +
> + for (i = 0; i < pte->adjoutlen; i++) {
> + p = &pte->adjout[i];
> + if (p->path_id_tx != path_id_tx)
same here
> + continue;
> + if (p->attrs == attrs)
> + return p;
> + if (p->path_id_tx > path_id_tx)
> + break;
> + }
> +
> + return NULL;
> }
bgpd: rewrite adj-out-rib code