Index | Thread | Search

From:
Claudio Jeker <cjeker@diehard.n-r-g.com>
Subject:
bgpd: reduce time spent in rib_dump_runner()
To:
tech@openbsd.org
Date:
Sat, 27 Dec 2025 17:17:31 +0100

Download raw body.

Thread
In some cases the RDE ends up with many RIB dump runners active and so
the rib_dump_runner() code consumes a lot of time to churn through all
of those calls.

Try to limit the time spend in rib_dump_runner() to roughly 10ms and
then stop and restart from that point on the next poll loop round.

This again ensures that the poll loop is not blocked for too long and
improves the overall responsiveness of bgpd.

In rib_dump_free() the code needs to check if the ctx is the currently
queued ctx and if so replace it with the next one in the list.
-- 
:wq Claudio

Index: rde_rib.c
===================================================================
RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v
diff -u -p -r1.285 rde_rib.c
--- rde_rib.c	24 Dec 2025 07:59:55 -0000	1.285
+++ rde_rib.c	27 Dec 2025 16:09:53 -0000
@@ -52,6 +52,7 @@ RB_PROTOTYPE(rib_tree, rib_entry, rib_e,
 RB_GENERATE(rib_tree, rib_entry, rib_e, rib_compare);
 
 LIST_HEAD(, rib_context) rib_dumps = LIST_HEAD_INITIALIZER(rib_dumps);
+static struct rib_context *rib_dump_ctx;
 
 static inline struct rib_entry *
 re_lock(struct rib_entry *re)
@@ -439,8 +440,19 @@ void
 rib_dump_runner(void)
 {
 	struct rib_context *ctx, *next;
+	monotime_t start;
 
-	LIST_FOREACH_SAFE(ctx, &rib_dumps, entry, next) {
+	start = getmonotime();
+
+	if (rib_dump_ctx != NULL)
+		ctx = rib_dump_ctx;
+	else
+		ctx = LIST_FIRST(&rib_dumps);
+
+	for (; ctx != NULL; ctx = next) {
+		next = LIST_NEXT(ctx, entry);
+		if (monotime_to_msec(monotime_sub(getmonotime(), start)) > 10)
+			break;
 		if (ctx->ctx_throttle && ctx->ctx_throttle(ctx->ctx_arg))
 			continue;
 		if (ctx->ctx_rib_call != NULL)
@@ -448,6 +460,7 @@ rib_dump_runner(void)
 		else
 			adjout_prefix_dump_r(ctx);
 	}
+	rib_dump_ctx = ctx;
 }
 
 static void
@@ -467,6 +480,8 @@ rib_dump_free(struct rib_context *ctx)
 		rib_dump_cleanup(ctx);
 	if (ctx->ctx_pt)
 		adjout_prefix_dump_cleanup(ctx);
+	if (ctx == rib_dump_ctx)
+		rib_dump_ctx = LIST_NEXT(ctx, entry);
 	LIST_REMOVE(ctx, entry);
 	free(ctx);
 }