From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 2A315A054F for ; Mon, 15 Feb 2021 14:29:07 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 22F4140FDF; Mon, 15 Feb 2021 14:29:07 +0100 (CET) Received: from youngberry.canonical.com (youngberry.canonical.com [91.189.89.112]) by mails.dpdk.org (Postfix) with ESMTP id 20EBF1606E3 for ; Mon, 15 Feb 2021 14:29:05 +0100 (CET) Received: from 2.general.paelzer.uk.vpn ([10.172.196.173] helo=Keschdeichel.fritz.box) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1lBdvx-0003bz-AW; Mon, 15 Feb 2021 13:29:01 +0000 From: Christian Ehrhardt To: Haiyue Wang Cc: Paolo Valerio , Konstantin Ananyev , dpdk stable Date: Mon, 15 Feb 2021 14:28:53 +0100 Message-Id: <20210215132857.1855675-1-christian.ehrhardt@canonical.com> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210204112954.2488123-1-christian.ehrhardt@canonical.com> References: <20210204112954.2488123-1-christian.ehrhardt@canonical.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [dpdk-stable] patch 'net/ixgbe: fix UDP zero checksum on x86' has been queued to stable release 19.11.7 X-BeenThere: stable@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: patches for DPDK stable branches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: stable-bounces@dpdk.org Sender: "stable" Hi, FYI, your patch has been queued to stable release 19.11.7 Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet. It will be pushed if I get no objections before 02/17/21. So please shout if anyone has objections. Also note that after the patch there's a diff of the upstream commit vs the patch applied to the branch. This will indicate if there was any rebasing needed to apply to the stable branch. If there were code changes for rebasing (ie: not only metadata diffs), please double check that the rebase was correctly done. Queued patches are on a temporary branch at: https://github.com/cpaelzer/dpdk-stable-queue This queued commit can be viewed at: https://github.com/cpaelzer/dpdk-stable-queue/commit/19e34170ca42803f9179053b55c843041bad4768 Thanks. Christian Ehrhardt --- >From 19e34170ca42803f9179053b55c843041bad4768 Mon Sep 17 00:00:00 2001 From: Haiyue Wang Date: Thu, 4 Feb 2021 22:39:48 +0800 Subject: [PATCH] net/ixgbe: fix UDP zero checksum on x86 [ upstream commit 9a40edb599d76f7f9d116bb2f91b23c082b5f154 ] 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. This patch changes the bad UDP checksum to PKT_RX_L4_CKSUM_UNKNOWN, so the software application will then have to recompute the checksum itself if needed. Bugzilla ID: 629 Fixes: af75078fece3 ("first public release") Reported-by: Paolo Valerio Signed-off-by: Haiyue Wang Acked-by: Konstantin Ananyev Tested-by: Paolo Valerio --- doc/guides/nics/ixgbe.rst | 10 ++++++++ drivers/net/ixgbe/ixgbe_rxtx.c | 30 ++++++++++++++++++++---- drivers/net/ixgbe/ixgbe_rxtx.h | 2 ++ drivers/net/ixgbe/ixgbe_rxtx_vec_sse.c | 32 +++++++++++++++++++++++--- 4 files changed, 67 insertions(+), 7 deletions(-) diff --git a/doc/guides/nics/ixgbe.rst b/doc/guides/nics/ixgbe.rst index 5c3a7e4f26..6ca2a33f09 100644 --- a/doc/guides/nics/ixgbe.rst +++ b/doc/guides/nics/ixgbe.rst @@ -253,6 +253,16 @@ Before binding ``vfio`` with legacy mode in X550 NICs, use ``modprobe vfio `` ``nointxmask=1`` to load ``vfio`` module if the intx is not shared with other devices. +UDP with zero checksum is reported as error +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Intel 82599 10 Gigabit Ethernet Controller Specification Update (Revision 2.87) +Errata: 44 Integrity Error Reported for IPv4/UDP Packets With Zero Checksum + +To support UDP zero checksum, the zero and bad UDP checksum packet is marked as +PKT_RX_L4_CKSUM_UNKNOWN, so the application needs to recompute the checksum to +validate it. + Inline crypto processing support -------------------------------- diff --git a/drivers/net/ixgbe/ixgbe_rxtx.c b/drivers/net/ixgbe/ixgbe_rxtx.c index 7777dc17f1..8b9b009396 100644 --- a/drivers/net/ixgbe/ixgbe_rxtx.c +++ b/drivers/net/ixgbe/ixgbe_rxtx.c @@ -1440,7 +1440,8 @@ rx_desc_status_to_pkt_flags(uint32_t rx_status, uint64_t vlan_flags) } static inline uint64_t -rx_desc_error_to_pkt_flags(uint32_t rx_status) +rx_desc_error_to_pkt_flags(uint32_t rx_status, uint16_t pkt_info, + uint8_t rx_udp_csum_zero_err) { uint64_t pkt_flags; @@ -1457,6 +1458,15 @@ rx_desc_error_to_pkt_flags(uint32_t rx_status) pkt_flags = error_to_pkt_flags_map[(rx_status >> IXGBE_RXDADV_ERR_CKSUM_BIT) & IXGBE_RXDADV_ERR_CKSUM_MSK]; + /* Mask out the bad UDP checksum error if the hardware has UDP zero + * checksum error issue, so that the software application will then + * have to recompute the checksum itself if needed. + */ + if ((rx_status & IXGBE_RXDADV_ERR_TCPE) && + (pkt_info & IXGBE_RXDADV_PKTTYPE_UDP) && + rx_udp_csum_zero_err) + pkt_flags &= ~PKT_RX_L4_CKSUM_BAD; + if ((rx_status & IXGBE_RXD_STAT_OUTERIPCS) && (rx_status & IXGBE_RXDADV_ERR_OUTERIPER)) { pkt_flags |= PKT_RX_EIP_CKSUM_BAD; @@ -1543,7 +1553,9 @@ ixgbe_rx_scan_hw_ring(struct ixgbe_rx_queue *rxq) /* convert descriptor fields to rte mbuf flags */ pkt_flags = rx_desc_status_to_pkt_flags(s[j], vlan_flags); - pkt_flags |= rx_desc_error_to_pkt_flags(s[j]); + pkt_flags |= rx_desc_error_to_pkt_flags(s[j], + (uint16_t)pkt_info[j], + rxq->rx_udp_csum_zero_err); pkt_flags |= ixgbe_rxd_pkt_info_to_pkt_flags ((uint16_t)pkt_info[j]); mb->ol_flags = pkt_flags; @@ -1876,7 +1888,9 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, rxm->vlan_tci = rte_le_to_cpu_16(rxd.wb.upper.vlan); pkt_flags = rx_desc_status_to_pkt_flags(staterr, vlan_flags); - pkt_flags = pkt_flags | rx_desc_error_to_pkt_flags(staterr); + pkt_flags = pkt_flags | + rx_desc_error_to_pkt_flags(staterr, (uint16_t)pkt_info, + rxq->rx_udp_csum_zero_err); pkt_flags = pkt_flags | ixgbe_rxd_pkt_info_to_pkt_flags((uint16_t)pkt_info); rxm->ol_flags = pkt_flags; @@ -1969,7 +1983,8 @@ ixgbe_fill_cluster_head_buf( head->vlan_tci = rte_le_to_cpu_16(desc->wb.upper.vlan); pkt_info = rte_le_to_cpu_32(desc->wb.lower.lo_dword.data); pkt_flags = rx_desc_status_to_pkt_flags(staterr, rxq->vlan_flags); - pkt_flags |= rx_desc_error_to_pkt_flags(staterr); + pkt_flags |= rx_desc_error_to_pkt_flags(staterr, (uint16_t)pkt_info, + rxq->rx_udp_csum_zero_err); pkt_flags |= ixgbe_rxd_pkt_info_to_pkt_flags((uint16_t)pkt_info); head->ol_flags = pkt_flags; head->packet_type = @@ -2981,6 +2996,13 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev, else rxq->pkt_type_mask = IXGBE_PACKET_TYPE_MASK_82599; + /* + * 82599 errata, UDP frames with a 0 checksum can be marked as checksum + * errors. + */ + if (hw->mac.type == ixgbe_mac_82599EB) + rxq->rx_udp_csum_zero_err = 1; + /* * Allocate RX ring hardware descriptors. A memzone large enough to * handle the maximum ring size is allocated in order to allow for diff --git a/drivers/net/ixgbe/ixgbe_rxtx.h b/drivers/net/ixgbe/ixgbe_rxtx.h index 5e1ac44942..4adfbb3089 100644 --- a/drivers/net/ixgbe/ixgbe_rxtx.h +++ b/drivers/net/ixgbe/ixgbe_rxtx.h @@ -129,6 +129,8 @@ struct ixgbe_rx_queue { uint8_t crc_len; /**< 0 if CRC stripped, 4 otherwise. */ uint8_t drop_en; /**< If not 0, set SRRCTL.Drop_En. */ uint8_t rx_deferred_start; /**< not in global dev start. */ + /** UDP frames with a 0 checksum can be marked as checksum errors. */ + uint8_t rx_udp_csum_zero_err; /** flags to set in mbuf when a vlan is detected. */ uint64_t vlan_flags; uint64_t offloads; /**< Rx offloads with DEV_RX_OFFLOAD_* */ diff --git a/drivers/net/ixgbe/ixgbe_rxtx_vec_sse.c b/drivers/net/ixgbe/ixgbe_rxtx_vec_sse.c index 03eacfd86b..4b658605bf 100644 --- a/drivers/net/ixgbe/ixgbe_rxtx_vec_sse.c +++ b/drivers/net/ixgbe/ixgbe_rxtx_vec_sse.c @@ -132,9 +132,9 @@ desc_to_olflags_v_ipsec(__m128i descs[4], struct rte_mbuf **rx_pkts) static inline void desc_to_olflags_v(__m128i descs[4], __m128i mbuf_init, uint8_t vlan_flags, - struct rte_mbuf **rx_pkts) + uint16_t udp_p_flag, struct rte_mbuf **rx_pkts) { - __m128i ptype0, ptype1, vtag0, vtag1, csum; + __m128i ptype0, ptype1, vtag0, vtag1, csum, udp_csum_skip; __m128i rearm0, rearm1, rearm2, rearm3; /* mask everything except rss type */ @@ -161,6 +161,7 @@ desc_to_olflags_v(__m128i descs[4], __m128i mbuf_init, uint8_t vlan_flags, (IXGBE_RXDADV_ERR_TCPE | IXGBE_RXDADV_ERR_IPE) >> 16, IXGBE_RXD_STAT_VP, IXGBE_RXD_STAT_VP, IXGBE_RXD_STAT_VP, IXGBE_RXD_STAT_VP); + /* map vlan present (0x8), IPE (0x2), L4E (0x1) to ol_flags */ const __m128i vlan_csum_map_lo = _mm_set_epi8( 0, 0, 0, 0, @@ -182,12 +183,23 @@ desc_to_olflags_v(__m128i descs[4], __m128i mbuf_init, uint8_t vlan_flags, 0, PKT_RX_L4_CKSUM_GOOD >> sizeof(uint8_t), 0, PKT_RX_L4_CKSUM_GOOD >> sizeof(uint8_t)); + /* mask everything except UDP header present if specified */ + const __m128i udp_hdr_p_msk = _mm_set_epi16 + (0, 0, 0, 0, + udp_p_flag, udp_p_flag, udp_p_flag, udp_p_flag); + + const __m128i udp_csum_bad_shuf = _mm_set_epi8 + (0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, ~(uint8_t)PKT_RX_L4_CKSUM_BAD, 0xFF); + ptype0 = _mm_unpacklo_epi16(descs[0], descs[1]); ptype1 = _mm_unpacklo_epi16(descs[2], descs[3]); vtag0 = _mm_unpackhi_epi16(descs[0], descs[1]); vtag1 = _mm_unpackhi_epi16(descs[2], descs[3]); ptype0 = _mm_unpacklo_epi32(ptype0, ptype1); + /* save the UDP header present information */ + udp_csum_skip = _mm_and_si128(ptype0, udp_hdr_p_msk); ptype0 = _mm_and_si128(ptype0, rsstype_msk); ptype0 = _mm_shuffle_epi8(rss_flags, ptype0); @@ -215,6 +227,15 @@ desc_to_olflags_v(__m128i descs[4], __m128i mbuf_init, uint8_t vlan_flags, vtag1 = _mm_or_si128(ptype0, vtag1); + /* convert the UDP header present 0x200 to 0x1 for aligning with each + * PKT_RX_L4_CKSUM_BAD value in low byte of 16 bits word ol_flag in + * vtag1 (4x16). Then mask out the bad checksum value by shuffle and + * bit-mask. + */ + udp_csum_skip = _mm_srli_epi16(udp_csum_skip, 9); + udp_csum_skip = _mm_shuffle_epi8(udp_csum_bad_shuf, udp_csum_skip); + vtag1 = _mm_and_si128(vtag1, udp_csum_skip); + /* * At this point, we have the 4 sets of flags in the low 64-bits * of vtag1 (4x16). @@ -341,6 +362,7 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts, __m128i dd_check, eop_check; __m128i mbuf_init; 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); @@ -365,6 +387,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; + /* 4 packets DD mask */ dd_check = _mm_set_epi64x(0x0000000100000001LL, 0x0000000100000001LL); @@ -477,7 +502,8 @@ _recv_raw_pkts_vec(struct ixgbe_rx_queue *rxq, struct rte_mbuf **rx_pkts, sterr_tmp1 = _mm_unpackhi_epi32(descs[1], descs[0]); /* set ol_flags with vlan packet type */ - desc_to_olflags_v(descs, mbuf_init, vlan_flags, &rx_pkts[pos]); + desc_to_olflags_v(descs, mbuf_init, vlan_flags, udp_p_flag, + &rx_pkts[pos]); #ifdef RTE_LIBRTE_SECURITY if (unlikely(use_ipsec)) -- 2.30.0 --- Diff of the applied patch vs upstream commit (please double-check if non-empty: --- --- - 2021-02-15 14:24:49.349925566 +0100 +++ 0001-net-ixgbe-fix-UDP-zero-checksum-on-x86.patch 2021-02-15 14:24:49.277482176 +0100 @@ -1 +1 @@ -From 9a40edb599d76f7f9d116bb2f91b23c082b5f154 Mon Sep 17 00:00:00 2001 +From 19e34170ca42803f9179053b55c843041bad4768 Mon Sep 17 00:00:00 2001 @@ -5,0 +6,2 @@ +[ upstream commit 9a40edb599d76f7f9d116bb2f91b23c082b5f154 ] + @@ -16 +17,0 @@ -Cc: stable@dpdk.org @@ -30 +31 @@ -index 696cbd93ba..4c644c0e68 100644 +index 5c3a7e4f26..6ca2a33f09 100644 @@ -33,3 +34,3 @@ -@@ -257,6 +257,16 @@ RSS isn't supported when QinQ is enabled - - Due to FW limitation, IXGBE doesn't support RSS when QinQ is enabled currently. +@@ -253,6 +253,16 @@ Before binding ``vfio`` with legacy mode in X550 NICs, use ``modprobe vfio `` + ``nointxmask=1`` to load ``vfio`` module if the intx is not shared with other + devices. @@ -51 +52 @@ -index 72d27f35ca..950b7894e0 100644 +index 7777dc17f1..8b9b009396 100644 @@ -54 +55 @@ -@@ -1466,7 +1466,8 @@ rx_desc_status_to_pkt_flags(uint32_t rx_status, uint64_t vlan_flags) +@@ -1440,7 +1440,8 @@ rx_desc_status_to_pkt_flags(uint32_t rx_status, uint64_t vlan_flags) @@ -64 +65 @@ -@@ -1483,6 +1484,15 @@ rx_desc_error_to_pkt_flags(uint32_t rx_status) +@@ -1457,6 +1458,15 @@ rx_desc_error_to_pkt_flags(uint32_t rx_status) @@ -80 +81 @@ -@@ -1569,7 +1579,9 @@ ixgbe_rx_scan_hw_ring(struct ixgbe_rx_queue *rxq) +@@ -1543,7 +1553,9 @@ ixgbe_rx_scan_hw_ring(struct ixgbe_rx_queue *rxq) @@ -91 +92 @@ -@@ -1902,7 +1914,9 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, +@@ -1876,7 +1888,9 @@ ixgbe_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, @@ -102 +103 @@ -@@ -1995,7 +2009,8 @@ ixgbe_fill_cluster_head_buf( +@@ -1969,7 +1983,8 @@ ixgbe_fill_cluster_head_buf( @@ -112 +113 @@ -@@ -3116,6 +3131,13 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev, +@@ -2981,6 +2996,13 @@ ixgbe_dev_rx_queue_setup(struct rte_eth_dev *dev, @@ -127 +128 @@ -index 8a25e98df6..476ef62cfd 100644 +index 5e1ac44942..4adfbb3089 100644 @@ -140 +141 @@ -index 9bbffe6119..7610fd93db 100644 +index 03eacfd86b..4b658605bf 100644 @@ -229 +230 @@ - #ifdef RTE_LIB_SECURITY + #ifdef RTE_LIBRTE_SECURITY