Download raw body.
move some pf_status counters to per cpu counters
currently there's a bunch of global pf stats that are collected in a
single struct. we've been moving counters in other subsystems to per cpu
counters, it makes sense to follow suit here.
this is the lowest hanging fruit in pf_status. the search counter is
updated every time the state table is searched, which is a lot. once
this is in i can move a few of the other chunks of stats to per cpu
counters too.
ok?
Index: pf.c
===================================================================
RCS file: /cvs/src/sys/net/pf.c,v
diff -u -p -r1.1219 pf.c
--- pf.c 11 Nov 2025 04:06:20 -0000 1.1219
+++ pf.c 27 Nov 2025 23:14:43 -0000
@@ -49,6 +49,7 @@
#include <sys/pool.h>
#include <sys/proc.h>
#include <sys/rwlock.h>
+#include <sys/percpu.h>
#include <sys/syslog.h>
#include <crypto/sha2.h>
@@ -101,6 +102,7 @@ struct pf_queuehead *pf_queues_active;
struct pf_queuehead *pf_queues_inactive;
struct pf_status pf_status;
+static struct cpumem *pf_status_fcounters;
struct mutex pf_inp_mtx = MUTEX_INITIALIZER(IPL_SOFTNET);
@@ -1337,7 +1339,7 @@ pf_state_insert(struct pfi_kif *kif, str
return (-1);
}
pf_state_list_insert(&pf_state_list, st);
- pf_status.fcounters[FCNT_STATE_INSERT]++;
+ counters_inc(pf_status_fcounters, FCNT_STATE_INSERT);
pf_status.states++;
pfi_kif_ref(kif, PFI_KIF_REF_STATE);
PF_STATE_EXIT_WRITE();
@@ -1355,7 +1357,7 @@ pf_state_insert(struct pfi_kif *kif, str
struct pf_state *
pf_find_state_byid(struct pf_state_cmp *key)
{
- pf_status.fcounters[FCNT_STATE_SEARCH]++;
+ counters_inc(pf_status_fcounters, FCNT_STATE_SEARCH);
return (RBT_FIND(pf_state_tree_id, &tree_id, (struct pf_state *)key));
}
@@ -1402,7 +1404,7 @@ pf_find_state(struct pf_pdesc *pd, struc
struct pf_state_item *si;
struct pf_state *st = NULL;
- pf_status.fcounters[FCNT_STATE_SEARCH]++;
+ counters_inc(pf_status_fcounters, FCNT_STATE_SEARCH);
if (pf_status.debug >= LOG_DEBUG) {
log(LOG_DEBUG, "pf: key search, %s on %s: ",
pd->dir == PF_OUT ? "out" : "in", pd->kif->pfik_name);
@@ -1503,7 +1505,7 @@ pf_find_state_all(struct pf_state_key_cm
struct pf_state_key *sk;
struct pf_state_item *si, *ret = NULL;
- pf_status.fcounters[FCNT_STATE_SEARCH]++;
+ counters_inc(pf_status_fcounters, FCNT_STATE_SEARCH);
sk = RBT_FIND(pf_state_tree, &pf_statetbl, (struct pf_state_key *)key);
@@ -2226,7 +2228,7 @@ pf_free_state(struct pf_state *st)
if (st->tag)
pf_tag_unref(st->tag);
pf_state_unref(st);
- pf_status.fcounters[FCNT_STATE_REMOVALS]++;
+ counters_inc(pf_status_fcounters, FCNT_STATE_REMOVALS);
pf_status.states--;
}
@@ -9054,4 +9056,41 @@ pf_pktenqueue_delayed(void *arg)
m_freem(pdy->m);
pool_put(&pf_pktdelay_pl, pdy);
+}
+
+void
+pf_status_init(void)
+{
+ memset(&pf_status, 0, sizeof(pf_status));
+ pf_status.debug = LOG_ERR;
+ pf_status.reass = PF_REASS_ENABLED;
+
+ /* XXX do our best to avoid a conflict */
+ pf_status.hostid = arc4random();
+
+ pf_status_fcounters = counters_alloc(FCNT_MAX);
+}
+
+void
+pf_status_clear(void)
+{
+ PF_ASSERT_LOCKED();
+ counters_zero(pf_status_fcounters, FCNT_MAX);
+}
+
+void
+pf_status_read(struct pf_status *pfs)
+{
+ uint64_t scratch[FCNT_MAX];
+
+ NET_LOCK();
+ PF_LOCK();
+ PF_FRAG_LOCK();
+ memcpy(pfs, &pf_status, sizeof(struct pf_status));
+ PF_FRAG_UNLOCK();
+ pfi_update_status(pfs->ifname, pfs);
+ PF_UNLOCK();
+ NET_UNLOCK();
+
+ counters_read(pf_status_fcounters, pfs->fcounters, FCNT_MAX, scratch);
}
Index: pf_ioctl.c
===================================================================
RCS file: /cvs/src/sys/net/pf_ioctl.c,v
diff -u -p -r1.426 pf_ioctl.c
--- pf_ioctl.c 20 Nov 2025 10:47:44 -0000 1.426
+++ pf_ioctl.c 27 Nov 2025 23:14:43 -0000
@@ -290,12 +290,7 @@ pfattach(int num)
pf_default_rule.route.addr.type = PF_ADDR_NONE;
pf_normalize_init();
- memset(&pf_status, 0, sizeof(pf_status));
- pf_status.debug = LOG_ERR;
- pf_status.reass = PF_REASS_ENABLED;
-
- /* XXX do our best to avoid a conflict */
- pf_status.hostid = arc4random();
+ pf_status_init();
pf_default_rule_new = pf_default_rule;
@@ -2914,18 +2909,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
error = pf_states_get((struct pfioc_states *)addr);
break;
- case DIOCGETSTATUS: {
- struct pf_status *s = (struct pf_status *)addr;
- NET_LOCK();
- PF_LOCK();
- PF_FRAG_LOCK();
- memcpy(s, &pf_status, sizeof(struct pf_status));
- PF_FRAG_UNLOCK();
- pfi_update_status(s->ifname, s);
- PF_UNLOCK();
- NET_UNLOCK();
+ case DIOCGETSTATUS:
+ pf_status_read((struct pf_status *)addr);
break;
- }
case DIOCSETSTATUSIF: {
struct pfioc_iface *pi = (struct pfioc_iface *)addr;
@@ -2958,8 +2944,8 @@ pfioctl(dev_t dev, u_long cmd, caddr_t a
goto fail;
}
+ pf_status_clear();
memset(pf_status.counters, 0, sizeof(pf_status.counters));
- memset(pf_status.fcounters, 0, sizeof(pf_status.fcounters));
memset(pf_status.scounters, 0, sizeof(pf_status.scounters));
PF_FRAG_LOCK();
memset(pf_status.ncounters, 0, sizeof(pf_status.ncounters));
@@ -4215,14 +4201,7 @@ pf_sysctl(void *oldp, size_t *oldlenp, v
{
struct pf_status pfs;
- NET_LOCK_SHARED();
- PF_LOCK();
- PF_FRAG_LOCK();
- memcpy(&pfs, &pf_status, sizeof(struct pf_status));
- PF_FRAG_UNLOCK();
- pfi_update_status(pfs.ifname, &pfs);
- PF_UNLOCK();
- NET_UNLOCK_SHARED();
+ pf_status_read(&pfs);
return sysctl_rdstruct(oldp, oldlenp, newp, &pfs, sizeof(pfs));
}
Index: pfvar_priv.h
===================================================================
RCS file: /cvs/src/sys/net/pfvar_priv.h,v
diff -u -p -r1.39 pfvar_priv.h
--- pfvar_priv.h 11 Nov 2025 04:06:20 -0000 1.39
+++ pfvar_priv.h 27 Nov 2025 23:14:43 -0000
@@ -680,6 +680,10 @@ u_int16_t pf_pkt_hash(sa_family_t, uint
const struct pf_addr *, const struct pf_addr *,
uint16_t, uint16_t);
+void pf_status_init(void);
+void pf_status_clear(void);
+void pf_status_read(struct pf_status *);
+
#endif /* _KERNEL */
#endif /* _NET_PFVAR_PRIV_H_ */
move some pf_status counters to per cpu counters