Download raw body.
bgpd: rework rde_enqueue_updates() to simplify the rib queue handling
bgpd: rework rde_enqueue_updates() to simplify the rib queue handling
bgpd: rework rde_enqueue_updates() to simplify the rib queue handling
On Wed, Jul 01, 2026 at 10:24:04AM +0200, Theo Buehler wrote:
> > > > @@ -588,7 +591,7 @@ prefix_evaluate(struct rib_entry *re, st
> > > > /* no old path to remove and path is ineligible, skip rest */
> > > > if (old_pathid_tx == 0 && new == NULL)
> > > > return;
> > > > - rde_enqueue_updates(re, new, old_pathid_tx, EVAL_ALL);
> > > > + rde_enqueue_updates(re, peer, new, old_pathid_tx, EVAL_ALL);
> > >
> > > While at this point we know old_pathid_tx != 0 || new != NULL, so we
> > > know that peer has been initialized, this isn't super obvious and far
> > > beyond gcc's deduction capabilities (both gcc 4.2.1 and 15.1 whine).
> > >
> > > I don't see a good fix (if we do want to fix this). Doing peer = NULL
> > > at the top and changing the above to
> > >
> > > if ((old_pathid_tx == 0 && new == NULL) || peer == NULL)
> > > return;
> > >
> > > doesn't look like an improvement to me...
> >
> > Hmmm. I'll have a closer look. We certainly can initalize peer = NULL at
> > the top. Not sure if we need to check for peer == NULL though.
>
> Then the "problem" becomes that rde_enqueue_updates(..., EVAL_ALL) may
> deref peer, which again isn't obviously excluded.
I would like to commit this version of prefix_evaluate().
This adds an extra check that new and old are not both NULL and sets peer
to NULL. Also use old == NULL instead of old_pathid_tx == 0 in the later
check. The rest of the function also checks on old.
--
:wq Claudio
Index: rde_decide.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_decide.c,v
diff -u -p -r1.108 rde_decide.c
--- rde_decide.c 21 May 2026 15:20:27 -0000 1.108
+++ rde_decide.c 1 Jul 2026 08:46:11 -0000
@@ -534,9 +534,13 @@ void
prefix_evaluate(struct rib_entry *re, struct prefix *new, struct prefix *old)
{
struct prefix *newbest, *oldbest;
+ struct rde_peer *peer = NULL;
struct rib *rib;
uint32_t old_pathid_tx = 0;
+ if (old == NULL && new == NULL)
+ fatalx("king bula sez: nothing to evaluate");
+
rib = re_rib(re);
if (rib->flags & F_RIB_NOEVALUATE) {
/* decision process is turned off */
@@ -553,6 +557,7 @@ prefix_evaluate(struct rib_entry *re, st
if (old != NULL) {
prefix_remove(old, re);
old_pathid_tx = old->path_id_tx;
+ peer = prefix_peer(old);
}
if (new != NULL) {
prefix_insert(new, NULL, re);
@@ -560,6 +565,7 @@ prefix_evaluate(struct rib_entry *re, st
new = NULL;
else
old_pathid_tx = 0;
+ peer = prefix_peer(new);
}
newbest = prefix_best(re);
@@ -575,7 +581,7 @@ prefix_evaluate(struct rib_entry *re, st
*/
if ((rib->flags & F_RIB_NOFIB) == 0)
rde_send_kroute(rib, newbest, oldbest);
- rde_enqueue_updates(re, new, old_pathid_tx, EVAL_DEFAULT);
+ rde_enqueue_updates(re, peer, new, old_pathid_tx, EVAL_DEFAULT);
return;
}
@@ -586,9 +592,9 @@ prefix_evaluate(struct rib_entry *re, st
*/
if (rde_evaluate_all()) {
/* no old path to remove and path is ineligible, skip rest */
- if (old_pathid_tx == 0 && new == NULL)
+ if (old == NULL && new == NULL)
return;
- rde_enqueue_updates(re, new, old_pathid_tx, EVAL_ALL);
+ rde_enqueue_updates(re, peer, new, old_pathid_tx, EVAL_ALL);
}
}
bgpd: rework rde_enqueue_updates() to simplify the rib queue handling
bgpd: rework rde_enqueue_updates() to simplify the rib queue handling
bgpd: rework rde_enqueue_updates() to simplify the rib queue handling