From patchwork Mon Feb 8 09:07:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Feifei Wang X-Patchwork-Id: 87816 X-Patchwork-Delegate: qi.z.zhang@intel.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 9DBF6A0547; Mon, 8 Feb 2021 10:07:17 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 148A040693; Mon, 8 Feb 2021 10:07:17 +0100 (CET) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mails.dpdk.org (Postfix) with ESMTP id 8C02F40147; Mon, 8 Feb 2021 10:07:15 +0100 (CET) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B19781FB; Mon, 8 Feb 2021 01:07:14 -0800 (PST) Received: from net-x86-dell-8268.shanghai.arm.com (net-x86-dell-8268.shanghai.arm.com [10.169.210.127]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id BC1163F719; Mon, 8 Feb 2021 01:07:11 -0800 (PST) From: Feifei Wang To: Jerin Jacob , Ruifeng Wang , Jeff Guo , Haiyue Wang Cc: dev@dpdk.org, nd@arm.com, Feifei Wang , stable@dpdk.org, Paolo Valerio Date: Mon, 8 Feb 2021 17:07:04 +0800 Message-Id: <20210208090704.1856110-1-feifei.wang2@arm.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH v1] net/ixgbe: fix UDP zero checksum error for Arm NEON path X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" 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 Signed-off-by: Feifei Wang Reviewed-by: Ruifeng Wang --- drivers/net/ixgbe/ixgbe_rxtx_vec_neon.c | 46 +++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) 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);