git: 30087aa2e00a - main - pf: Support clearing ether counters

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Wed, 02 Mar 2022 16:00:52 UTC
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=30087aa2e00ac8ba7cc487ddc9fccfdd2cd330ea

commit 30087aa2e00ac8ba7cc487ddc9fccfdd2cd330ea
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2021-02-17 16:24:05 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2022-03-02 16:00:05 +0000

    pf: Support clearing ether counters
    
    Allow the evaluations/packets/bytes counters on Ethernet rules to be
    cleared.
    
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D31748
---
 sbin/pfctl/pfctl.c        | 16 +++++++++-------
 sys/netpfil/pf/pf_ioctl.c | 14 ++++++++++++++
 2 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index 83b3c1db0613..f825ef834ac4 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -98,7 +98,7 @@ int	 pfctl_get_pool(int, struct pfctl_pool *, u_int32_t, u_int32_t, int,
 	    char *);
 void	 pfctl_print_eth_rule_counters(struct pfctl_eth_rule *, int);
 void	 pfctl_print_rule_counters(struct pfctl_rule *, int);
-int	 pfctl_show_eth_rules(int, int);
+int	 pfctl_show_eth_rules(int, int, enum pfctl_show);
 int	 pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int);
 int	 pfctl_show_nat(int, int, char *);
 int	 pfctl_show_src_nodes(int, int);
@@ -1052,7 +1052,7 @@ pfctl_print_title(char *title)
 }
 
 int
-pfctl_show_eth_rules(int dev, int opts)
+pfctl_show_eth_rules(int dev, int opts, enum pfctl_show format)
 {
 	struct pfctl_eth_rules_info info;
 	struct pfctl_eth_rule rule;
@@ -1063,8 +1063,8 @@ pfctl_show_eth_rules(int dev, int opts)
 		return (-1);
 	}
 	for (int nr = 0; nr < info.nr; nr++) {
-		if (pfctl_get_eth_rule(dev, nr, info.ticket, &rule, false)
-		    != 0) {
+		if (pfctl_get_eth_rule(dev, nr, info.ticket, &rule,
+		    opts & PF_OPT_CLRRULECTRS) != 0) {
 			warn("DIOCGETETHRULE");
 			return (-1);
 		}
@@ -2640,13 +2640,13 @@ main(int argc, char *argv[])
 			pfctl_show_limits(dev, opts);
 			break;
 		case 'e':
-			pfctl_show_eth_rules(dev, opts);
+			pfctl_show_eth_rules(dev, opts, 0);
 			break;
 		case 'a':
 			opts |= PF_OPT_SHOWALL;
 			pfctl_load_fingerprints(dev, opts);
 
-			pfctl_show_eth_rules(dev, opts);
+			pfctl_show_eth_rules(dev, opts, 0);
 
 			pfctl_show_nat(dev, opts, anchorname);
 			pfctl_show_rules(dev, path, opts, 0, anchorname, 0);
@@ -2673,9 +2673,11 @@ main(int argc, char *argv[])
 		}
 	}
 
-	if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL)
+	if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL) {
+		pfctl_show_eth_rules(dev, opts, PFCTL_SHOW_NOTHING);
 		pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING,
 		    anchorname, 0);
+	}
 
 	if (clearopt != NULL) {
 		if (anchorname[0] == '_' || strstr(anchorname, "/_") != NULL)
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index b116d6e91a7b..7e14d0cf405c 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -2555,6 +2555,7 @@ DIOCGETETHRULES_error:
 		void			*nvlpacked = NULL;
 		struct pf_keth_rule	*rule = NULL;
 		u_int32_t		 ticket, nr;
+		bool			 clear = false;
 
 #define ERROUT(x)	do { error = (x); goto DIOCGETETHRULE_error; } while (0)
 
@@ -2571,6 +2572,12 @@ DIOCGETETHRULES_error:
 			ERROUT(EBADMSG);
 		ticket = nvlist_get_number(nvl, "ticket");
 
+		if (nvlist_exists_bool(nvl, "clear"))
+			clear = nvlist_get_bool(nvl, "clear");
+
+		if (clear && !(flags & FWRITE))
+			ERROUT(EACCES);
+
 		if (! nvlist_exists_number(nvl, "nr"))
 			ERROUT(EBADMSG);
 		nr = nvlist_get_number(nvl, "nr");
@@ -2612,6 +2619,13 @@ DIOCGETETHRULES_error:
 			ERROUT(ENOSPC);
 
 		error = copyout(nvlpacked, nv->data, nv->len);
+		if (error == 0 && clear) {
+			counter_u64_zero(rule->evaluations);
+			for (int i = 0; i < 2; i++) {
+				counter_u64_zero(rule->packets[i]);
+				counter_u64_zero(rule->bytes[i]);
+			}
+		}
 
 #undef ERROUT
 DIOCGETETHRULE_error: