[PATCH] net/ice: support Rx timestamp offload on vector path

Sandeep Penigalapati sandeep.penigalapati at intel.com
Fri Sep 18 23:03:52 CEST 2026


The ice PMD only supported Rx hardware timestamp offload
(RTE_ETH_RX_OFFLOAD_TIMESTAMP) on the scalar Rx path. Enabling the
offload forced a fallback from the AVX2/AVX512 vector Rx paths to the
scalar path, causing a significant performance drop on 800 series
adapters.

Add Rx timestamp support to the AVX2 and AVX512 vector Rx paths,
mirroring the existing iavf implementation: the 32-bit timestamp is
read from the flex descriptor in the vectorized loop and converted to
64 bits, with register rollover tracking, in a scalar pass over the
received packets after the loop.

Advertise the timestamp offload only on the x86 vector paths that
implement it, via a new ICE_RX_VECTOR_OFFLOAD_TS_OFFLOADS mask, so on
Arm the request still falls back to the scalar path.

Signed-off-by: Sandeep Penigalapati <sandeep.penigalapati at intel.com>
---
 doc/guides/nics/features/ice.ini            |   2 +-
 doc/guides/rel_notes/release_26_11.rst      |   5 +
 drivers/net/intel/ice/ice_rxtx.c            |   8 +-
 drivers/net/intel/ice/ice_rxtx.h            |   4 +
 drivers/net/intel/ice/ice_rxtx_vec_avx2.c   | 158 +++++++++++++++-----
 drivers/net/intel/ice/ice_rxtx_vec_avx512.c | 158 +++++++++++++++-----
 6 files changed, 262 insertions(+), 73 deletions(-)

diff --git a/doc/guides/nics/features/ice.ini b/doc/guides/nics/features/ice.ini
index 893d09e9ec..0ff4af19e0 100644
--- a/doc/guides/nics/features/ice.ini
+++ b/doc/guides/nics/features/ice.ini
@@ -36,7 +36,7 @@ VLAN offload         = Y
 QinQ offload         = P
 L3 checksum offload  = Y
 L4 checksum offload  = Y
-Timestamp offload    = P
+Timestamp offload    = Y
 Inner L3 checksum    = P
 Inner L4 checksum    = P
 Packet type parsing  = Y
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index 4b3e5d995c..bc5faa5182 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst
@@ -56,6 +56,11 @@ New Features
      =======================================================
 
 
+* **Updated Intel ice driver.**
+
+  Added support for the Rx hardware timestamp offload
+  (``RTE_ETH_RX_OFFLOAD_TIMESTAMP``) in the AVX2 and AVX512 vector Rx paths.
+
 Removed Items
 -------------
 
diff --git a/drivers/net/intel/ice/ice_rxtx.c b/drivers/net/intel/ice/ice_rxtx.c
index c4b5454c53..2a81b998dc 100644
--- a/drivers/net/intel/ice/ice_rxtx.c
+++ b/drivers/net/intel/ice/ice_rxtx.c
@@ -3303,7 +3303,7 @@ static const struct ci_rx_path_info ice_rx_path_infos[] = {
 		.pkt_burst = ice_recv_pkts_vec_avx2_offload,
 		.info = "Offload Vector AVX2",
 		.features = {
-			.rx_offloads = ICE_RX_VECTOR_OFFLOAD_OFFLOADS,
+			.rx_offloads = ICE_RX_VECTOR_OFFLOAD_TS_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_256,
 			.bulk_alloc = true
 		}
@@ -3312,7 +3312,7 @@ static const struct ci_rx_path_info ice_rx_path_infos[] = {
 		.pkt_burst = ice_recv_scattered_pkts_vec_avx2_offload,
 		.info = "Offload Vector AVX2 Scattered",
 		.features = {
-			.rx_offloads = ICE_RX_VECTOR_OFFLOAD_OFFLOADS,
+			.rx_offloads = ICE_RX_VECTOR_OFFLOAD_TS_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_256,
 			.scattered = true,
 			.bulk_alloc = true
@@ -3342,7 +3342,7 @@ static const struct ci_rx_path_info ice_rx_path_infos[] = {
 		.pkt_burst = ice_recv_pkts_vec_avx512_offload,
 		.info = "Offload Vector AVX512",
 		.features = {
-			.rx_offloads = ICE_RX_VECTOR_OFFLOAD_OFFLOADS,
+			.rx_offloads = ICE_RX_VECTOR_OFFLOAD_TS_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_512,
 			.bulk_alloc = true
 		}
@@ -3351,7 +3351,7 @@ static const struct ci_rx_path_info ice_rx_path_infos[] = {
 		.pkt_burst = ice_recv_scattered_pkts_vec_avx512_offload,
 		.info = "Offload Vector AVX512 Scattered",
 		.features = {
-			.rx_offloads = ICE_RX_VECTOR_OFFLOAD_OFFLOADS,
+			.rx_offloads = ICE_RX_VECTOR_OFFLOAD_TS_OFFLOADS,
 			.simd_width = RTE_VECT_SIMD_512,
 			.scattered = true,
 			.bulk_alloc = true
diff --git a/drivers/net/intel/ice/ice_rxtx.h b/drivers/net/intel/ice/ice_rxtx.h
index 999b6b30d6..1ac57c23a4 100644
--- a/drivers/net/intel/ice/ice_rxtx.h
+++ b/drivers/net/intel/ice/ice_rxtx.h
@@ -105,6 +105,10 @@
 		RTE_ETH_RX_OFFLOAD_VLAN_STRIP |	\
 		RTE_ETH_RX_OFFLOAD_VLAN_FILTER |\
 		RTE_ETH_RX_OFFLOAD_RSS_HASH)
+/* vector offload paths that also support Rx timestamp (AVX2/AVX512 only) */
+#define ICE_RX_VECTOR_OFFLOAD_TS_OFFLOADS (	\
+		ICE_RX_VECTOR_OFFLOAD_OFFLOADS |\
+		RTE_ETH_RX_OFFLOAD_TIMESTAMP)
 
 /* basic scalar path */
 #define ICE_TX_SCALAR_OFFLOADS (		\
diff --git a/drivers/net/intel/ice/ice_rxtx_vec_avx2.c b/drivers/net/intel/ice/ice_rxtx_vec_avx2.c
index b72f69a47b..a316eae43b 100644
--- a/drivers/net/intel/ice/ice_rxtx_vec_avx2.c
+++ b/drivers/net/intel/ice/ice_rxtx_vec_avx2.c
@@ -7,6 +7,7 @@
 #include "../common/rx_vec_x86.h"
 
 #include <rte_vect.h>
+#include <rte_mbuf_dyn.h>
 
 static __rte_always_inline void
 ice_rxq_rearm(struct ci_rx_queue *rxq)
@@ -440,12 +441,16 @@ _ice_recv_raw_pkts_vec_avx2(struct ci_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 
 		if (offload) {
 #ifndef RTE_NET_INTEL_USE_16BYTE_DESC
+			const uint64_t rxmode_offloads =
+				rxq->ice_vsi->adapter->pf.dev_data->dev_conf.rxmode.offloads;
 			/**
-			 * needs to load 2nd 16B of each desc for RSS hash parsing,
+			 * needs to load 2nd 16B of each desc for RSS hash parsing
+			 * or Rx timestamp offload,
 			 * will cause performance drop to get into this context.
 			 */
-			if (rxq->ice_vsi->adapter->pf.dev_data->dev_conf.rxmode.offloads &
-					RTE_ETH_RX_OFFLOAD_RSS_HASH) {
+			if (rxmode_offloads &
+					(RTE_ETH_RX_OFFLOAD_RSS_HASH |
+					 RTE_ETH_RX_OFFLOAD_TIMESTAMP)) {
 				/* load bottom half of every 32B desc */
 				const __m128i raw_desc_bh7 = _mm_load_si128
 					(RTE_CAST_PTR(const __m128i *, &rxdp[7].wb.status_error1));
@@ -488,37 +493,77 @@ _ice_recv_raw_pkts_vec_avx2(struct ci_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 						(_mm256_castsi128_si256(raw_desc_bh0),
 						raw_desc_bh1, 1);
 
-				/**
-				 * to shift the 32b RSS hash value to the
-				 * highest 32b of each 128b before mask
-				 */
-				__m256i rss_hash6_7 =
-					_mm256_slli_epi64(raw_desc_bh6_7, 32);
-				__m256i rss_hash4_5 =
-					_mm256_slli_epi64(raw_desc_bh4_5, 32);
-				__m256i rss_hash2_3 =
-					_mm256_slli_epi64(raw_desc_bh2_3, 32);
-				__m256i rss_hash0_1 =
-					_mm256_slli_epi64(raw_desc_bh0_1, 32);
-
-				__m256i rss_hash_msk =
-					_mm256_set_epi32(0xFFFFFFFF, 0, 0, 0,
-							 0xFFFFFFFF, 0, 0, 0);
-
-				rss_hash6_7 = _mm256_and_si256
-						(rss_hash6_7, rss_hash_msk);
-				rss_hash4_5 = _mm256_and_si256
-						(rss_hash4_5, rss_hash_msk);
-				rss_hash2_3 = _mm256_and_si256
-						(rss_hash2_3, rss_hash_msk);
-				rss_hash0_1 = _mm256_and_si256
-						(rss_hash0_1, rss_hash_msk);
-
-				mb6_7 = _mm256_or_si256(mb6_7, rss_hash6_7);
-				mb4_5 = _mm256_or_si256(mb4_5, rss_hash4_5);
-				mb2_3 = _mm256_or_si256(mb2_3, rss_hash2_3);
-				mb0_1 = _mm256_or_si256(mb0_1, rss_hash0_1);
-			} /* if() on RSS hash parsing */
+				if (rxmode_offloads & RTE_ETH_RX_OFFLOAD_RSS_HASH) {
+					/**
+					 * to shift the 32b RSS hash value to the
+					 * highest 32b of each 128b before mask
+					 */
+					__m256i rss_hash6_7 =
+						_mm256_slli_epi64(raw_desc_bh6_7, 32);
+					__m256i rss_hash4_5 =
+						_mm256_slli_epi64(raw_desc_bh4_5, 32);
+					__m256i rss_hash2_3 =
+						_mm256_slli_epi64(raw_desc_bh2_3, 32);
+					__m256i rss_hash0_1 =
+						_mm256_slli_epi64(raw_desc_bh0_1, 32);
+
+					__m256i rss_hash_msk =
+						_mm256_set_epi32(0xFFFFFFFF, 0, 0, 0,
+								 0xFFFFFFFF, 0, 0, 0);
+
+					rss_hash6_7 = _mm256_and_si256
+							(rss_hash6_7, rss_hash_msk);
+					rss_hash4_5 = _mm256_and_si256
+							(rss_hash4_5, rss_hash_msk);
+					rss_hash2_3 = _mm256_and_si256
+							(rss_hash2_3, rss_hash_msk);
+					rss_hash0_1 = _mm256_and_si256
+							(rss_hash0_1, rss_hash_msk);
+
+					mb6_7 = _mm256_or_si256(mb6_7, rss_hash6_7);
+					mb4_5 = _mm256_or_si256(mb4_5, rss_hash4_5);
+					mb2_3 = _mm256_or_si256(mb2_3, rss_hash2_3);
+					mb0_1 = _mm256_or_si256(mb0_1, rss_hash0_1);
+				} /* if() on RSS hash parsing */
+
+				if (rxmode_offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) {
+					/**
+					 * Extract the 32b Rx timestamp (flex_ts.ts_high),
+					 * located in the highest 32b of each 32B desc, and
+					 * stash it (low 32b) into the mbuf timestamp
+					 * dynfield. The 32b->64b conversion with rollover
+					 * tracking is performed in a scalar pass after the
+					 * main loop (see below), matching the scalar path.
+					 */
+					*RTE_MBUF_DYNFIELD(rx_pkts[i + 0],
+						rxq->ts_offset, uint32_t *) =
+						_mm256_extract_epi32(raw_desc_bh0_1, 3);
+					*RTE_MBUF_DYNFIELD(rx_pkts[i + 1],
+						rxq->ts_offset, uint32_t *) =
+						_mm256_extract_epi32(raw_desc_bh0_1, 7);
+					*RTE_MBUF_DYNFIELD(rx_pkts[i + 2],
+						rxq->ts_offset, uint32_t *) =
+						_mm256_extract_epi32(raw_desc_bh2_3, 3);
+					*RTE_MBUF_DYNFIELD(rx_pkts[i + 3],
+						rxq->ts_offset, uint32_t *) =
+						_mm256_extract_epi32(raw_desc_bh2_3, 7);
+					*RTE_MBUF_DYNFIELD(rx_pkts[i + 4],
+						rxq->ts_offset, uint32_t *) =
+						_mm256_extract_epi32(raw_desc_bh4_5, 3);
+					*RTE_MBUF_DYNFIELD(rx_pkts[i + 5],
+						rxq->ts_offset, uint32_t *) =
+						_mm256_extract_epi32(raw_desc_bh4_5, 7);
+					*RTE_MBUF_DYNFIELD(rx_pkts[i + 6],
+						rxq->ts_offset, uint32_t *) =
+						_mm256_extract_epi32(raw_desc_bh6_7, 3);
+					*RTE_MBUF_DYNFIELD(rx_pkts[i + 7],
+						rxq->ts_offset, uint32_t *) =
+						_mm256_extract_epi32(raw_desc_bh6_7, 7);
+
+					mbuf_flags = _mm256_or_si256(mbuf_flags,
+						_mm256_set1_epi32((int)rxq->ts_flag));
+				} /* if() on Rx timestamp parsing */
+			} /* if() on RSS hash or Rx timestamp parsing */
 #endif
 		}
 
@@ -653,6 +698,51 @@ _ice_recv_raw_pkts_vec_avx2(struct ci_rx_queue *rxq, struct rte_mbuf **rx_pkts,
 			break;
 	}
 
+#ifndef RTE_NET_INTEL_USE_16BYTE_DESC
+	/**
+	 * Convert the stashed 32b Rx timestamps to 64b for the packets that
+	 * were actually received, tracking the register rollover. This mirrors
+	 * the scalar Rx path and is only done over valid (received) packets, so
+	 * timestamps of non-DD descriptors never corrupt the rollover state.
+	 */
+	if (offload && received > 0 &&
+			(rxq->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP)) {
+		struct ice_vsi *vsi = rxq->ice_vsi;
+		struct ice_hw *hw = ICE_VSI_TO_HW(vsi);
+		struct ice_adapter *ad = vsi->adapter;
+		uint64_t ts_ns;
+		bool is_tsinit = false;
+		uint64_t sw_cur_time =
+			rte_get_timer_cycles() / (rte_get_timer_hz() / 1000);
+
+		if (unlikely(sw_cur_time - rxq->hw_time_update > 4))
+			is_tsinit = true;
+
+		for (uint16_t k = 0; k < received; k++) {
+			uint32_t ts_high = *RTE_MBUF_DYNFIELD(rx_pkts[k],
+					rxq->ts_offset, uint32_t *);
+
+			rxq->time_high = ts_high;
+			if (unlikely(is_tsinit)) {
+				ts_ns = ice_tstamp_convert_32b_64b(hw, ad, 1,
+								   ts_high);
+				rxq->hw_time_low = (uint32_t)ts_ns;
+				rxq->hw_time_high = (uint32_t)(ts_ns >> 32);
+				is_tsinit = false;
+			} else {
+				if (ts_high < rxq->hw_time_low)
+					rxq->hw_time_high += 1;
+				ts_ns = (uint64_t)rxq->hw_time_high << 32 | ts_high;
+				rxq->hw_time_low = ts_high;
+			}
+			*RTE_MBUF_DYNFIELD(rx_pkts[k], rxq->ts_offset,
+					   rte_mbuf_timestamp_t *) = ts_ns;
+		}
+		rxq->hw_time_update = rte_get_timer_cycles() /
+				      (rte_get_timer_hz() / 1000);
+	}
+#endif
+
 	/* update tail pointers */
 	rxq->rx_tail += received;
 	rxq->rx_tail &= (rxq->nb_rx_desc - 1);
diff --git a/drivers/net/intel/ice/ice_rxtx_vec_avx512.c b/drivers/net/intel/ice/ice_rxtx_vec_avx512.c
index 309ab9fca7..1ebfc064f4 100644
--- a/drivers/net/intel/ice/ice_rxtx_vec_avx512.c
+++ b/drivers/net/intel/ice/ice_rxtx_vec_avx512.c
@@ -7,6 +7,7 @@
 #include "../common/rx_vec_x86.h"
 
 #include <rte_vect.h>
+#include <rte_mbuf_dyn.h>
 
 static __rte_always_inline void
 ice_rxq_rearm(struct ci_rx_queue *rxq)
@@ -462,12 +463,16 @@ _ice_recv_raw_pkts_vec_avx512(struct ci_rx_queue *rxq,
 
 		if (do_offload) {
 #ifndef RTE_NET_INTEL_USE_16BYTE_DESC
+			const uint64_t rxmode_offloads =
+				rxq->ice_vsi->adapter->pf.dev_data->dev_conf.rxmode.offloads;
 			/**
-			 * needs to load 2nd 16B of each desc for RSS hash parsing,
+			 * needs to load 2nd 16B of each desc for RSS hash parsing
+			 * or Rx timestamp offload,
 			 * will cause performance drop to get into this context.
 			 */
-			if (rxq->ice_vsi->adapter->pf.dev_data->dev_conf.rxmode.offloads &
-					RTE_ETH_RX_OFFLOAD_RSS_HASH) {
+			if (rxmode_offloads &
+					(RTE_ETH_RX_OFFLOAD_RSS_HASH |
+					 RTE_ETH_RX_OFFLOAD_TIMESTAMP)) {
 				/* load bottom half of every 32B desc */
 				const __m128i raw_desc_bh7 = _mm_load_si128
 					(RTE_CAST_PTR(const __m128i *, &rxdp[7].wb.status_error1));
@@ -510,37 +515,77 @@ _ice_recv_raw_pkts_vec_avx512(struct ci_rx_queue *rxq,
 						(_mm256_castsi128_si256(raw_desc_bh0),
 						raw_desc_bh1, 1);
 
-				/**
-				 * to shift the 32b RSS hash value to the
-				 * highest 32b of each 128b before mask
-				 */
-				__m256i rss_hash6_7 =
-					_mm256_slli_epi64(raw_desc_bh6_7, 32);
-				__m256i rss_hash4_5 =
-					_mm256_slli_epi64(raw_desc_bh4_5, 32);
-				__m256i rss_hash2_3 =
-					_mm256_slli_epi64(raw_desc_bh2_3, 32);
-				__m256i rss_hash0_1 =
-					_mm256_slli_epi64(raw_desc_bh0_1, 32);
-
-				__m256i rss_hash_msk =
-					_mm256_set_epi32(0xFFFFFFFF, 0, 0, 0,
-							 0xFFFFFFFF, 0, 0, 0);
-
-				rss_hash6_7 = _mm256_and_si256
-						(rss_hash6_7, rss_hash_msk);
-				rss_hash4_5 = _mm256_and_si256
-						(rss_hash4_5, rss_hash_msk);
-				rss_hash2_3 = _mm256_and_si256
-						(rss_hash2_3, rss_hash_msk);
-				rss_hash0_1 = _mm256_and_si256
-						(rss_hash0_1, rss_hash_msk);
-
-				mb6_7 = _mm256_or_si256(mb6_7, rss_hash6_7);
-				mb4_5 = _mm256_or_si256(mb4_5, rss_hash4_5);
-				mb2_3 = _mm256_or_si256(mb2_3, rss_hash2_3);
-				mb0_1 = _mm256_or_si256(mb0_1, rss_hash0_1);
-			} /* if() on RSS hash parsing */
+				if (rxmode_offloads & RTE_ETH_RX_OFFLOAD_RSS_HASH) {
+					/**
+					 * to shift the 32b RSS hash value to the
+					 * highest 32b of each 128b before mask
+					 */
+					__m256i rss_hash6_7 =
+						_mm256_slli_epi64(raw_desc_bh6_7, 32);
+					__m256i rss_hash4_5 =
+						_mm256_slli_epi64(raw_desc_bh4_5, 32);
+					__m256i rss_hash2_3 =
+						_mm256_slli_epi64(raw_desc_bh2_3, 32);
+					__m256i rss_hash0_1 =
+						_mm256_slli_epi64(raw_desc_bh0_1, 32);
+
+					__m256i rss_hash_msk =
+						_mm256_set_epi32(0xFFFFFFFF, 0, 0, 0,
+								 0xFFFFFFFF, 0, 0, 0);
+
+					rss_hash6_7 = _mm256_and_si256
+							(rss_hash6_7, rss_hash_msk);
+					rss_hash4_5 = _mm256_and_si256
+							(rss_hash4_5, rss_hash_msk);
+					rss_hash2_3 = _mm256_and_si256
+							(rss_hash2_3, rss_hash_msk);
+					rss_hash0_1 = _mm256_and_si256
+							(rss_hash0_1, rss_hash_msk);
+
+					mb6_7 = _mm256_or_si256(mb6_7, rss_hash6_7);
+					mb4_5 = _mm256_or_si256(mb4_5, rss_hash4_5);
+					mb2_3 = _mm256_or_si256(mb2_3, rss_hash2_3);
+					mb0_1 = _mm256_or_si256(mb0_1, rss_hash0_1);
+				} /* if() on RSS hash parsing */
+
+				if (rxmode_offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) {
+					/**
+					 * Extract the 32b Rx timestamp (flex_ts.ts_high),
+					 * located in the highest 32b of each 32B desc, and
+					 * stash it (low 32b) into the mbuf timestamp
+					 * dynfield. The 32b->64b conversion with rollover
+					 * tracking is performed in a scalar pass after the
+					 * main loop (see below), matching the scalar path.
+					 */
+					*RTE_MBUF_DYNFIELD(rx_pkts[i + 0],
+						rxq->ts_offset, uint32_t *) =
+						_mm256_extract_epi32(raw_desc_bh0_1, 3);
+					*RTE_MBUF_DYNFIELD(rx_pkts[i + 1],
+						rxq->ts_offset, uint32_t *) =
+						_mm256_extract_epi32(raw_desc_bh0_1, 7);
+					*RTE_MBUF_DYNFIELD(rx_pkts[i + 2],
+						rxq->ts_offset, uint32_t *) =
+						_mm256_extract_epi32(raw_desc_bh2_3, 3);
+					*RTE_MBUF_DYNFIELD(rx_pkts[i + 3],
+						rxq->ts_offset, uint32_t *) =
+						_mm256_extract_epi32(raw_desc_bh2_3, 7);
+					*RTE_MBUF_DYNFIELD(rx_pkts[i + 4],
+						rxq->ts_offset, uint32_t *) =
+						_mm256_extract_epi32(raw_desc_bh4_5, 3);
+					*RTE_MBUF_DYNFIELD(rx_pkts[i + 5],
+						rxq->ts_offset, uint32_t *) =
+						_mm256_extract_epi32(raw_desc_bh4_5, 7);
+					*RTE_MBUF_DYNFIELD(rx_pkts[i + 6],
+						rxq->ts_offset, uint32_t *) =
+						_mm256_extract_epi32(raw_desc_bh6_7, 3);
+					*RTE_MBUF_DYNFIELD(rx_pkts[i + 7],
+						rxq->ts_offset, uint32_t *) =
+						_mm256_extract_epi32(raw_desc_bh6_7, 7);
+
+					mbuf_flags = _mm256_or_si256(mbuf_flags,
+						_mm256_set1_epi32((int)rxq->ts_flag));
+				} /* if() on Rx timestamp parsing */
+			} /* if() on RSS hash or Rx timestamp parsing */
 #endif
 		}
 
@@ -679,6 +724,51 @@ _ice_recv_raw_pkts_vec_avx512(struct ci_rx_queue *rxq,
 			break;
 	}
 
+#ifndef RTE_NET_INTEL_USE_16BYTE_DESC
+	/**
+	 * Convert the stashed 32b Rx timestamps to 64b for the packets that
+	 * were actually received, tracking the register rollover. This mirrors
+	 * the scalar Rx path and is only done over valid (received) packets, so
+	 * timestamps of non-DD descriptors never corrupt the rollover state.
+	 */
+	if (do_offload && received > 0 &&
+			(rxq->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP)) {
+		struct ice_vsi *vsi = rxq->ice_vsi;
+		struct ice_hw *hw = ICE_VSI_TO_HW(vsi);
+		struct ice_adapter *ad = vsi->adapter;
+		uint64_t ts_ns;
+		bool is_tsinit = false;
+		uint64_t sw_cur_time =
+			rte_get_timer_cycles() / (rte_get_timer_hz() / 1000);
+
+		if (unlikely(sw_cur_time - rxq->hw_time_update > 4))
+			is_tsinit = true;
+
+		for (uint16_t k = 0; k < received; k++) {
+			uint32_t ts_high = *RTE_MBUF_DYNFIELD(rx_pkts[k],
+					rxq->ts_offset, uint32_t *);
+
+			rxq->time_high = ts_high;
+			if (unlikely(is_tsinit)) {
+				ts_ns = ice_tstamp_convert_32b_64b(hw, ad, 1,
+								   ts_high);
+				rxq->hw_time_low = (uint32_t)ts_ns;
+				rxq->hw_time_high = (uint32_t)(ts_ns >> 32);
+				is_tsinit = false;
+			} else {
+				if (ts_high < rxq->hw_time_low)
+					rxq->hw_time_high += 1;
+				ts_ns = (uint64_t)rxq->hw_time_high << 32 | ts_high;
+				rxq->hw_time_low = ts_high;
+			}
+			*RTE_MBUF_DYNFIELD(rx_pkts[k], rxq->ts_offset,
+					   rte_mbuf_timestamp_t *) = ts_ns;
+		}
+		rxq->hw_time_update = rte_get_timer_cycles() /
+				      (rte_get_timer_hz() / 1000);
+	}
+#endif
+
 	/* update tail pointers */
 	rxq->rx_tail += received;
 	rxq->rx_tail &= (rxq->nb_rx_desc - 1);
-- 
2.27.0



More information about the dev mailing list