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
This commit is contained in:
parent
610b97ebaa
commit
b21826bf15
@ -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;
|
||||
@ -1032,7 +1033,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;
|
||||
@ -1114,6 +1116,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);
|
||||
}
|
||||
@ -1818,6 +1835,7 @@ static void
|
||||
pfr_setflags_ktable(struct pfr_ktable *kt, int newf)
|
||||
{
|
||||
struct pfr_kentryworkq addrq;
|
||||
struct pfr_walktree w;
|
||||
|
||||
PF_RULES_WASSERT();
|
||||
|
||||
@ -1838,6 +1856,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);
|
||||
|
Loading…
Reference in New Issue
Block a user