Index | Thread | Search

From:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Subject:
bgpd: cleanup adjout_prefix dump upcalls
To:
tech@openbsd.org
Date:
Fri, 12 Dec 2025 13:27:00 +0100

Download raw body.

Thread
This step prepares for the next round of Adj-RIB-Out rework.
The adjout_prefix_dump upcalls gain a few extra arguments.
Both the peer and the pt_entry are now passed to the upcall since these
values will be removed from struct adjout_prefix.

While the change is simple it results in a lot of churn inside the rde rib
control message handler. Since the pte needs to be passed to the callbacks
the code doing the quick lookups got changed to use pt_lookup and friends
and use adjout_prefix_first() and adjout_prefix_next() to talk the
adj-rib-out. With this adjout_prefix_lookup() and adjout_prefix_match()
become unused.

In up_generate_default() the adjout_prefix_lookup() can be removed and
replaced with a adjout_prefix_first() call after the pte is fetched.

-- 
:wq Claudio

Index: rde.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.c,v
diff -u -p -r1.674 rde.c
--- rde.c	10 Dec 2025 12:36:51 -0000	1.674
+++ rde.c	11 Dec 2025 22:15:48 -0000
@@ -2937,8 +2937,8 @@ rde_dump_rib_as(struct prefix *p, struct
 }
 
 static void
-rde_dump_adjout_as(struct rde_peer *peer, struct adjout_prefix *p,
-    struct adjout_attr *attrs, pid_t pid, int flags)
+rde_dump_adjout_as(struct rde_peer *peer, struct pt_entry *pte,
+    struct adjout_prefix *p, struct adjout_attr *attrs, pid_t pid, int flags)
 {
 	struct ctl_show_rib	 rib;
 	struct ibuf		*wbuf;
@@ -2963,11 +2963,11 @@ rde_dump_adjout_as(struct rde_peer *peer
 		rib.true_nexthop = nexthop->true_nexthop;
 	} else {
 		/* announced network can have a NULL nexthop */
-		rib.exit_nexthop.aid = p->pt->aid;
-		rib.true_nexthop.aid = p->pt->aid;
+		rib.exit_nexthop.aid = pte->aid;
+		rib.true_nexthop.aid = pte->aid;
 	}
-	pt_getaddr(p->pt, &rib.prefix);
-	rib.prefixlen = p->pt->prefixlen;
+	pt_getaddr(pte, &rib.prefix);
+	rib.prefixlen = pte->prefixlen;
 	rib.origin = asp->origin;
 	/* roa and aspa vstate skipped, they don't matter in adj-rib-out */
 	rib.flags = 0;
@@ -2976,7 +2976,7 @@ rde_dump_adjout_as(struct rde_peer *peer
 		rib.flags |= F_PREF_INTERNAL;
 	if (asp->flags & F_PREFIX_ANNOUNCED)
 		rib.flags |= F_PREF_ANNOUNCE;
-	if (peer_has_add_path(peer, p->pt->aid, CAPA_AP_SEND)) {
+	if (peer_has_add_path(peer, pte->aid, CAPA_AP_SEND)) {
 		rib.path_id = p->path_id_tx;
 		rib.flags |= F_PREF_PATH_ID;
 	}
@@ -3074,15 +3074,15 @@ rde_dump_filter(struct prefix *p, struct
 }
 
 static void
-rde_dump_adjout_filter(struct rde_peer *peer, struct adjout_prefix *p,
-     struct adjout_attr *attrs, struct ctl_show_rib_request *req)
+rde_dump_adjout_filter(struct rde_peer *peer, struct pt_entry *pte,
+     struct adjout_prefix *p, struct ctl_show_rib_request *req)
 {
-	struct rde_aspath	*asp;
+	struct adjout_attr *attrs = p->attrs;
+	struct rde_aspath *asp = attrs->aspath;
 
 	if (!rde_match_peer(peer, &req->neighbor))
 		return;
 
-	asp = attrs->aspath;
 	if ((req->flags & F_CTL_HAS_PATHID)) {
 		/* Match against the transmit path id if adjout is used.  */
 		if (req->path_id != p->path_id_tx)
@@ -3096,7 +3096,7 @@ rde_dump_adjout_filter(struct rde_peer *
 			return;
 	}
 	/* in the adj-rib-out, skip matching against roa and aspa state */
-	rde_dump_adjout_as(peer, p, attrs, req->pid, req->flags);
+	rde_dump_adjout_as(peer, pte, p, attrs, req->pid, req->flags);
 }
 
 static void
@@ -3112,17 +3112,12 @@ rde_dump_upcall(struct rib_entry *re, vo
 }
 
 static void
-rde_dump_adjout_upcall(struct adjout_prefix *p, void *ptr)
+rde_dump_adjout_upcall(struct rde_peer *peer, struct pt_entry *pte,
+    struct adjout_prefix *p, void *ptr)
 {
 	struct rde_dump_ctx	*ctx = ptr;
-	struct rde_peer		*peer;
-	struct adjout_attr	*attrs;
-
-	if ((peer = peer_get(ctx->peerid)) == NULL)
-		return;
 
-	attrs = p->attrs;
-	rde_dump_adjout_filter(peer, p, attrs, &ctx->req);
+	rde_dump_adjout_filter(peer, pte, p, &ctx->req);
 }
 
 static int
@@ -3251,30 +3246,39 @@ rde_dump_ctx_new(struct ctl_show_rib_req
 			}
 
 			do {
+				struct pt_entry *pte;
+
 				if (req->flags & F_SHORTER) {
 					for (plen = 0; plen <= req->prefixlen;
 					    plen++) {
-						p = adjout_prefix_lookup(peer,
-						    &req->prefix, plen);
+						pte = pt_get(&req->prefix,
+						    plen);
+						if (pte == NULL)
+							continue;
 						/* dump all matching paths */
+						p = adjout_prefix_first(peer,
+						    pte);
 						while (p != NULL) {
 							rde_dump_adjout_upcall(
-							    p, ctx);
+							    peer, pte, p, ctx);
 							p = adjout_prefix_next(
 							    peer, p);
 						}
 					}
-					p = NULL;
+					continue;
 				} else if (req->prefixlen == hostplen) {
-					p = adjout_prefix_match(peer,
-					    &req->prefix);
+					pte = pt_lookup(&req->prefix);
 				} else {
-					p = adjout_prefix_lookup(peer,
-					    &req->prefix, req->prefixlen);
+					pte = pt_get(&req->prefix,
+					    req->prefixlen);
 				}
+				if (pte == NULL)
+					continue;
+
 				/* dump all matching paths */
+				p = adjout_prefix_first(peer, pte);
 				while (p != NULL) {
-					rde_dump_adjout_upcall(p, ctx);
+					rde_dump_adjout_upcall(peer, pte, p, ctx);
 					p = adjout_prefix_next(peer, p);
 				}
 			} while ((peer = peer_match(&req->neighbor,
@@ -3538,10 +3542,9 @@ rde_evaluate_all(void)
 
 /* flush Adj-RIB-Out by withdrawing all prefixes */
 static void
-rde_up_flush_upcall(struct adjout_prefix *p, void *ptr)
+rde_up_flush_upcall(struct rde_peer *peer, struct pt_entry *pte,
+    struct adjout_prefix *p, void *ptr)
 {
-	struct rde_peer *peer = ptr;
-
 	adjout_prefix_withdraw(peer, p);
 }
 
Index: rde.h
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde.h,v
diff -u -p -r1.330 rde.h
--- rde.h	11 Dec 2025 19:26:11 -0000	1.330
+++ rde.h	11 Dec 2025 22:06:06 -0000
@@ -361,7 +361,8 @@ struct rib_context {
 	struct adjout_prefix		*ctx_p;
 	uint32_t			 ctx_id;
 	void		(*ctx_rib_call)(struct rib_entry *, void *);
-	void		(*ctx_prefix_call)(struct adjout_prefix *, void *);
+	void		(*ctx_prefix_call)(struct rde_peer *,
+			    struct pt_entry *, struct adjout_prefix *, void *);
 	void		(*ctx_done)(void *, uint8_t);
 	int		(*ctx_throttle)(void *);
 	void				*ctx_arg;
@@ -739,10 +740,6 @@ struct adjout_prefix	*adjout_prefix_firs
 			    struct pt_entry *);
 struct adjout_prefix	*adjout_prefix_next(struct rde_peer *,
 			    struct adjout_prefix *);
-struct adjout_prefix	*adjout_prefix_lookup(struct rde_peer *,
-			    struct bgpd_addr *, int);
-struct adjout_prefix	*adjout_prefix_match(struct rde_peer *,
-			    struct bgpd_addr *);
 
 void		 prefix_add_eor(struct rde_peer *, uint8_t);
 void		 adjout_prefix_update(struct adjout_prefix *, struct rde_peer *,
@@ -757,11 +754,13 @@ void		 adjout_prefix_dump_cleanup(struct
 void		 adjout_prefix_dump_r(struct rib_context *);
 int		 adjout_prefix_dump_new(struct rde_peer *, uint8_t,
 		    unsigned int, void *,
-		    void (*)(struct adjout_prefix *, void *),
+		    void (*)(struct rde_peer *, struct pt_entry *,
+			struct adjout_prefix *, void *),
 		    void (*)(void *, uint8_t), int (*)(void *));
 int		 adjout_prefix_dump_subtree(struct rde_peer *,
 		    struct bgpd_addr *, uint8_t, unsigned int, void *,
-		    void (*)(struct adjout_prefix *, void *),
+		    void (*)(struct rde_peer *, struct pt_entry *,
+			struct adjout_prefix *, void *),
 		    void (*)(void *, uint8_t), int (*)(void *));
 void		 adjout_peer_init(struct rde_peer *);
 
Index: rde_adjout.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_adjout.c,v
diff -u -p -r1.10 rde_adjout.c
--- rde_adjout.c	11 Dec 2025 19:26:11 -0000	1.10
+++ rde_adjout.c	11 Dec 2025 22:07:58 -0000
@@ -491,49 +491,6 @@ adjout_prefix_next(struct rde_peer *peer
 }
 
 /*
- * Lookup addr/prefixlen in the peer prefix_index. Returns first match.
- * Returns NULL if not found.
- */
-struct adjout_prefix *
-adjout_prefix_lookup(struct rde_peer *peer, struct bgpd_addr *addr, int plen)
-{
-	return adjout_prefix_first(peer, pt_fill(addr, plen));
-}
-
-/*
- * Lookup addr in the peer prefix_index. Returns first match.
- * Returns NULL if not found.
- */
-struct adjout_prefix *
-adjout_prefix_match(struct rde_peer *peer, struct bgpd_addr *addr)
-{
-	struct adjout_prefix *p;
-	int i;
-
-	switch (addr->aid) {
-	case AID_INET:
-	case AID_VPN_IPv4:
-		for (i = 32; i >= 0; i--) {
-			p = adjout_prefix_lookup(peer, addr, i);
-			if (p != NULL)
-				return p;
-		}
-		break;
-	case AID_INET6:
-	case AID_VPN_IPv6:
-		for (i = 128; i >= 0; i--) {
-			p = adjout_prefix_lookup(peer, addr, i);
-			if (p != NULL)
-				return p;
-		}
-		break;
-	default:
-		fatalx("%s: unknown af", __func__);
-	}
-	return NULL;
-}
-
-/*
  * Put a prefix from the Adj-RIB-Out onto the update queue.
  */
 void
@@ -733,7 +690,7 @@ adjout_prefix_dump_r(struct rib_context 
 			ctx->ctx_p = adjout_prefix_lock(p);
 			return;
 		}
-		ctx->ctx_prefix_call(p, ctx->ctx_arg);
+		ctx->ctx_prefix_call(peer, p->pt, p, ctx->ctx_arg);
 	}
 
 done:
@@ -744,9 +701,12 @@ done:
 }
 
 int
-adjout_prefix_dump_new(struct rde_peer *peer, uint8_t aid, unsigned int count,
-    void *arg, void (*upcall)(struct adjout_prefix *, void *),
-    void (*done)(void *, uint8_t), int (*throttle)(void *))
+adjout_prefix_dump_new(struct rde_peer *peer, uint8_t aid,
+    unsigned int count, void *arg,
+    void (*upcall)(struct rde_peer *, struct pt_entry *,
+	struct adjout_prefix *, void *),
+    void (*done)(void *, uint8_t),
+    int (*throttle)(void *))
 {
 	struct rib_context *ctx;
 
@@ -772,7 +732,8 @@ adjout_prefix_dump_new(struct rde_peer *
 int
 adjout_prefix_dump_subtree(struct rde_peer *peer, struct bgpd_addr *subtree,
     uint8_t subtreelen, unsigned int count, void *arg,
-    void (*upcall)(struct adjout_prefix *, void *),
+    void (*upcall)(struct rde_peer *, struct pt_entry *,
+	struct adjout_prefix *, void *),
     void (*done)(void *, uint8_t),
     int (*throttle)(void *))
 {
Index: rde_peer.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_peer.c,v
diff -u -p -r1.60 rde_peer.c
--- rde_peer.c	10 Dec 2025 12:36:51 -0000	1.60
+++ rde_peer.c	11 Dec 2025 19:26:58 -0000
@@ -518,14 +518,10 @@ peer_stale(struct rde_peer *peer, uint8_
  * Enqueue a prefix onto the update queue so it can be sent out.
  */
 static void
-peer_blast_upcall(struct adjout_prefix *p, void *ptr)
+peer_blast_upcall(struct rde_peer *peer, struct pt_entry *pte,
+    struct adjout_prefix *p, void *ptr)
 {
-	struct rde_peer		*peer = ptr;
-	struct adjout_attr	*attrs = NULL;
-
-	attrs = p->attrs;
-
-	pend_prefix_add(peer, attrs, p->pt, p->path_id_tx);
+	pend_prefix_add(peer, p->attrs, pte, p->path_id_tx);
 }
 
 /*
Index: rde_update.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_update.c,v
diff -u -p -r1.188 rde_update.c
--- rde_update.c	10 Dec 2025 12:36:51 -0000	1.188
+++ rde_update.c	11 Dec 2025 19:59:02 -0000
@@ -417,7 +417,6 @@ up_generate_default(struct rde_peer *pee
 
 	memset(&addr, 0, sizeof(addr));
 	addr.aid = aid;
-	p = adjout_prefix_lookup(peer, &addr, 0);
 
 	/* outbound filter as usual */
 	if (rde_filter(peer->out_rules, peer, peerself, &addr, 0, &state) ==
@@ -431,6 +430,7 @@ up_generate_default(struct rde_peer *pee
 	pte = pt_get(&addr, 0);
 	if (pte == NULL)
 		pte = pt_add(&addr, 0);
+	p = adjout_prefix_first(peer, pte);
 	adjout_prefix_update(p, peer, &state, pte, 0);
 	rde_filterstate_clean(&state);