--- a/sys/net/pf/pf_table.c +++ b/sys/net/pf/pf_table.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -137,6 +138,12 @@ struct malloc_type *pfr_kentry_pl; struct malloc_type *pfr_kentry_pl2; static struct pf_addr pfr_ffaddr; /* constant after setup */ +/* + * Serializes packet-path (pf_token SHARED) mutators of radix trees and + * per-entry counters. Ioctl paths hold pf_token EXCLUSIVE and are + * already serialized against the packet path. + */ +static struct spinlock pfr_pktmut_lock = SPINLOCK_INITIALIZER(pfr_pktmut_lock, "pf_table pkt mut"); void pfr_copyout_addr(struct pfr_addr *, struct pfr_kentry *ke); @@ -863,19 +870,27 @@ struct pfr_kentry *p; int rv; + spin_lock(&pfr_pktmut_lock); p = pfr_lookup_addr(kt, ad, 1); - if (p != NULL) + if (p != NULL) { + spin_unlock(&pfr_pktmut_lock); return (0); + } p = pfr_create_kentry(ad, 1); - if (p == NULL) + if (p == NULL) { + spin_unlock(&pfr_pktmut_lock); return (EINVAL); + } rv = pfr_route_kentry(kt, p); - if (rv) + if (rv) { + spin_unlock(&pfr_pktmut_lock); return (rv); + } p->pfrke_tzero = tzero; kt->pfrkt_cnt++; + spin_unlock(&pfr_pktmut_lock); return (0); } @@ -2058,6 +2073,7 @@ kt->pfrkt_bytes[dir_out][op_pass] += len; if (ke != NULL && op_pass != PFR_OP_XPASS && (kt->pfrkt_flags & PFR_TFLAG_COUNTERS)) { + spin_lock(&pfr_pktmut_lock); if (ke->pfrke_counters == NULL) ke->pfrke_counters = kmalloc(sizeof(struct pfr_kcounters), M_PFRKCOUNTERSPL, M_NOWAIT|M_ZERO); @@ -2065,6 +2081,7 @@ ke->pfrke_counters->pfrkc_packets[dir_out][op_pass]++; ke->pfrke_counters->pfrkc_bytes[dir_out][op_pass] += len; } + spin_unlock(&pfr_pktmut_lock); } }