svn commit: r361095 - in head/sys: net netpfil/pf

Mark Johnston markj at FreeBSD.org
Sat May 16 00:28:13 UTC 2020


Author: markj
Date: Sat May 16 00:28:12 2020
New Revision: 361095
URL: https://svnweb.freebsd.org/changeset/base/361095

Log:
  pf: Add a new zone for per-table entry counters.
  
  Right now we optionally allocate 8 counters per table entry, so in
  addition to memory consumed by counters, we require 8 pointers worth of
  space in each entry even when counters are not allocated (the default).
  
  Instead, define a UMA zone that returns contiguous per-CPU counter
  arrays for use in table entries.  On amd64 this reduces sizeof(struct
  pfr_kentry) from 216 to 160.  The smaller size also results in better
  slab efficiency, so memory usage for large tables is reduced by about
  28%.
  
  Reviewed by:	kp
  MFC after:	2 weeks
  Differential Revision:	https://reviews.freebsd.org/D24843

Modified:
  head/sys/net/pfvar.h
  head/sys/netpfil/pf/pf_table.c

Modified: head/sys/net/pfvar.h
==============================================================================
--- head/sys/net/pfvar.h	Fri May 15 23:44:52 2020	(r361094)
+++ head/sys/net/pfvar.h	Sat May 16 00:28:12 2020	(r361095)
@@ -1000,6 +1000,8 @@ struct pfr_addr {
 
 enum { PFR_DIR_IN, PFR_DIR_OUT, PFR_DIR_MAX };
 enum { PFR_OP_BLOCK, PFR_OP_PASS, PFR_OP_ADDR_MAX, PFR_OP_TABLE_MAX };
+enum { PFR_TYPE_PACKETS, PFR_TYPE_BYTES, PFR_TYPE_MAX };
+#define	PFR_NUM_COUNTERS	(PFR_DIR_MAX * PFR_OP_ADDR_MAX * PFR_TYPE_MAX)
 #define PFR_OP_XPASS	PFR_OP_ADDR_MAX
 
 struct pfr_astats {
@@ -1045,10 +1047,12 @@ union sockaddr_union {
 #endif /* _SOCKADDR_UNION_DEFINED */
 
 struct pfr_kcounters {
-	counter_u64_t		 pfrkc_packets[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
-	counter_u64_t		 pfrkc_bytes[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
+	counter_u64_t		 pfrkc_counters;
 	long			 pfrkc_tzero;
 };
+#define	pfr_kentry_counter(kc, dir, op, t)		\
+	((kc)->pfrkc_counters +				\
+	    (dir) * PFR_OP_ADDR_MAX * PFR_TYPE_MAX + (op) * PFR_TYPE_MAX + (t))
 
 SLIST_HEAD(pfr_kentryworkq, pfr_kentry);
 struct pfr_kentry {

Modified: head/sys/netpfil/pf/pf_table.c
==============================================================================
--- head/sys/netpfil/pf/pf_table.c	Fri May 15 23:44:52 2020	(r361094)
+++ head/sys/netpfil/pf/pf_table.c	Sat May 16 00:28:12 2020	(r361095)
@@ -127,6 +127,8 @@ struct pfr_walktree {
 static MALLOC_DEFINE(M_PFTABLE, "pf_table", "pf(4) tables structures");
 VNET_DEFINE_STATIC(uma_zone_t, pfr_kentry_z);
 #define	V_pfr_kentry_z		VNET(pfr_kentry_z)
+VNET_DEFINE_STATIC(uma_zone_t, pfr_kentry_counter_z);
+#define	V_pfr_kentry_counter_z	VNET(pfr_kentry_counter_z)
 
 static struct pf_addr	 pfr_ffaddr = {
 	.addr32 = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }
@@ -144,12 +146,8 @@ static void		 pfr_mark_addrs(struct pfr_ktable *);
 static struct pfr_kentry
 			*pfr_lookup_addr(struct pfr_ktable *,
 			    struct pfr_addr *, int);
-static bool		 pfr_create_kentry_counter(struct pfr_kentry *, int,
-			    int);
 static struct pfr_kentry *pfr_create_kentry(struct pfr_addr *, bool);
 static void		 pfr_destroy_kentries(struct pfr_kentryworkq *);
-static void		 pfr_destroy_kentry_counter(struct pfr_kcounters *,
-			    int, int);
 static void		 pfr_destroy_kentry(struct pfr_kentry *);
 static void		 pfr_insert_kentries(struct pfr_ktable *,
 			    struct pfr_kentryworkq *, long);
@@ -205,6 +203,9 @@ void
 pfr_initialize(void)
 {
 
+	V_pfr_kentry_counter_z = uma_zcreate("pf table entry counters",
+	    PFR_NUM_COUNTERS * sizeof(uint64_t), NULL, NULL, NULL, NULL,
+	    UMA_ALIGN_PTR, UMA_ZONE_PCPU);
 	V_pfr_kentry_z = uma_zcreate("pf table entries",
 	    sizeof(struct pfr_kentry), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR,
 	    0);
@@ -217,6 +218,7 @@ pfr_cleanup(void)
 {
 
 	uma_zdestroy(V_pfr_kentry_z);
+	uma_zdestroy(V_pfr_kentry_counter_z);
 }
 
 int
@@ -785,27 +787,11 @@ pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr
 	return (ke);
 }
 
-static bool
-pfr_create_kentry_counter(struct pfr_kentry *ke, int pfr_dir, int pfr_op)
-{
-	counter_u64_t c;
-
-	c = counter_u64_alloc(M_NOWAIT);
-	if (c == NULL)
-		return (false);
-	ke->pfrke_counters.pfrkc_packets[pfr_dir][pfr_op] = c;
-	c = counter_u64_alloc(M_NOWAIT);
-	if (c == NULL)
-		return (false);
-	ke->pfrke_counters.pfrkc_bytes[pfr_dir][pfr_op] = c;
-	return (true);
-}
-
 static struct pfr_kentry *
 pfr_create_kentry(struct pfr_addr *ad, bool counters)
 {
 	struct pfr_kentry	*ke;
-	int pfr_dir, pfr_op;
+	counter_u64_t		 c;
 
 	ke = uma_zalloc(V_pfr_kentry_z, M_NOWAIT | M_ZERO);
 	if (ke == NULL)
@@ -819,15 +805,14 @@ pfr_create_kentry(struct pfr_addr *ad, bool counters)
 	ke->pfrke_net = ad->pfra_net;
 	ke->pfrke_not = ad->pfra_not;
 	ke->pfrke_counters.pfrkc_tzero = 0;
-	if (counters)
-		for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir++)
-			for (pfr_op = 0; pfr_op < PFR_OP_ADDR_MAX; pfr_op++) {
-				if (!pfr_create_kentry_counter(ke, pfr_dir,
-				    pfr_op)) {
-					pfr_destroy_kentry(ke);
-					return (NULL);
-				}
-			}
+	if (counters) {
+		c = uma_zalloc_pcpu(V_pfr_kentry_counter_z, M_NOWAIT | M_ZERO);
+		if (c == NULL) {
+			pfr_destroy_kentry(ke);
+			return (NULL);
+		}
+		ke->pfrke_counters.pfrkc_counters = c;
+	}
 	return (ke);
 }
 
@@ -843,26 +828,12 @@ pfr_destroy_kentries(struct pfr_kentryworkq *workq)
 }
 
 static void
-pfr_destroy_kentry_counter(struct pfr_kcounters *kc, int pfr_dir, int pfr_op)
+pfr_destroy_kentry(struct pfr_kentry *ke)
 {
 	counter_u64_t c;
 
-	if ((c = kc->pfrkc_packets[pfr_dir][pfr_op]) != NULL)
-		counter_u64_free(c);
-	if ((c = kc->pfrkc_bytes[pfr_dir][pfr_op]) != NULL)
-		counter_u64_free(c);
-}
-
-static void
-pfr_destroy_kentry(struct pfr_kentry *ke)
-{
-	int pfr_dir, pfr_op;
-
-	for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir ++)
-		for (pfr_op = 0; pfr_op < PFR_OP_ADDR_MAX; pfr_op ++)
-			pfr_destroy_kentry_counter(&ke->pfrke_counters,
-			    pfr_dir, pfr_op);
-
+	if ((c = ke->pfrke_counters.pfrkc_counters) != NULL)
+		uma_zfree_pcpu(V_pfr_kentry_counter_z, c);
 	uma_zfree(V_pfr_kentry_z, ke);
 }
 
@@ -935,28 +906,19 @@ pfr_clean_node_mask(struct pfr_ktable *kt,
 }
 
 static void
-pfr_clear_kentry_counters(struct pfr_kentry *p, int pfr_dir, int pfr_op)
-{
-	counter_u64_zero(p->pfrke_counters.pfrkc_packets[pfr_dir][pfr_op]);
-	counter_u64_zero(p->pfrke_counters.pfrkc_bytes[pfr_dir][pfr_op]);
-}
-
-static void
 pfr_clstats_kentries(struct pfr_ktable *kt, struct pfr_kentryworkq *workq,
     long tzero, int negchange)
 {
 	struct pfr_kentry	*p;
-	int			pfr_dir, pfr_op;
+	int			 i;
 
 	SLIST_FOREACH(p, workq, pfrke_workq) {
 		if (negchange)
 			p->pfrke_not = !p->pfrke_not;
 		if ((kt->pfrkt_flags & PFR_TFLAG_COUNTERS) != 0)
-			for (pfr_dir = 0; pfr_dir < PFR_DIR_MAX; pfr_dir++)
-				for (pfr_op = 0; pfr_op < PFR_OP_ADDR_MAX;
-				    pfr_op++)
-					pfr_clear_kentry_counters(p, pfr_dir,
-					    pfr_op);
+			for (i = 0; i < PFR_NUM_COUNTERS; i++)
+				counter_u64_zero(
+				    p->pfrke_counters.pfrkc_counters + i);
 		p->pfrke_counters.pfrkc_tzero = tzero;
 	}
 }
@@ -1077,12 +1039,12 @@ pfr_copyout_astats(struct pfr_astats *as, const struct
 		return;
 	}
 
-	for (dir = 0; dir < PFR_DIR_MAX; dir ++) {
+	for (dir = 0; dir < PFR_DIR_MAX; dir++) {
 		for (op = 0; op < PFR_OP_ADDR_MAX; op ++) {
-			as->pfras_packets[dir][op] =
-			    counter_u64_fetch(kc->pfrkc_packets[dir][op]);
-			as->pfras_bytes[dir][op] =
-			    counter_u64_fetch(kc->pfrkc_bytes[dir][op]);
+			as->pfras_packets[dir][op] = counter_u64_fetch(
+			    pfr_kentry_counter(kc, dir, op, PFR_TYPE_PACKETS));
+			as->pfras_bytes[dir][op] = counter_u64_fetch(
+			    pfr_kentry_counter(kc, dir, op, PFR_TYPE_BYTES));
 		}
 	}
 }
@@ -2147,10 +2109,10 @@ pfr_update_stats(struct pfr_ktable *kt, struct pf_addr
 	counter_u64_add(kt->pfrkt_bytes[dir_out][op_pass], len);
 	if (ke != NULL && op_pass != PFR_OP_XPASS &&
 	    (kt->pfrkt_flags & PFR_TFLAG_COUNTERS)) {
-		counter_u64_add(ke->pfrke_counters.
-		    pfrkc_packets[dir_out][op_pass], 1);
-		counter_u64_add(ke->pfrke_counters.
-		    pfrkc_bytes[dir_out][op_pass], len);
+		counter_u64_add(pfr_kentry_counter(&ke->pfrke_counters,
+		    dir_out, op_pass, PFR_TYPE_PACKETS), 1);
+		counter_u64_add(pfr_kentry_counter(&ke->pfrke_counters,
+		    dir_out, op_pass, PFR_TYPE_BYTES), len);
 	}
 }
 


More information about the svn-src-all mailing list