git: ab2c8a52a3a9 - stable/12 - pf: deal with tables gaining or losing counters
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 19 Feb 2022 14:22:34 UTC
The branch stable/12 has been updated by kp:
URL: https://cgit.FreeBSD.org/src/commit/?id=ab2c8a52a3a983e48cdd3f31191e577fbf571535
commit ab2c8a52a3a983e48cdd3f31191e577fbf571535
Author: Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2022-02-01 17:25:57 +0000
Commit: Kristof Provost <kp@FreeBSD.org>
CommitDate: 2022-02-19 08:43:33 +0000
pf: deal with tables gaining or losing counters
When we create a table without counters, add an entry and later
re-define the table to have counters we wound up trying to read
non-existent counters.
We now cope with this by attempting to add them if needed, removing them
when they're no longer needed and not trying to read from counters that
are not present.
MFC after: 2 weeks
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D34131
(cherry picked from commit b21826bf15f7ec1e206fa3cfdf40691f84fb1d8e)
---
sys/netpfil/pf/pf_table.c | 36 ++++++++++++++++++++++++++++++++++--
1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/sys/netpfil/pf/pf_table.c b/sys/netpfil/pf/pf_table.c
index af7e36c91c08..0012d0f864c4 100644
--- a/sys/netpfil/pf/pf_table.c
+++ b/sys/netpfil/pf/pf_table.c
@@ -103,7 +103,8 @@ struct pfr_walktree {
PFRW_GET_ADDRS,
PFRW_GET_ASTATS,
PFRW_POOL_GET,
- PFRW_DYNADDR_UPDATE
+ PFRW_DYNADDR_UPDATE,
+ PFRW_COUNTERS
} pfrw_op;
union {
struct pfr_addr *pfrw1_addr;
@@ -1033,7 +1034,8 @@ pfr_copyout_astats(struct pfr_astats *as, const struct pfr_kentry *ke,
pfr_copyout_addr(&as->pfras_a, ke);
as->pfras_tzero = kc->pfrkc_tzero;
- if (! (w->pfrw_flags & PFR_TFLAG_COUNTERS)) {
+ if (! (w->pfrw_flags & PFR_TFLAG_COUNTERS) ||
+ kc->pfrkc_counters == NULL) {
bzero(as->pfras_packets, sizeof(as->pfras_packets));
bzero(as->pfras_bytes, sizeof(as->pfras_bytes));
as->pfras_a.pfra_fback = PFR_FB_NOCOUNT;
@@ -1115,6 +1117,21 @@ pfr_walktree(struct radix_node *rn, void *arg)
}
break;
}
+ case PFRW_COUNTERS:
+ {
+ if (w->pfrw_flags & PFR_TFLAG_COUNTERS) {
+ if (ke->pfrke_counters.pfrkc_counters != NULL)
+ break;
+ ke->pfrke_counters.pfrkc_counters =
+ uma_zalloc_pcpu(V_pfr_kentry_counter_z,
+ M_NOWAIT | M_ZERO);
+ } else {
+ uma_zfree_pcpu(V_pfr_kentry_counter_z,
+ ke->pfrke_counters.pfrkc_counters);
+ ke->pfrke_counters.pfrkc_counters = NULL;
+ }
+ break;
+ }
}
return (0);
}
@@ -1819,6 +1836,7 @@ static void
pfr_setflags_ktable(struct pfr_ktable *kt, int newf)
{
struct pfr_kentryworkq addrq;
+ struct pfr_walktree w;
PF_RULES_WASSERT();
@@ -1839,6 +1857,20 @@ pfr_setflags_ktable(struct pfr_ktable *kt, int newf)
V_pfr_ktable_cnt--;
return;
}
+ if (newf & PFR_TFLAG_COUNTERS && ! (kt->pfrkt_flags & PFR_TFLAG_COUNTERS)) {
+ bzero(&w, sizeof(w));
+ w.pfrw_op = PFRW_COUNTERS;
+ w.pfrw_flags |= PFR_TFLAG_COUNTERS;
+ kt->pfrkt_ip4->rnh_walktree(&kt->pfrkt_ip4->rh, pfr_walktree, &w);
+ kt->pfrkt_ip6->rnh_walktree(&kt->pfrkt_ip6->rh, pfr_walktree, &w);
+ }
+ if (! (newf & PFR_TFLAG_COUNTERS) && (kt->pfrkt_flags & PFR_TFLAG_COUNTERS)) {
+ bzero(&w, sizeof(w));
+ w.pfrw_op = PFRW_COUNTERS;
+ w.pfrw_flags |= 0;
+ kt->pfrkt_ip4->rnh_walktree(&kt->pfrkt_ip4->rh, pfr_walktree, &w);
+ kt->pfrkt_ip6->rnh_walktree(&kt->pfrkt_ip6->rh, pfr_walktree, &w);
+ }
if (!(newf & PFR_TFLAG_ACTIVE) && kt->pfrkt_cnt) {
pfr_enqueue_addrs(kt, &addrq, NULL, 0);
pfr_remove_kentries(kt, &addrq);