git: eaba5142bdef - main - pf: carry pfra_fback in the netlink pfr_addr encoding

From: R. Christian McDonald <rcm_at_FreeBSD.org>
Date: Tue, 29 Sep 2026 20:01:26 UTC
The branch main has been updated by rcm:

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

commit eaba5142bdefd6b5b249793f6f8ec3528afb12e3
Author:     R. Christian McDonald <rcm@FreeBSD.org>
AuthorDate: 2026-09-29 01:21:56 +0000
Commit:     R. Christian McDonald <rcm@FreeBSD.org>
CommitDate: 2026-09-29 19:57:47 +0000

    pf: carry pfra_fback in the netlink pfr_addr encoding
    
    The netlink encoding of struct pfr_addr omits pfra_fback, so no
    per-address feedback reaches userspace.  In particular,
    pfr_get_astats() marks entries of tables without counters with
    PFR_FB_NOCOUNT, which pfctl uses to skip their counters, so
    "pfctl -v -T show" prints zero counters for such tables.
    
    Add PFR_A_FBACK, emit it from the kernel and decode it in libpfctl.
    
    Add a regression test.
    
    Reviewed by:    kp
    Approved by:    kp (mentor)
    Fixes:          08f54dfca197 ("pf: convert DIOCRGETASTATS to netlink")
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 lib/libpfctl/libpfctl.c       |  1 +
 sys/netpfil/pf/pf_nl.c        |  1 +
 sys/netpfil/pf/pf_nl.h        |  1 +
 tests/sys/netpfil/pf/table.sh | 33 +++++++++++++++++++++++++++++++++
 4 files changed, 36 insertions(+)

diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index 6578cff5e45a..a7dbc0a412aa 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -2799,6 +2799,7 @@ static const struct snl_attr_parser ap_pfr_addr[] = {
 	{ .type = PFR_A_NET, .off = _OUT(pfra_net), .cb = snl_attr_get_uint8 },
 	{ .type = PFR_A_NOT, .off = _OUT(pfra_not), .cb = snl_attr_get_bool },
 	{ .type = PFR_A_ADDR, .off = _OUT(pfra_ip6addr), .cb = snl_attr_get_in6_addr },
+	{ .type = PFR_A_FBACK, .off = _OUT(pfra_fback), .cb = snl_attr_get_uint8 },
 };
 #undef _OUT
 SNL_DECLARE_ATTR_PARSER(pfr_addr_parser, ap_pfr_addr);
diff --git a/sys/netpfil/pf/pf_nl.c b/sys/netpfil/pf/pf_nl.c
index 8a04c330f4eb..6281b2d0ad19 100644
--- a/sys/netpfil/pf/pf_nl.c
+++ b/sys/netpfil/pf/pf_nl.c
@@ -2315,6 +2315,7 @@ nlattr_add_pfr_addr(struct nl_writer *nw, int attr, const struct pfr_addr *a)
 	nlattr_add_u8(nw, PFR_A_NET, a->pfra_net);
 	nlattr_add_bool(nw, PFR_A_NOT, a->pfra_not);
 	nlattr_add_in6_addr(nw, PFR_A_ADDR, &a->pfra_u._pfra_ip6addr);
+	nlattr_add_u8(nw, PFR_A_FBACK, a->pfra_fback);
 
 	nlattr_set_len(nw, off);
 
diff --git a/sys/netpfil/pf/pf_nl.h b/sys/netpfil/pf/pf_nl.h
index 220ef8ea9cd8..d795d33c085a 100644
--- a/sys/netpfil/pf/pf_nl.h
+++ b/sys/netpfil/pf/pf_nl.h
@@ -498,6 +498,7 @@ enum pfr_addr_t {
 	PFR_A_NET		= 2, /* uint8_t */
 	PFR_A_NOT		= 3, /* bool */
 	PFR_A_ADDR		= 4, /* in6_addr */
+	PFR_A_FBACK		= 5, /* uint8_t */
 };
 
 enum pf_table_addrs_t {
diff --git a/tests/sys/netpfil/pf/table.sh b/tests/sys/netpfil/pf/table.sh
index 7c8cb084b48a..24201588ddbf 100644
--- a/tests/sys/netpfil/pf/table.sh
+++ b/tests/sys/netpfil/pf/table.sh
@@ -949,6 +949,38 @@ test_cleanup()
 	pft_cleanup
 }
 
+atf_test_case "show_no_counters" "cleanup"
+show_no_counters_head()
+{
+	atf_set descr 'Test pfctl -v -T show on a table without counters'
+	atf_set require.user root
+}
+
+show_no_counters_body()
+{
+	pft_init
+
+	vnet_mkjail alcatraz
+	jexec alcatraz pfctl -e
+
+	pft_set_rules alcatraz \
+	    "table <foo> persist { 192.0.2.1 }" \
+	    "table <bar> persist counters { 192.0.2.1 }" \
+	    "pass all"
+
+	atf_check -s exit:0 -e ignore \
+	    -o match:"Cleared:" -o not-match:"In/Block:" \
+	    jexec alcatraz pfctl -t foo -v -T show
+	atf_check -s exit:0 -e ignore \
+	    -o match:"Cleared:" -o match:"In/Block:" \
+	    jexec alcatraz pfctl -t bar -v -T show
+}
+
+show_no_counters_cleanup()
+{
+	pft_cleanup
+}
+
 atf_init_test_cases()
 {
 	atf_add_test_case "v4_counters"
@@ -972,4 +1004,5 @@ atf_init_test_cases()
 	atf_add_test_case "replace_verbose"
 	atf_add_test_case "load"
 	atf_add_test_case "test"
+	atf_add_test_case "show_no_counters"
 }