git: c1241c6e30c7 - main - pf: modify pfik_flags atomically
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 30 Sep 2026 23:19:03 UTC
The branch main has been updated by rcm:
URL: https://cgit.FreeBSD.org/src/commit/?id=c1241c6e30c792fb514f4689d2ed92ee21d3cf39
commit c1241c6e30c792fb514f4689d2ed92ee21d3cf39
Author: R. Christian McDonald <rcm@FreeBSD.org>
AuthorDate: 2026-09-30 22:56:22 +0000
Commit: R. Christian McDonald <rcm@FreeBSD.org>
CommitDate: 2026-09-30 22:56:22 +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
---
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 9c9509900ea9..73e6900ec6eb 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -3223,6 +3223,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.
*/
@@ -3258,11 +3266,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 aed1af15fb30..7528e920e433 100644
--- a/sys/netpfil/pf/pf_if.c
+++ b/sys/netpfil/pf/pf_if.c
@@ -426,7 +426,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);
@@ -460,7 +460,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);
}
@@ -660,7 +660,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);
}
}
@@ -1018,7 +1018,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);
@@ -1034,7 +1034,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) {