From: Mark Johnston Subject: avoid flushing relayd pf tables during config reload To: tech@openbsd.org Date: Mon, 7 Apr 2025 12:48:37 -0400 Hi, One user of relayd on FreeBSD reported a problem where pf redirects installed by relayd would not apply when connections arrive in the middle of a relayd config reload. The reload window is generally quite short, but connectivity problems were noticeable nonetheless. A patch is below; I tested it manually against OpenBSD 7.6 and ran the regression tests. More specifically, when handling a config reload, relayd's PFE receives all of the new config structures (redirects, tables, etc.), and then flushes all of the corresponding pf tables prior to syncing them with pf. This behaviour results in a small window where a redirect rule will fail to handle new connection requests. I believe the intent behind flushing here is just to ensure that disabled redirects are removed from the ruleset. pfe_sync() and sync_table() will handle the case where a table's contents change across a reload. So, the patch stops relayd from flushing a table unless it was explicitly disabled. diff --git a/usr.sbin/relayd/pfe_filter.c b/usr.sbin/relayd/pfe_filter.c index c1851260c62..7fe0c30cf4c 100644 --- a/usr.sbin/relayd/pfe_filter.c +++ b/usr.sbin/relayd/pfe_filter.c @@ -91,10 +91,14 @@ init_tables(struct relayd *env) return; /* - * clear all tables, since some already existed + * Clear disabled tables and tables belonging to disabled redirects. + * Don't touch enabled tables since that could disrupt traffic. */ - TAILQ_FOREACH(rdr, env->sc_rdrs, entry) - flush_table(env, rdr); + TAILQ_FOREACH(rdr, env->sc_rdrs, entry) { + if (rdr->conf.flags & F_DISABLE || + rdr->table->conf.flags & F_DISABLE) + flush_table(env, rdr); + } return;