Index | Thread | Search

From:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Subject:
bgpd: prefix_evaluate is tricky
To:
tech@openbsd.org
Date:
Thu, 14 May 2026 15:36:33 +0200

Download raw body.

Thread
I tricked myself again in thinking that changing the state of a prefix and
then calling prefix_evaluate(re, p, p); would do the right thing.
It does not, at least not in all cases.

The problem is that prefix_evaluate() uses prefix_best() to decide if the
overall route decision changed or not. prefix_best() is influenced by
prefix_eligible() and so changing PREFIX_FLAG_FILTERED also affects the
prefix_best() calls inside prefix_evaluate().

If the only prefix sets PREFIX_FLAG_FILTERED then the code would not
correctly withdraw the route. In the current code
	oldbest = prefix_best(re);
already returns NULL even though the path is still active.

This is similar to prefix_evaluate_nexthop() but I decided to fix this
with a more brutal method. First remove the prefix, then readd it.
Since the flag is toggled no real extra work should be caused by this.

-- 
:wq Claudio

Index: rde_rib.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v
diff -u -p -r1.293 rde_rib.c
--- rde_rib.c	13 May 2026 14:06:24 -0000	1.293
+++ rde_rib.c	14 May 2026 13:22:56 -0000
@@ -890,11 +890,13 @@ prefix_update(struct rib *rib, struct rd
 			if (p_filtered != filtered) {
 				struct rib_entry	*re;
 
+				re = rib_get_addr(rib, prefix, prefixlen);
+				/* remove prefix from rib */
+				prefix_evaluate(re, NULL, p);
 				/* toggle filtered flag */
 				p->flags ^= PREFIX_FLAG_FILTERED;
-				/* make route decision */
-				re = rib_get_addr(rib, prefix, prefixlen);
-				prefix_evaluate(re, p, p);
+				/* redo route decision */
+				prefix_evaluate(re, p, NULL);
 			}
 			return (0);
 		}