The branch main has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=7a66b3008693ce61957e8b2a3d99829063e1e4af

commit 7a66b3008693ce61957e8b2a3d99829063e1e4af
Author:     Mark Johnston <ma...@freebsd.org>
AuthorDate: 2025-02-06 14:36:20 +0000
Commit:     Mark Johnston <ma...@freebsd.org>
CommitDate: 2025-02-06 16:25:42 +0000

    pf: Stop using net_epoch to synchronize access to eth rules
    
    Commit 20c4899a8eea4 modified pf_test_eth_rule() to not acquire the
    rules read lock, so pf_commit_eth() was changed to wait until the
    now-inactive rules are no longer in use before freeing them.  In
    particular, it uses the net_epoch to schedule callbacks once the
    inactive rules are no longer visible to packet processing threads.
    
    However, since commit 812839e5aaaf4, pf_test_eth_rule() acquires the
    rules read lock, so this deferred action is unneeded.  This patch
    reverts a portion of 20c4899a8eea4 such that we avoid using deferred
    callbacks to free inactive rules.
    
    The main motivation is performance: epoch_drain_callbacks() is quite
    slow, especially on busy systems, and its use in the DIOCXBEGIN handler
    in particular causes long stalls in relayd when reloading configuration.
    
    Reviewed by:    kp
    MFC after:      2 weeks
    Sponsored by:   Klara, Inc.
    Sponsored by:   Modirum MDPay
    Differential Revision:  https://reviews.freebsd.org/D48822
---
 sys/net/pfvar.h           |  1 -
 sys/netpfil/pf/pf.c       |  9 +++------
 sys/netpfil/pf/pf_ioctl.c | 32 +++-----------------------------
 3 files changed, 6 insertions(+), 36 deletions(-)

diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 3e2f17520b91..5ef7957f4fa0 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -687,7 +687,6 @@ struct pf_keth_ruleset {
                int                      open;
                uint32_t                 ticket;
        } active, inactive;
-       struct epoch_context     epoch_ctx;
        struct vnet             *vnet;
        struct pf_keth_anchor   *anchor;
 };
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index 1cfd1a11db53..4d8a0f2aba31 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -5186,11 +5186,6 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct 
mbuf **m0)
                return (PF_PASS);
        }
 
-       ruleset = V_pf_keth;
-       rules = ck_pr_load_ptr(&ruleset->active.rules);
-       r = TAILQ_FIRST(rules);
-       rm = NULL;
-
        if (__predict_false(m->m_len < sizeof(struct ether_header)) &&
            (m = *m0 = m_pullup(*m0, sizeof(struct ether_header))) == NULL) {
                DPFPRINTF(PF_DEBUG_URGENT,
@@ -5234,7 +5229,9 @@ pf_test_eth_rule(int dir, struct pfi_kkif *kif, struct 
mbuf **m0)
 
        PF_RULES_RLOCK();
 
-       while (r != NULL) {
+       ruleset = V_pf_keth;
+       rules = atomic_load_ptr(&ruleset->active.rules);
+       for (r = TAILQ_FIRST(rules), rm = NULL; r != NULL;) {
                counter_u64_add(r->evaluations, 1);
                SDT_PROBE2(pf, eth, test_rule, test, r->nr, r);
 
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index a45db33f38dc..b8e9a078baf2 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -107,7 +107,6 @@ static void          pf_empty_kpool(struct pf_kpalist *);
 static int              pfioctl(struct cdev *, u_long, caddr_t, int,
                            struct thread *);
 static int              pf_begin_eth(uint32_t *, const char *);
-static void             pf_rollback_eth_cb(struct epoch_context *);
 static int              pf_rollback_eth(uint32_t, const char *);
 static int              pf_commit_eth(uint32_t, const char *);
 static void             pf_free_eth_rule(struct pf_keth_rule *);
@@ -794,23 +793,6 @@ pf_begin_eth(uint32_t *ticket, const char *anchor)
        return (0);
 }
 
-static void
-pf_rollback_eth_cb(struct epoch_context *ctx)
-{
-       struct pf_keth_ruleset *rs;
-
-       rs = __containerof(ctx, struct pf_keth_ruleset, epoch_ctx);
-
-       CURVNET_SET(rs->vnet);
-
-       PF_RULES_WLOCK();
-       pf_rollback_eth(rs->inactive.ticket,
-           rs->anchor ? rs->anchor->path : "");
-       PF_RULES_WUNLOCK();
-
-       CURVNET_RESTORE();
-}
-
 static int
 pf_rollback_eth(uint32_t ticket, const char *anchor)
 {
@@ -904,15 +886,12 @@ pf_commit_eth(uint32_t ticket, const char *anchor)
        pf_eth_calc_skip_steps(rs->inactive.rules);
 
        rules = rs->active.rules;
-       ck_pr_store_ptr(&rs->active.rules, rs->inactive.rules);
+       atomic_store_ptr(&rs->active.rules, rs->inactive.rules);
        rs->inactive.rules = rules;
        rs->inactive.ticket = rs->active.ticket;
 
-       /* Clean up inactive rules (i.e. previously active rules), only when
-        * we're sure they're no longer used. */
-       NET_EPOCH_CALL(pf_rollback_eth_cb, &rs->epoch_ctx);
-
-       return (0);
+       return (pf_rollback_eth(rs->inactive.ticket,
+           rs->anchor ? rs->anchor->path : ""));
 }
 
 #ifdef ALTQ
@@ -5179,8 +5158,6 @@ DIOCCHANGEADDR_error:
                        free(ioes, M_TEMP);
                        break;
                }
-               /* Ensure there's no more ethernet rules to clean up. */
-               NET_EPOCH_DRAIN_CALLBACKS();
                PF_RULES_WLOCK();
                for (i = 0, ioe = ioes; i < io->size; i++, ioe++) {
                        ioe->anchor[sizeof(ioe->anchor) - 1] = '\0';
@@ -6805,9 +6782,6 @@ pf_unload_vnet(void)
        shutdown_pf();
        PF_RULES_WUNLOCK();
 
-       /* Make sure we've cleaned up ethernet rules before we continue. */
-       NET_EPOCH_DRAIN_CALLBACKS();
-
        ret = swi_remove(V_pf_swi_cookie);
        MPASS(ret == 0);
        ret = intr_event_destroy(V_pf_swi_ie);

Reply via email to