git: 7267f83272b1 - stable/12 - pf: allow table stats clearing and reading with ruleset rlock

Mateusz Guzik mjg at FreeBSD.org
Wed Jul 14 14:57:57 UTC 2021


The branch stable/12 has been updated by mjg:

URL: https://cgit.FreeBSD.org/src/commit/?id=7267f83272b148f8734c0ced0489ff1022c1f68d

commit 7267f83272b148f8734c0ced0489ff1022c1f68d
Author:     Mateusz Guzik <mjg at FreeBSD.org>
AuthorDate: 2021-07-02 12:55:57 +0000
Commit:     Mateusz Guzik <mjg at FreeBSD.org>
CommitDate: 2021-07-14 14:55:29 +0000

    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")
    
    (cherry picked from commit dc1ab04e4c9ede3606985e0cce1200e3060ac166)
---
 sys/net/pfvar.h           |  7 +++++++
 sys/netpfil/pf/pf.c       |  4 ++++
 sys/netpfil/pf/pf_ioctl.c | 18 ++++++++++++------
 sys/netpfil/pf/pf_table.c |  2 ++
 4 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index a98bdac54529..6c934ad47bf2 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -128,10 +128,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
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index cb616ef5788f..aa7a01d50823 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -212,6 +212,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;
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 0481e58ae1e2..eb9719886bbe 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -3740,10 +3740,12 @@ DIOCCHANGEADDR_error:
 			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;
 		}
@@ -3754,12 +3756,14 @@ DIOCCHANGEADDR_error:
 		    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);
@@ -3798,10 +3802,12 @@ DIOCCHANGEADDR_error:
 			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;
 	}
diff --git a/sys/netpfil/pf/pf_table.c b/sys/netpfil/pf/pf_table.c
index d0b91fff1656..8dbab5e7bbe1 100644
--- a/sys/netpfil/pf/pf_table.c
+++ b/sys/netpfil/pf/pf_table.c
@@ -1865,6 +1865,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);


More information about the dev-commits-src-all mailing list