[v1] net/ixgbe: fix UDP zero checksum error for Arm NEON path

Message ID 20210208090704.1856110-1-feifei.wang2@arm.com (mailing list archive)
State Accepted, archived
Delegated to: Qi Zhang
Headers
Series [v1] net/ixgbe: fix UDP zero checksum error for Arm NEON path |

Checks

Context Check Description
ci/Intel-compilation success Compilation OK
ci/iol-broadcom-Performance success Performance Testing PASS
ci/intel-Testing success Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-testing fail Testing issues
ci/travis-robot warning Travis build: failed
ci/checkpatch success coding style OK

Commit Message

Feifei Wang Feb. 8, 2021, 9:07 a.m. UTC
  There is an 82599 errata that UDP frames with a zero checksum are
incorrectly marked as checksum invalid by the hardware.  This was
leading to misleading PKT_RX_L4_CKSUM_BAD flag.

To fix it for the NEON path in Arm platform, change the bad UDP checksum to
unknown, and then let software application to recompute the checksum.

This patch depends on:
http://patches.dpdk.org/patch/87750/

NICs: 82599(igb)
Driver: ixgbe(vector)
Architecture: arm64
$:./app/dpdk-testpmd -c 0x3 -w 0002:f9:00.0 -- -i
--port-topology=chained --enable-rx-cksum
test-pmd> set fwd rxonly
test-pmd> set verbose 1
test-pmd> start

1. UDP Test:
Package: (Ether()/IP()/UDP(checksum=0)
ol_flags: PKT_RX_L4_CKSUM_UNKNOWN PKT_RX_IP_CKSUM_GOOD

2. TCP Test:
Package: (Ether()/IP()/TCP(checksum=0)
ol_flags: PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_GOOD

Bugzilla ID: 629
Fixes: af75078fece3 ("first public release")
Cc: stable@dpdk.org

Reported-by: Paolo Valerio <pvalerio@redhat.com>
Signed-off-by: Feifei Wang <feifei.wang2@arm.com>
Reviewed-by: Ruifeng Wang <ruifeng.wang@arm.com>
---
 drivers/net/ixgbe/ixgbe_rxtx_vec_neon.c | 46 +++++++++++++++++++++++--
 1 file changed, 43 insertions(+), 3 deletions(-)
  

Comments

Thomas Monjalon Feb. 10, 2021, 8:46 p.m. UTC | #1
08/02/2021 10:07, Feifei Wang:
> There is an 82599 errata that UDP frames with a zero checksum are
> incorrectly marked as checksum invalid by the hardware.  This was
> leading to misleading PKT_RX_L4_CKSUM_BAD flag.
> 
> To fix it for the NEON path in Arm platform, change the bad UDP checksum to
> unknown, and then let software application to recompute the checksum.
> 
> This patch depends on:
> http://patches.dpdk.org/patch/87750/
> 
> NICs: 82599(igb)
> Driver: ixgbe(vector)
> Architecture: arm64
> $:./app/dpdk-testpmd -c 0x3 -w 0002:f9:00.0 -- -i
> --port-topology=chained --enable-rx-cksum
> test-pmd> set fwd rxonly
> test-pmd> set verbose 1
> test-pmd> start
> 
> 1. UDP Test:
> Package: (Ether()/IP()/UDP(checksum=0)
> ol_flags: PKT_RX_L4_CKSUM_UNKNOWN PKT_RX_IP_CKSUM_GOOD
> 
> 2. TCP Test:
> Package: (Ether()/IP()/TCP(checksum=0)
> ol_flags: PKT_RX_L4_CKSUM_BAD PKT_RX_IP_CKSUM_GOOD
> 
> Bugzilla ID: 629
> Fixes: af75078fece3 ("first public release")
> Cc: stable@dpdk.org
> 
> Reported-by: Paolo Valerio <pvalerio@redhat.com>
> Signed-off-by: Feifei Wang <feifei.wang2@arm.com>
> Reviewed-by: Ruifeng Wang <ruifeng.wang@arm.com>

I wonder why the patch for SSE Rx is applied in next-net-intel
while this one for NEON Rx is ignored.
Either I merge both or none.
I'll go with both.

Applied, thanks.
  

Patch

diff --git a/drivers/net/ixgbe/ixgbe_rxtx_vec_neon.c b/drivers/net/ixgbe/ixgbe_rxtx_vec_neon.c
index f83b800ad..c541f537c 100644
--- a/drivers/net/ixgbe/ixgbe_rxtx_vec_neon.c
+++ b/drivers/net/ixgbe/ixgbe_rxtx_vec_neon.c
@@ -83,9 +83,12 @@  ixgbe_rxq_rearm(struct ixgbe_rx_queue *rxq)
 
 static inline void
 desc_to_olflags_v(uint8x16x2_t sterr_tmp1, uint8x16x2_t sterr_tmp2,
-		  uint8x16_t staterr, uint8_t vlan_flags, struct rte_mbuf **rx_pkts)
+		  uint8x16_t staterr, uint8_t vlan_flags, uint16_t udp_p_flag,
+		  struct rte_mbuf **rx_pkts)
 {
-	uint8x16_t ptype;
+	uint16_t udp_p_flag_hi;
+	uint8x16_t ptype, udp_csum_skip;
+	uint32x4_t temp_udp_csum_skip = {0, 0, 0, 0};
 	uint8x16_t vtag_lo, vtag_hi, vtag;
 	uint8x16_t temp_csum;
 	uint32x4_t csum = {0, 0, 0, 0};
@@ -139,7 +142,31 @@  desc_to_olflags_v(uint8x16x2_t sterr_tmp1, uint8x16x2_t sterr_tmp2,
 			PKT_RX_L4_CKSUM_GOOD >> sizeof(uint8_t), 0,
 			0, 0, 0, 0};
 
+	/* change mask from 0x200(IXGBE_RXDADV_PKTTYPE_UDP) to 0x2 */
+	udp_p_flag_hi = udp_p_flag >> 8;
+
+	/* mask everything except UDP header present if specified */
+	const uint8x16_t udp_hdr_p_msk = {
+			0, 0, 0, 0,
+			udp_p_flag_hi, udp_p_flag_hi, udp_p_flag_hi, udp_p_flag_hi,
+			0, 0, 0, 0,
+			0, 0, 0, 0};
+
+	const uint8x16_t udp_csum_bad_shuf = {
+			0xFF, ~(uint8_t)PKT_RX_L4_CKSUM_BAD, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0,
+			0, 0, 0, 0};
+
 	ptype = vzipq_u8(sterr_tmp1.val[0], sterr_tmp2.val[0]).val[0];
+
+	/* save the UDP header present information */
+	udp_csum_skip = vandq_u8(ptype, udp_hdr_p_msk);
+
+	/* move UDP header present information to low 32bits */
+	temp_udp_csum_skip = vcopyq_laneq_u32(temp_udp_csum_skip, 0,
+				vreinterpretq_u32_u8(udp_csum_skip), 1);
+
 	ptype = vandq_u8(ptype, rsstype_msk);
 	ptype = vqtbl1q_u8(rss_flags, ptype);
 
@@ -166,6 +193,15 @@  desc_to_olflags_v(uint8x16x2_t sterr_tmp1, uint8x16x2_t sterr_tmp2,
 	vtag_lo = vqtbl1q_u8(vlan_csum_map_lo, vtag);
 	vtag_lo = vorrq_u8(ptype, vtag_lo);
 
+	/* convert the UDP header present 0x2 to 0x1 for aligning with each
+	 * PKT_RX_L4_CKSUM_BAD value in low byte of 8 bits word ol_flag in
+	 * vtag_lo (4x8). Then mask out the bad checksum value by shuffle and
+	 * bit-mask.
+	 */
+	udp_csum_skip = vshrq_n_u8(vreinterpretq_u8_u32(temp_udp_csum_skip), 1);
+	udp_csum_skip = vqtbl1q_u8(udp_csum_bad_shuf, udp_csum_skip);
+	vtag_lo = vandq_u8(vtag_lo, udp_csum_skip);
+
 	vtag = vzipq_u8(vtag_lo, vtag_hi).val[0];
 	vol.word = vgetq_lane_u64(vreinterpretq_u64_u8(vtag), 0);
 
@@ -267,6 +303,7 @@  _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 	uint16x8_t crc_adjust = {0, 0, rxq->crc_len, 0,
 				 rxq->crc_len, 0, 0, 0};
 	uint8_t vlan_flags;
+	uint16_t udp_p_flag = 0; /* Rx Descriptor UDP header present */
 
 	/* nb_pkts has to be floor-aligned to RTE_IXGBE_DESCS_PER_LOOP */
 	nb_pkts = RTE_ALIGN_FLOOR(nb_pkts, RTE_IXGBE_DESCS_PER_LOOP);
@@ -291,6 +328,9 @@  _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 				rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD)))
 		return 0;
 
+	if (rxq->rx_udp_csum_zero_err)
+		udp_p_flag = IXGBE_RXDADV_PKTTYPE_UDP;
+
 	/* Cache is empty -> need to scan the buffer rings, but first move
 	 * the next 'n' mbufs into the cache
 	 */
@@ -362,7 +402,7 @@  _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 
 		/* set ol_flags with vlan packet type */
 		desc_to_olflags_v(sterr_tmp1, sterr_tmp2, staterr, vlan_flags,
-				  &rx_pkts[pos]);
+				  udp_p_flag, &rx_pkts[pos]);
 
 		/* D.2 pkt 3,4 set in_port/nb_seg and remove crc */
 		tmp = vsubq_u16(vreinterpretq_u16_u8(pkt_mb4), crc_adjust);