Skip to contentSkip to conversation

bnxt_en: add XDP RSS hash metadata support

PATCH Superseded Chris J Arges 3 participants 8 messages Feb 27 – Feb 28

Subsystems (6)

v1 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

cover bnxt_en: add XDP RSS hash metadata support

This series adds XDP RSS hash metadata extraction support for the bnxt_en driver and includes selftests to validate the functionality. I was able to test this on a BCM57414 NIC.

The driver changes introduce a bnxt_xdp_buff wrapper that carries hardware RX completion descriptors alongside the xdp_buff, then use it to implement bpf_xdp_metadata_rx_hash().

The selftest changes refactor common XDP/BPF helpers into a shared library and add a new xdp_metadata test that verifies RSS hash extraction for TCP and UDP traffic via device-bound XDP programs.

Chris J Arges (4):
bnxt_en: use bnxt_xdp_buff for xdp context
bnxt_en: Implement XDP RSS hash metadata extraction
selftests: net: move common xdp.py functions into lib
selftests: drv-net: xdp: Add rss_hash metadata tests

 drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  30 ++--
 drivers/net/ethernet/broadcom/bnxt/bnxt.h     |   2 +
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c |  47 +++++
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h |  10 ++
 tools/testing/selftests/drivers/net/Makefile  |   1 +
 .../selftests/drivers/net/lib/py/__init__.py  |   2 +
 tools/testing/selftests/drivers/net/xdp.py    |  95 +++-------
 .../selftests/drivers/net/xdp_metadata.py     | 144 ++++++++++++++++
 .../testing/selftests/net/lib/py/__init__.py  |   2 +
 tools/testing/selftests/net/lib/py/bpf.py     |  68 ++++++++
 .../selftests/net/lib/xdp_metadata.bpf.c      | 163 ++++++++++++++++++
 11 files changed, 482 insertions(+), 82 deletions(-)
 create mode 100644 tools/testing/selftests/drivers/net/xdp_metadata.py
 create mode 100644 tools/testing/selftests/net/lib/py/bpf.py
 create mode 100644 tools/testing/selftests/net/lib/xdp_metadata.bpf.c

base-commit: 7dff99b354601dd01829e1511711846e04340a69

Signature · 1 line
2.43.0
#1 lore raw

PATCH 1/4 bnxt_en: use bnxt_xdp_buff for xdp context

This adds bnxt_xdp_buff which embeds the xdp_buff struct and stores pointers to hardware RX completion descriptors (rx_cmp and rx_cmp_ext) along with the completion type.

---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     | 25 +++++++++++--------
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h |  7 ++++++
 2 files changed, 22 insertions(+), 10 deletions(-)
drivers/net/ethernet/broadcom/bnxt/bnxt.c +15 -10
index e062d5d400da..a80ec5391b89 100644
@@ -2118,7 +2118,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
 	bool xdp_active = false;
 	dma_addr_t dma_addr;
 	struct sk_buff *skb;
-	struct xdp_buff xdp;
+	struct bnxt_xdp_buff bnxt_xdp;
 	u32 flags, misc;
 	u32 cmpl_ts;
 	void *data;
@@ -2231,9 +2231,13 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
 	dma_addr = rx_buf->mapping;
 
 	if (bnxt_xdp_attached(bp, rxr)) {
-		bnxt_xdp_buff_init(bp, rxr, cons, data_ptr, len, &xdp);
+		bnxt_xdp.rxcmp = rxcmp;
+		bnxt_xdp.rxcmp1 = rxcmp1;
+		bnxt_xdp.cmp_type = cmp_type;
+
+		bnxt_xdp_buff_init(bp, rxr, cons, data_ptr, len, &bnxt_xdp.xdp);
 		if (agg_bufs) {
-			u32 frag_len = bnxt_rx_agg_netmems_xdp(bp, cpr, &xdp,
+			u32 frag_len = bnxt_rx_agg_netmems_xdp(bp, cpr, &bnxt_xdp.xdp,
 							       cp_cons,
 							       agg_bufs,
 							       false);
@@ -2245,12 +2249,12 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
 	}
 
 	if (xdp_active) {
-		if (bnxt_rx_xdp(bp, rxr, cons, &xdp, data, &data_ptr, &len, event)) {
+		if (bnxt_rx_xdp(bp, rxr, cons, &bnxt_xdp.xdp, data, &data_ptr, &len, event)) {
 			rc = 1;
 			goto next_rx;
 		}
-		if (xdp_buff_has_frags(&xdp)) {
-			sinfo = xdp_get_shared_info_from_buff(&xdp);
+		if (xdp_buff_has_frags(&bnxt_xdp.xdp)) {
+			sinfo = xdp_get_shared_info_from_buff(&bnxt_xdp.xdp);
 			agg_bufs = sinfo->nr_frags;
 		} else {
 			agg_bufs = 0;
@@ -2261,7 +2265,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
 		if (!xdp_active)
 			skb = bnxt_copy_skb(bnapi, data_ptr, len, dma_addr);
 		else
-			skb = bnxt_copy_xdp(bnapi, &xdp, len, dma_addr);
+			skb = bnxt_copy_xdp(bnapi, &bnxt_xdp.xdp, len, dma_addr);
 		bnxt_reuse_rx_data(rxr, cons, data);
 		if (!skb) {
 			if (agg_bufs) {
@@ -2269,7 +2273,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
 					bnxt_reuse_rx_agg_bufs(cpr, cp_cons, 0,
 							       agg_bufs, false);
 				else
-					bnxt_xdp_buff_frags_free(rxr, &xdp);
+					bnxt_xdp_buff_frags_free(rxr, &bnxt_xdp.xdp);
 			}
 			goto oom_next_rx;
 		}
@@ -2293,10 +2297,11 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
 			if (!skb)
 				goto oom_next_rx;
 		} else {
-			skb = bnxt_xdp_build_skb(bp, skb, agg_bufs, rxr, &xdp);
+			skb = bnxt_xdp_build_skb(bp, skb, agg_bufs,
+						 rxr, &bnxt_xdp.xdp);
 			if (!skb) {
 				/* we should be able to free the old skb here */
-				bnxt_xdp_buff_frags_free(rxr, &xdp);
+				bnxt_xdp_buff_frags_free(rxr, &bnxt_xdp.xdp);
 				goto oom_next_rx;
 			}
 		}
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h +7 -0
index 8933a0dec09a..8c66698bde11 100644
@@ -12,6 +12,13 @@
 
 DECLARE_STATIC_KEY_FALSE(bnxt_xdp_locking_key);
 
+struct bnxt_xdp_buff {
+	struct xdp_buff xdp;
+	struct rx_cmp *rxcmp;
+	struct rx_cmp_ext *rxcmp1;
+	u8 cmp_type;
+};
+
 struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp,
 				   struct bnxt_tx_ring_info *txr,
 				   dma_addr_t mapping, u32 len,
Signature · 1 line
2.43.0
#2 lore raw

PATCH 2/4 bnxt_en: Implement XDP RSS hash metadata extraction

In reply to Chris J Arges

Add support for extracting RSS hash values and hash types from hardware completion descriptors in XDP programs for bnxt_en.

Add IP_TYPE definition for determining if completion is ipv4 or ipv6. In addition add ITYPE_ICMP flag for identifying ICMP completions.

---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  5 ++
 drivers/net/ethernet/broadcom/bnxt/bnxt.h     |  2 +
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 47 +++++++++++++++++++
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h |  3 ++
 4 files changed, 57 insertions(+)
drivers/net/ethernet/broadcom/bnxt/bnxt.c +5 -0
index a80ec5391b89..a8ea73c880e9 100644
@@ -15905,6 +15905,10 @@ static const struct net_device_ops bnxt_netdev_ops = {
 	.ndo_hwtstamp_set	= bnxt_hwtstamp_set,
 };
 
+static const struct xdp_metadata_ops bnxt_xdp_metadata_ops = {
+	.xmo_rx_hash		= bnxt_xdp_rx_hash,
+};
+
 static void bnxt_get_queue_stats_rx(struct net_device *dev, int i,
 				    struct netdev_queue_stats_rx *stats)
 {
@@ -16789,6 +16793,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 		goto init_err_free;
 
 	dev->netdev_ops = &bnxt_netdev_ops;
+	dev->xdp_metadata_ops = &bnxt_xdp_metadata_ops;
 	dev->stat_ops = &bnxt_stat_ops;
 	dev->watchdog_timeo = BNXT_TX_TIMEOUT;
 	dev->ethtool_ops = &bnxt_ethtool_ops;
drivers/net/ethernet/broadcom/bnxt/bnxt.h +2 -0
index 9a41b9e0423c..13eb1ca814b7 100644
@@ -232,6 +232,7 @@ struct rx_cmp {
 	 #define RX_CMP_FLAGS_ITYPE_UDP				 (3 << 12)
 	 #define RX_CMP_FLAGS_ITYPE_FCOE			 (4 << 12)
 	 #define RX_CMP_FLAGS_ITYPE_ROCE			 (5 << 12)
+	 #define RX_CMP_FLAGS_ITYPE_ICMP			 (7 << 12)
 	 #define RX_CMP_FLAGS_ITYPE_PTP_WO_TS			 (8 << 12)
 	 #define RX_CMP_FLAGS_ITYPE_PTP_W_TS			 (9 << 12)
 	#define RX_CMP_LEN					(0xffff << 16)
@@ -311,6 +312,7 @@ struct rx_cmp_ext {
 	#define RX_CMP_FLAGS2_T_IP_CS_CALC			(0x1 << 2)
 	#define RX_CMP_FLAGS2_T_L4_CS_CALC			(0x1 << 3)
 	#define RX_CMP_FLAGS2_META_FORMAT_VLAN			(0x1 << 4)
+	#define RX_CMP_FLAGS2_IP_TYPE				(0x1 << 8)
 	__le32 rx_cmp_meta_data;
 	#define RX_CMP_FLAGS2_METADATA_TCI_MASK			0xffff
 	#define RX_CMP_FLAGS2_METADATA_VID_MASK			0xfff
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +47 -0

50 lines not on this page · raw message

drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h +3 -0
index 8c66698bde11..fb4f9143929f 100644
@@ -41,4 +41,7 @@ void bnxt_xdp_buff_frags_free(struct bnxt_rx_ring_info *rxr,
 struct sk_buff *bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb,
 				   u8 num_frags, struct bnxt_rx_ring_info *rxr,
 				   struct xdp_buff *xdp);
+int bnxt_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash,
+		     enum xdp_rss_hash_type *rss_type);
+
 #endif
Signature · 1 line
2.43.0
#4 lore raw

PATCH 3/4 selftests: net: move common xdp.py functions into lib

In reply to Chris J Arges

This moves a few functions which can be useful to other python programs that manipulate XDP programs. This also refactors xdp.py to use the refactored functions.

---
 .../selftests/drivers/net/lib/py/__init__.py  |  2 +
 tools/testing/selftests/drivers/net/xdp.py    | 95 +++++--------------
 .../testing/selftests/net/lib/py/__init__.py  |  2 +
 tools/testing/selftests/net/lib/py/bpf.py     | 68 +++++++++++++
 4 files changed, 95 insertions(+), 72 deletions(-)
 create mode 100644 tools/testing/selftests/net/lib/py/bpf.py
tools/testing/selftests/drivers/net/lib/py/__init__.py +2 -0
index 8b75faa9af6d..29c4913cd434 100644
@@ -23,6 +23,7 @@ try:
     from net.lib.py import CmdExitFailure
     from net.lib.py import bkg, cmd, bpftool, bpftrace, defer, ethtool, \
         fd_read_timeout, ip, rand_port, wait_port_listen, wait_file
+    from net.lib.py import bpf_map_set, bpf_map_dump, bpf_prog_map_ids
     from net.lib.py import KsftSkipEx, KsftFailEx, KsftXfailEx
     from net.lib.py import ksft_disruptive, ksft_exit, ksft_pr, ksft_run, \
         ksft_setup, ksft_variants, KsftNamedVariant
@@ -36,6 +37,7 @@ try:
                "bkg", "cmd", "bpftool", "bpftrace", "defer", "ethtool",
                "fd_read_timeout", "ip", "rand_port",
                "wait_port_listen", "wait_file",
+               "bpf_map_set", "bpf_map_dump", "bpf_prog_map_ids",
                "KsftSkipEx", "KsftFailEx", "KsftXfailEx",
                "ksft_disruptive", "ksft_exit", "ksft_pr", "ksft_run",
                "ksft_setup", "ksft_variants", "KsftNamedVariant",
tools/testing/selftests/drivers/net/xdp.py +23 -72

168 lines not on this page · raw message

tools/testing/selftests/net/lib/py/__init__.py +2 -0
index f528b67639de..c1aa9d0f8dcf 100644
@@ -14,6 +14,7 @@ from .netns import NetNS, NetNSEnter
 from .nsim import NetdevSim, NetdevSimDev
 from .utils import CmdExitFailure, fd_read_timeout, cmd, bkg, defer, \
     bpftool, ip, ethtool, bpftrace, rand_port, wait_port_listen, wait_file, tool
+from .bpf import bpf_map_set, bpf_map_dump, bpf_prog_map_ids
 from .ynl import NlError, YnlFamily, EthtoolFamily, NetdevFamily, RtnlFamily, RtnlAddrFamily
 from .ynl import NetshaperFamily, DevlinkFamily, PSPFamily
 
@@ -27,6 +28,7 @@ __all__ = ["KSRC",
            "CmdExitFailure", "fd_read_timeout", "cmd", "bkg", "defer",
            "bpftool", "ip", "ethtool", "bpftrace", "rand_port",
            "wait_port_listen", "wait_file", "tool",
+           "bpf_map_set", "bpf_map_dump", "bpf_prog_map_ids",
            "NetdevSim", "NetdevSimDev",
            "NetshaperFamily", "DevlinkFamily", "PSPFamily", "NlError",
            "YnlFamily", "EthtoolFamily", "NetdevFamily", "RtnlFamily",
tools/testing/selftests/net/lib/py/bpf.py new file +68 -0

68 lines not on this page · raw message

Signature · 1 line
2.43.0
#6 lore raw

PATCH 4/4 selftests: drv-net: xdp: Add rss_hash metadata tests

In reply to Chris J Arges

This test loads xdp_metadata.bpf which calls bpf_xdp_metadata_rx_hash() on incoming packets. The metadata from that packet is then sent to a BPF map for validation. It borrows structure from xdp.py, reusing common functions.

The test checks the device's xdp-rx-metadata-features via netlink before running and skips on devices that do not advertise hash support. This allows the tests to pass, but one can override the device and test on HW or veth devices.

The test is fairly simple and just verifies that a TCP or UDP packet can be identified as an L4 flow. This minimal test also passes if run on a veth device.

---
 tools/testing/selftests/drivers/net/Makefile  |   1 +
 .../selftests/drivers/net/xdp_metadata.py     | 144 ++++++++++++++++
 .../selftests/net/lib/xdp_metadata.bpf.c      | 163 ++++++++++++++++++
 3 files changed, 308 insertions(+)
 create mode 100644 tools/testing/selftests/drivers/net/xdp_metadata.py
 create mode 100644 tools/testing/selftests/net/lib/xdp_metadata.bpf.c
tools/testing/selftests/drivers/net/Makefile +1 -0
index 8154d6d429d3..6f9708e8d05a 100644
@@ -23,6 +23,7 @@ TEST_PROGS := \
 	shaper.py \
 	stats.py \
 	xdp.py \
+	xdp_metadata.py \
 # end of TEST_PROGS
 
 # YNL files, must be before "include ..lib.mk"
tools/testing/selftests/drivers/net/xdp_metadata.py new file +144 -0

144 lines not on this page · raw message

tools/testing/selftests/net/lib/xdp_metadata.bpf.c new file +163 -0

163 lines not on this page · raw message

Signature · 1 line
2.43.0
Reviewed-by on v1 2/4
#3 lore raw

Re: [PATCH net-next 2/4] bnxt_en: Implement XDP RSS hash metadata extraction

In reply to Chris J Arges
Quoted 13 lines · Chris J Arges

Add support for extracting RSS hash values and hash types from hardware completion descriptors in XDP programs for bnxt_en.

Add IP_TYPE definition for determining if completion is ipv4 or ipv6. In addition add ITYPE_ICMP flag for identifying ICMP completions.

---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c     |  5 ++
 drivers/net/ethernet/broadcom/bnxt/bnxt.h     |  2 +
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 47 +++++++++++++++++++
 drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h |  3 ++
 4 files changed, 57 insertions(+)

[...]

Quoted 7 lines
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +0 -0
index 85cbeb35681c..f75060374163 100644
@@ -472,3 +472,50 @@ bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb, u8 num_frags,
 				  xdp_buff_get_skb_flags(xdp));
 	return skb;

drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb, u8 num_frags, · line 483

Quoted 10 lines
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +9 -0
 }
+
+int bnxt_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash,
+		     enum xdp_rss_hash_type *rss_type)
+{
+	const struct bnxt_xdp_buff *xdp = (void *)ctx;
+	const struct rx_cmp *rxcmp = xdp->rxcmp;
+	const struct rx_cmp_ext *rxcmp1 = xdp->rxcmp1;
+	u32 itypes;
+	enum xdp_rss_hash_type hash_type = 0;

Nit: This may need to be put into RCT style. (?)

Everything else seemed OK to me...

Reviewed-by on v1 3/4
#5 lore raw

Re: [PATCH net-next 3/4] selftests: net: move common xdp.py functions into lib

In reply to Chris J Arges
Quoted 4 lines · Chris J Arges

This moves a few functions which can be useful to other python programs that manipulate XDP programs. This also refactors xdp.py to use the refactored functions.

Quoted 8 lines
---
 .../selftests/drivers/net/lib/py/__init__.py  |  2 +
 tools/testing/selftests/drivers/net/xdp.py    | 95 +++++--------------
 .../testing/selftests/net/lib/py/__init__.py  |  2 +
 tools/testing/selftests/net/lib/py/bpf.py     | 68 +++++++++++++
 4 files changed, 95 insertions(+), 72 deletions(-)
 create mode 100644 tools/testing/selftests/net/lib/py/bpf.py
maintainer
#7 lore raw

Re: [PATCH net-next 4/4] selftests: drv-net: xdp: Add rss_hash metadata tests

In reply to Chris J Arges
Quoted 5 lines · On Fri, 27 Feb 2026 11:40:20 -0600 Chris J Arges wrote:

This test loads xdp_metadata.bpf which calls bpf_xdp_metadata_rx_hash() on incoming packets. The metadata from that packet is then sent to a BPF map for validation. It borrows structure from xdp.py, reusing common functions.

Quoted 8 lines

The test checks the device's xdp-rx-metadata-features via netlink before running and skips on devices that do not advertise hash support. This allows the tests to pass, but one can override the device and test on HW or veth devices.

The test is fairly simple and just verifies that a TCP or UDP packet can be identified as an L4 flow. This minimal test also passes if run on a veth device.

Thanks for adding the test! The series doesn't seem to apply, I think you'll need to rebase on latest net-next and repost.

tools/testing/selftests/drivers/net/Makefile

Quoted 4 lines
tools/testing/selftests/drivers/net/Makefile +0 -0
index 8154d6d429d3..6f9708e8d05a 100644

the drivers/net tests are expected to run against netdevsim. You'll need to implement the xmo in netdevsim.. Or does it already support them given it uses xdp_generic under the hood? Alternatively you can move the test under hw/ and not bother.

tools/testing/selftests/drivers/net/Makefile

Quoted 7 lines
tools/testing/selftests/drivers/net/Makefile +7 -0
+# BPF map keys matching the enums in xdp_metadata.bpf.c
+_SETUP_KEY_PORT = 1
+
+_RSS_KEY_HASH = 0
+_RSS_KEY_TYPE = 1
+_RSS_KEY_PKT_CNT = 2
+_RSS_KEY_ERR_CNT = 3

Does pylint complain about those ? We try to keep pylint --disable=R clean for new tests.

tools/testing/selftests/drivers/net/Makefile

Quoted 2 lines
tools/testing/selftests/drivers/net/Makefile +2 -0
+    ksft_ge(pkt_cnt, 1, "should have received at least one packet")
+    ksft_pr(f"  RSS hash error count: {err_cnt}")

Does it randomly report non-zero?
I'm wondering why not ksft_eq(err_cnt, 0, comment='RSS hash error count')

tools/testing/selftests/drivers/net/Makefile

Quoted 11 lines
tools/testing/selftests/drivers/net/Makefile +11 -0
+    ksft_ne(hash_val, 0,
+            f"RSS hash should be non-zero for {proto.upper()} traffic")
+    ksft_pr(f"  RSS hash: {hash_val:#010x}")
+
+    ksft_pr(f"  RSS hash type: {hash_type:#06x}")
+    XDP_RSS_L4 = 0x8  # BIT(3) from enum xdp_rss_hash_type
+    ksft_ne(hash_type & XDP_RSS_L4, 0,
+            f"RSS hash type should include L4 for {proto.upper()} traffic")
+
+
+def main():

add:

""" Ksft boiler plate main """

to silence pylint?