pf: allow table stats clearing and reading with ruleset rlock

Instead serialize against these operations with a dedicated lock.

Prior to the change, When pushing 17 mln pps of traffic, calling
DIOCRGETTSTATS in a loop would restrict throughput to about 7 mln.  With
the change there is no slowdown.

Reviewed by:	kp (previous version)
Sponsored by:	Rubicon Communications, LLC ("Netgate")
This commit is contained in:
Mateusz Guzik
2021-07-02 14:55:57 +02:00
parent f92c21a28c
commit dc1ab04e4c
4 changed files with 25 additions and 6 deletions
+7
View File
@@ -131,10 +131,17 @@ extern struct rmlock pf_rules_lock;
#define PF_RULES_RUNLOCK() rm_runlock(&pf_rules_lock, &_pf_rules_tracker)
#define PF_RULES_WLOCK() rm_wlock(&pf_rules_lock)
#define PF_RULES_WUNLOCK() rm_wunlock(&pf_rules_lock)
#define PF_RULES_WOWNED() rm_wowned(&pf_rules_lock)
#define PF_RULES_ASSERT() rm_assert(&pf_rules_lock, RA_LOCKED)
#define PF_RULES_RASSERT() rm_assert(&pf_rules_lock, RA_RLOCKED)
#define PF_RULES_WASSERT() rm_assert(&pf_rules_lock, RA_WLOCKED)
extern struct mtx pf_table_stats_lock;
#define PF_TABLE_STATS_LOCK() mtx_lock(&pf_table_stats_lock)
#define PF_TABLE_STATS_UNLOCK() mtx_unlock(&pf_table_stats_lock)
#define PF_TABLE_STATS_OWNED() mtx_owned(&pf_table_stats_lock)
#define PF_TABLE_STATS_ASSERT() mtx_assert(&pf_rules_lock, MA_OWNED)
extern struct sx pf_end_lock;
#define PF_MODVER 1
+4
View File
@@ -211,6 +211,10 @@ struct mtx pf_unlnkdrules_mtx;
MTX_SYSINIT(pf_unlnkdrules_mtx, &pf_unlnkdrules_mtx, "pf unlinked rules",
MTX_DEF);
struct mtx pf_table_stats_lock;
MTX_SYSINIT(pf_table_stats_lock, &pf_table_stats_lock, "pf table stats",
MTX_DEF);
VNET_DEFINE_STATIC(uma_zone_t, pf_sources_z);
#define V_pf_sources_z VNET(pf_sources_z)
uma_zone_t pf_mtag_z;
+12 -6
View File
@@ -3725,10 +3725,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
error = ENODEV;
break;
}
PF_RULES_WLOCK();
PF_TABLE_STATS_LOCK();
PF_RULES_RLOCK();
n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
if (n < 0) {
PF_RULES_WUNLOCK();
PF_RULES_RUNLOCK();
PF_TABLE_STATS_UNLOCK();
error = EINVAL;
break;
}
@@ -3739,12 +3741,14 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
sizeof(struct pfr_tstats), M_TEMP, M_NOWAIT);
if (pfrtstats == NULL) {
error = ENOMEM;
PF_RULES_WUNLOCK();
PF_RULES_RUNLOCK();
PF_TABLE_STATS_UNLOCK();
break;
}
error = pfr_get_tstats(&io->pfrio_table, pfrtstats,
&io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
PF_RULES_WUNLOCK();
PF_RULES_RUNLOCK();
PF_TABLE_STATS_UNLOCK();
if (error == 0)
error = copyout(pfrtstats, io->pfrio_buffer, totlen);
free(pfrtstats, M_TEMP);
@@ -3779,10 +3783,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
break;
}
PF_RULES_WLOCK();
PF_TABLE_STATS_LOCK();
PF_RULES_RLOCK();
error = pfr_clr_tstats(pfrts, io->pfrio_size,
&io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL);
PF_RULES_WUNLOCK();
PF_RULES_RUNLOCK();
PF_TABLE_STATS_UNLOCK();
free(pfrts, M_TEMP);
break;
}
+2
View File
@@ -1864,6 +1864,8 @@ pfr_clstats_ktable(struct pfr_ktable *kt, long tzero, int recurse)
struct pfr_kentryworkq addrq;
int pfr_dir, pfr_op;
MPASS(PF_TABLE_STATS_OWNED() || PF_RULES_WOWNED());
if (recurse) {
pfr_enqueue_addrs(kt, &addrq, NULL, 0);
pfr_clstats_kentries(kt, &addrq, tzero, 0);