[PATCH] net/hns3: fix L4 checksum incorrect for tunnel packets

Xingui Yang yangxingui at huawei.com
Sat May 9 08:36:56 CEST 2026


In HIP09 simple BD mode, the driver incorrectly calculates L4_START
position for tunnel packets. The current implementation only uses
l2_len + l3_len without considering outer header lengths (outer_l2_len
and outer_l3_len), causing hardware to calculate checksum from wrong
offset.

For a typical NvGRE tunnel packet with structure:
  Outer Eth(14) + Outer IPv6(40) + NvGRE(8) + Inner Eth(14) +
  Inner IPv6(40) + TCP(20)

Expected L4_START: 116 bytes (from packet start to inner TCP header)
Actual calculation: 62 bytes (missing outer headers)

This results in incorrect TCP/UDP checksum for all tunnel packets when
using simple BD mode, including NvGRE, VxLAN, GRE, GENEVE tunnels.

Fix by adding outer_l2_len and outer_l3_len to L4_START calculation
when RTE_MBUF_F_TX_TUNNEL_MASK flag is set.

Fixes: 6393fc0b823 ("net/hns3: simplify hardware checksum offloading")
Cc: stable at dpdk.org

Signed-off-by: Xingui Yang <yangxingui at huawei.com>
---
 drivers/net/hns3/hns3_rxtx.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c
index 573604b0cd..4d48cbdc11 100644
--- a/drivers/net/hns3/hns3_rxtx.c
+++ b/drivers/net/hns3/hns3_rxtx.c
@@ -3982,6 +3982,7 @@ hns3_handle_simple_bd(struct hns3_tx_queue *txq, struct hns3_desc *desc,
 {
 #define HNS3_TCP_CSUM_OFFSET	16
 #define HNS3_UDP_CSUM_OFFSET	6
+	uint32_t l4_start;
 
 	/*
 	 * In HIP09, NIC HW support Tx simple BD mode that the HW will
@@ -4003,9 +4004,13 @@ hns3_handle_simple_bd(struct hns3_tx_queue *txq, struct hns3_desc *desc,
 	    ((m->ol_flags & RTE_MBUF_F_TX_L4_MASK) == RTE_MBUF_F_TX_TCP_CKSUM ||
 	     (m->ol_flags & RTE_MBUF_F_TX_L4_MASK) == RTE_MBUF_F_TX_UDP_CKSUM)) {
 		/* set checksum start and offset, defined in 2 Bytes */
+		l4_start = m->l2_len + m->l3_len;
+		if (m->ol_flags & RTE_MBUF_F_TX_TUNNEL_MASK)
+			l4_start += m->outer_l2_len + m->outer_l3_len;
+
 		hns3_set_field(desc->tx.type_cs_vlan_tso_len,
 			       HNS3_TXD_L4_START_M, HNS3_TXD_L4_START_S,
-			       (m->l2_len + m->l3_len) >> HNS3_SIMPLE_BD_UNIT);
+			       l4_start >> HNS3_SIMPLE_BD_UNIT);
 		hns3_set_field(desc->tx.ol_type_vlan_len_msec,
 			   HNS3_TXD_L4_CKS_OFFSET_M, HNS3_TXD_L4_CKS_OFFSET_S,
 			   (m->ol_flags & RTE_MBUF_F_TX_L4_MASK) ==
-- 
2.33.0



More information about the dev mailing list