git: a928edf20d46 - stable/15 - pf: modify pfik_flags atomically
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 28 Oct 2026 20:35:39 UTC
The branch stable/15 has been updated by rcm:
URL: https://cgit.FreeBSD.org/src/commit/?id=a928edf20d46a2a2d1de3ea1f40a687e31683313
commit a928edf20d46a2a2d1de3ea1f40a687e31683313
Author: R. Christian McDonald <rcm@FreeBSD.org>
AuthorDate: 2026-09-30 22:56:22 +0000
Commit: R. Christian McDonald <rcm@FreeBSD.org>
CommitDate: 2026-10-28 20:34:03 +0000
pf: modify pfik_flags atomically
The purge thread sets PFI_IFLAG_REFS on the interfaces that states
refer to without the rules lock, under which the other flags are
changed. The updates can interleave, so that a "set skip on" is lost,
or outlives its removal, until the next ruleset load.
Use atomic operations to modify the flags. In the purge thread, only
write if the flag is not already set.
Reviewed by: kp
Approved by: kp (mentor)
MFC after: 1 week
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D60107
(cherry picked from commit c1241c6e30c792fb514f4689d2ed92ee21d3cf39)
---
sys/netpfil/pf/pf.c | 12 ++++++++++--
sys/netpfil/pf/pf_if.c | 10 +++++-----
2 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index ea081fa90b34..8c2b905b4ba0 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -2908,6 +2908,14 @@ pf_free_state(struct pf_kstate *cur)
pf_counter_u64_add(&V_pf_status.fcounters[FCNT_STATE_REMOVALS], 1);
}
+static inline void
+pf_kkif_mark(struct pfi_kkif *kif)
+{
+
+ if ((atomic_load_int(&kif->pfik_flags) & PFI_IFLAG_REFS) == 0)
+ atomic_set_int(&kif->pfik_flags, PFI_IFLAG_REFS);
+}
+
/*
* Called only from pf_purge_thread(), thus serialized.
*/
@@ -2943,11 +2951,11 @@ relock:
s->nat_rule->rule_ref |= PFRULE_REFS;
if (s->anchor != NULL)
s->anchor->rule_ref |= PFRULE_REFS;
- s->kif->pfik_flags |= PFI_IFLAG_REFS;
+ pf_kkif_mark(s->kif);
SLIST_FOREACH(mrm, &s->match_rules, entry)
mrm->r->rule_ref |= PFRULE_REFS;
if (s->act.rt_kif)
- s->act.rt_kif->pfik_flags |= PFI_IFLAG_REFS;
+ pf_kkif_mark(s->act.rt_kif);
count++;
}
PF_HASHROW_UNLOCK(ih);
diff --git a/sys/netpfil/pf/pf_if.c b/sys/netpfil/pf/pf_if.c
index 5703c6712d80..d108d7a2e86a 100644
--- a/sys/netpfil/pf/pf_if.c
+++ b/sys/netpfil/pf/pf_if.c
@@ -421,7 +421,7 @@ pfi_kkif_remove_if_unref(struct pfi_kkif *kif)
}
RB_REMOVE(pfi_ifhead, &V_pfi_ifs, kif);
- kif->pfik_flags |= PFI_IFLAG_REFS;
+ atomic_set_int(&kif->pfik_flags, PFI_IFLAG_REFS);
mtx_lock(&pfi_unlnkdkifs_mtx);
LIST_INSERT_HEAD(&V_pfi_unlinked_kifs, kif, pfik_list);
@@ -455,7 +455,7 @@ pfi_kkif_purge(void)
LIST_REMOVE(kif, pfik_list);
pf_kkif_free(kif);
} else
- kif->pfik_flags &= ~PFI_IFLAG_REFS;
+ atomic_clear_int(&kif->pfik_flags, PFI_IFLAG_REFS);
}
mtx_unlock(&pfi_unlnkdkifs_mtx);
}
@@ -648,7 +648,7 @@ pfi_kkif_update(struct pfi_kkif *kif)
if (tmpkif == NULL)
continue;
- tmpkif->pfik_flags |= kif->pfik_flags;
+ atomic_set_int(&tmpkif->pfik_flags, kif->pfik_flags);
}
}
@@ -1006,7 +1006,7 @@ pfi_set_flags(const char *name, int flags)
RB_FOREACH(p, pfi_ifhead, &V_pfi_ifs) {
if (pfi_skip_if(name, p))
continue;
- p->pfik_flags |= flags;
+ atomic_set_int(&p->pfik_flags, flags);
}
NET_EPOCH_EXIT(et);
return (0);
@@ -1022,7 +1022,7 @@ pfi_clear_flags(const char *name, int flags)
RB_FOREACH_SAFE(p, pfi_ifhead, &V_pfi_ifs, tmp) {
if (pfi_skip_if(name, p))
continue;
- p->pfik_flags &= ~flags;
+ atomic_clear_int(&p->pfik_flags, flags);
if (p->pfik_ifp == NULL && p->pfik_group == NULL &&
p->pfik_flags == 0 && p->pfik_rulerefs == 0) {