Index | Thread | Search

From:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Subject:
bgpd: fix error handling PREFIX_FLAG_FILTERED
To:
tech@openbsd.org
Date:
Mon, 4 May 2026 21:15:11 +0200

Download raw body.

Thread
With the introduction of 'rde rib Loc-RIB include filtered' it is possible
that prefixes change prefix_eligible() outcome without a change of
attributes or nexthop. This happens when new filters are installed.
 
In prefix_update() this takes a shortcut path but that path is missing a
call to prefix_evaluate() to ensure that if the filtered flag changes an
update is forced.

Below is my try to fix this. If the filtered state changed, toggle the
PREFIX_FLAG_FILTERED bit and then call prefix_evaluate(). If the filtered
flag is in sync with filtered then this can be skipped.

I used p_filtered to be 0 or 1 and check against !filtered (to ensure that
this value is also 0 or 1). I hope that's not too much magic...
-- 
:wq Claudio

Index: rde_rib.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v
diff -u -p -r1.290 rde_rib.c
--- rde_rib.c	17 Mar 2026 09:29:29 -0000	1.290
+++ rde_rib.c	4 May 2026 18:36:51 -0000
@@ -872,13 +872,22 @@ prefix_update(struct rib *rib, struct rd
 		    prefix_nhflags(p) == state->nhflags &&
 		    communities_equal(ncomm, prefix_communities(p)) &&
 		    path_equal(nasp, prefix_aspath(p))) {
+			int p_filtered;
+
 			/* no change, update last change */
 			p->lastchange = getmonotime();
 			p->validation_state = state->vstate;
-			if (filtered)
-				p->flags |= PREFIX_FLAG_FILTERED;
-			else
-				p->flags &= ~PREFIX_FLAG_FILTERED;
+			p_filtered = (p->flags & PREFIX_FLAG_FILTERED) != 0;
+			/* check if filtered flag changed */
+			if (p_filtered == !filtered) {
+				struct rib_entry	*re;
+
+				/* toggle filtered flag */
+				p->flags ^= PREFIX_FLAG_FILTERED;
+				/* make route decision */
+				re = rib_get_addr(rib, prefix, prefixlen);
+				prefix_evaluate(re, p, p);
+			}
 			return (0);
 		}
 	}