The IEEE1588 timesync support was only supported on the scalar RX paths,
but is, in a number of ways, quite similar to how FDIR support works: we
read and process values from the various per-packet flags and then do a
single store to the mbuf. Add support for IEEE1588 to the AVX2 and
AVX-512 vector functions inline in the main descriptor processing loop,
as well as the appropriate one-line fix for the case of scattered
packets.

Suggested-by: Anurag Mandal <[email protected]>
Signed-off-by: Bruce Richardson <[email protected]>
---
 drivers/net/intel/common/rx.h                 |  3 +
 drivers/net/intel/i40e/i40e_rxtx_vec_avx2.c   | 59 ++++++++++++++++++
 drivers/net/intel/i40e/i40e_rxtx_vec_avx512.c | 61 +++++++++++++++++++
 drivers/net/intel/i40e/i40e_rxtx_vec_common.h | 12 ++--
 4 files changed, 131 insertions(+), 4 deletions(-)

diff --git a/drivers/net/intel/common/rx.h b/drivers/net/intel/common/rx.h
index e0bf520ebd..8f4454d477 100644
--- a/drivers/net/intel/common/rx.h
+++ b/drivers/net/intel/common/rx.h
@@ -167,6 +167,9 @@ ci_rx_reassemble_packets(struct rte_mbuf **rx_bufs, 
uint16_t nb_bufs, uint8_t *s
                                start->hash = end->hash;
                                start->vlan_tci = end->vlan_tci;
                                start->ol_flags = end->ol_flags;
+#ifdef RTE_LIBRTE_IEEE1588
+                               start->timesync = end->timesync;
+#endif
                                /* we need to strip crc for the whole packet */
                                start->pkt_len -= crc_len;
                                if (end->data_len > crc_len) {
diff --git a/drivers/net/intel/i40e/i40e_rxtx_vec_avx2.c 
b/drivers/net/intel/i40e/i40e_rxtx_vec_avx2.c
index dd06e258ad..652a915db2 100644
--- a/drivers/net/intel/i40e/i40e_rxtx_vec_avx2.c
+++ b/drivers/net/intel/i40e/i40e_rxtx_vec_avx2.c
@@ -494,6 +494,65 @@ _recv_raw_pkts_vec_avx2(struct ci_rx_queue *rxq, struct 
rte_mbuf **rx_pkts,
 
                } /* if() on FDIR enabled */
 
+#ifdef RTE_LIBRTE_IEEE1588
+               /* The TSYNVALID and TSYNINDX bits are already present in
+                * status0_7, so the PTP timestamp flags can be built with
+                * no extra descriptor reads, the same way the RSS/FDIR flags
+                * are above. Only the 2-bit timestamp register index has to
+                * land in a specific mbuf field, so it still needs a
+                * per-packet store, done the same way as the FDIR ID above.
+                */
+               const __m256i tsyn_valid_mask = _mm256_set1_epi32(
+                               1 << I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT);
+               const __m256i tsyn_valid = _mm256_cmpeq_epi32(
+                               _mm256_and_si256(status0_7, tsyn_valid_mask),
+                               tsyn_valid_mask);
+               const __m256i tmst_flags = _mm256_and_si256(tsyn_valid,
+                               _mm256_set1_epi32(RTE_MBUF_F_RX_IEEE1588_TMST));
+               mbuf_flags = _mm256_or_si256(mbuf_flags, tmst_flags);
+
+               /* zero the index unless TSYNVALID is set, to match the
+                * scalar driver, which only ever assigns tsyn & 0x03
+                */
+               const __m256i tsyn_indx = _mm256_and_si256(tsyn_valid,
+                               _mm256_srli_epi32(_mm256_and_si256(status0_7,
+                                       _mm256_set1_epi32(0x3 << 
I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT)),
+                                       I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT));
+
+               /* status0_7 packet order is (hi->lo): [1, 3, 5, 7, 0, 2, 4, 6] 
*/
+               rx_pkts[i + 1]->timesync = _mm256_extract_epi32(tsyn_indx, 7);
+               rx_pkts[i + 3]->timesync = _mm256_extract_epi32(tsyn_indx, 6);
+               rx_pkts[i + 5]->timesync = _mm256_extract_epi32(tsyn_indx, 5);
+               rx_pkts[i + 7]->timesync = _mm256_extract_epi32(tsyn_indx, 4);
+               rx_pkts[i + 0]->timesync = _mm256_extract_epi32(tsyn_indx, 3);
+               rx_pkts[i + 2]->timesync = _mm256_extract_epi32(tsyn_indx, 2);
+               rx_pkts[i + 4]->timesync = _mm256_extract_epi32(tsyn_indx, 1);
+               rx_pkts[i + 6]->timesync = _mm256_extract_epi32(tsyn_indx, 0);
+
+               /* the PTP flag only depends on packet_type, which was already
+                * looked up above for each packet, so again no extra reads
+                * are needed to build it
+                */
+               const __m256i ptp_flags = _mm256_set_epi32(
+                       (ptype_tbl[ptype1] & RTE_PTYPE_L2_MASK) == 
RTE_PTYPE_L2_ETHER_TIMESYNC ?
+                               RTE_MBUF_F_RX_IEEE1588_PTP : 0,
+                       (ptype_tbl[ptype3] & RTE_PTYPE_L2_MASK) == 
RTE_PTYPE_L2_ETHER_TIMESYNC ?
+                               RTE_MBUF_F_RX_IEEE1588_PTP : 0,
+                       (ptype_tbl[ptype5] & RTE_PTYPE_L2_MASK) == 
RTE_PTYPE_L2_ETHER_TIMESYNC ?
+                               RTE_MBUF_F_RX_IEEE1588_PTP : 0,
+                       (ptype_tbl[ptype7] & RTE_PTYPE_L2_MASK) == 
RTE_PTYPE_L2_ETHER_TIMESYNC ?
+                               RTE_MBUF_F_RX_IEEE1588_PTP : 0,
+                       (ptype_tbl[ptype0] & RTE_PTYPE_L2_MASK) == 
RTE_PTYPE_L2_ETHER_TIMESYNC ?
+                               RTE_MBUF_F_RX_IEEE1588_PTP : 0,
+                       (ptype_tbl[ptype2] & RTE_PTYPE_L2_MASK) == 
RTE_PTYPE_L2_ETHER_TIMESYNC ?
+                               RTE_MBUF_F_RX_IEEE1588_PTP : 0,
+                       (ptype_tbl[ptype4] & RTE_PTYPE_L2_MASK) == 
RTE_PTYPE_L2_ETHER_TIMESYNC ?
+                               RTE_MBUF_F_RX_IEEE1588_PTP : 0,
+                       (ptype_tbl[ptype6] & RTE_PTYPE_L2_MASK) == 
RTE_PTYPE_L2_ETHER_TIMESYNC ?
+                               RTE_MBUF_F_RX_IEEE1588_PTP : 0);
+               mbuf_flags = _mm256_or_si256(mbuf_flags, ptp_flags);
+#endif /* RTE_LIBRTE_IEEE1588 */
+
                /*
                 * At this point, we have the 8 sets of flags in the low 16-bits
                 * of each 32-bit value in vlan0.
diff --git a/drivers/net/intel/i40e/i40e_rxtx_vec_avx512.c 
b/drivers/net/intel/i40e/i40e_rxtx_vec_avx512.c
index ea2e6dc024..f96e965914 100644
--- a/drivers/net/intel/i40e/i40e_rxtx_vec_avx512.c
+++ b/drivers/net/intel/i40e/i40e_rxtx_vec_avx512.c
@@ -543,6 +543,67 @@ _recv_raw_pkts_vec_avx512(struct ci_rx_queue *rxq, struct 
rte_mbuf **rx_pkts,
 
                } /* if() on FDIR enabled */
 
+#ifdef RTE_LIBRTE_IEEE1588
+               /* The TSYNVALID and TSYNINDX bits are already present in
+                * status0_7, so the PTP timestamp flags can be built with
+                * no extra descriptor reads, the same way the RSS/FDIR flags
+                * are above. Only the 2-bit timestamp register index has to
+                * land in a specific mbuf field, so it still needs a
+                * per-packet store, done the same way as the FDIR ID above.
+                */
+               const __m256i tsyn_valid_mask = _mm256_set1_epi32(
+                               1 << I40E_RXD_QW1_STATUS_TSYNVALID_SHIFT);
+               const __m256i tsyn_valid = _mm256_cmpeq_epi32(
+                               _mm256_and_si256(status0_7, tsyn_valid_mask),
+                               tsyn_valid_mask);
+               const __m256i tmst_flags = _mm256_and_si256(tsyn_valid,
+                               _mm256_set1_epi32(RTE_MBUF_F_RX_IEEE1588_TMST));
+
+               mbuf_flags = _mm256_or_si256(mbuf_flags, tmst_flags);
+
+               /* zero the index unless TSYNVALID is set, to match the
+                * scalar driver, which only ever assigns tsyn & 0x03
+                */
+               const __m256i tsyn_indx = _mm256_and_si256(tsyn_valid,
+                               _mm256_srli_epi32(_mm256_and_si256(status0_7,
+                                       _mm256_set1_epi32(0x3 << 
I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT)),
+                                       I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT));
+
+               /* status0_7 packet order is (hi->lo): [1, 3, 5, 7, 0, 2, 4, 6] 
*/
+               rx_pkts[i + 1]->timesync = _mm256_extract_epi32(tsyn_indx, 7);
+               rx_pkts[i + 3]->timesync = _mm256_extract_epi32(tsyn_indx, 6);
+               rx_pkts[i + 5]->timesync = _mm256_extract_epi32(tsyn_indx, 5);
+               rx_pkts[i + 7]->timesync = _mm256_extract_epi32(tsyn_indx, 4);
+               rx_pkts[i + 0]->timesync = _mm256_extract_epi32(tsyn_indx, 3);
+               rx_pkts[i + 2]->timesync = _mm256_extract_epi32(tsyn_indx, 2);
+               rx_pkts[i + 4]->timesync = _mm256_extract_epi32(tsyn_indx, 1);
+               rx_pkts[i + 6]->timesync = _mm256_extract_epi32(tsyn_indx, 0);
+
+               /* the PTP flag only depends on packet_type, which was already
+                * looked up above for each packet, so again no extra reads
+                * are needed to build it
+                */
+               const __m256i ptp_flags = _mm256_set_epi32(
+                       (ptype_tbl[ptype1] & RTE_PTYPE_L2_MASK) == 
RTE_PTYPE_L2_ETHER_TIMESYNC ?
+                               RTE_MBUF_F_RX_IEEE1588_PTP : 0,
+                       (ptype_tbl[ptype3] & RTE_PTYPE_L2_MASK) == 
RTE_PTYPE_L2_ETHER_TIMESYNC ?
+                               RTE_MBUF_F_RX_IEEE1588_PTP : 0,
+                       (ptype_tbl[ptype5] & RTE_PTYPE_L2_MASK) == 
RTE_PTYPE_L2_ETHER_TIMESYNC ?
+                               RTE_MBUF_F_RX_IEEE1588_PTP : 0,
+                       (ptype_tbl[ptype7] & RTE_PTYPE_L2_MASK) == 
RTE_PTYPE_L2_ETHER_TIMESYNC ?
+                               RTE_MBUF_F_RX_IEEE1588_PTP : 0,
+                       (ptype_tbl[ptype0] & RTE_PTYPE_L2_MASK) == 
RTE_PTYPE_L2_ETHER_TIMESYNC ?
+                               RTE_MBUF_F_RX_IEEE1588_PTP : 0,
+                       (ptype_tbl[ptype2] & RTE_PTYPE_L2_MASK) == 
RTE_PTYPE_L2_ETHER_TIMESYNC ?
+                               RTE_MBUF_F_RX_IEEE1588_PTP : 0,
+                       (ptype_tbl[ptype4] & RTE_PTYPE_L2_MASK) == 
RTE_PTYPE_L2_ETHER_TIMESYNC ?
+                               RTE_MBUF_F_RX_IEEE1588_PTP : 0,
+                       (ptype_tbl[ptype6] & RTE_PTYPE_L2_MASK) == 
RTE_PTYPE_L2_ETHER_TIMESYNC ?
+                               RTE_MBUF_F_RX_IEEE1588_PTP : 0);
+
+               mbuf_flags = _mm256_or_si256(mbuf_flags, ptp_flags);
+#endif /* RTE_LIBRTE_IEEE1588 */
+
                /* At this point, we have the 8 sets of flags in the low 16-bits
                 * of each 32-bit value in vlan0.
                 * We want to extract these, and merge them with the mbuf init 
data
diff --git a/drivers/net/intel/i40e/i40e_rxtx_vec_common.h 
b/drivers/net/intel/i40e/i40e_rxtx_vec_common.h
index 292a39501e..521e206438 100644
--- a/drivers/net/intel/i40e/i40e_rxtx_vec_common.h
+++ b/drivers/net/intel/i40e/i40e_rxtx_vec_common.h
@@ -53,7 +53,14 @@ _i40e_rx_queue_release_mbufs_vec(struct ci_rx_queue *rxq)
 static inline int
 i40e_rx_vec_dev_conf_condition_check_default(struct rte_eth_dev *dev)
 {
-#ifndef RTE_LIBRTE_IEEE1588
+#if defined(RTE_LIBRTE_IEEE1588) && !defined(RTE_ARCH_X86)
+       /* Only the AVX2/AVX512 Rx paths propagate the IEEE1588 PTP flags and
+        * the hardware timestamp register index, so other architectures
+        * still have to fall back to the scalar Rx path.
+        */
+       RTE_SET_USED(dev);
+       return -1;
+#else
        /**
         * Vector mode is allowed only when number of Rx queue
         * descriptor is power of 2.
@@ -67,9 +74,6 @@ i40e_rx_vec_dev_conf_condition_check_default(struct 
rte_eth_dev *dev)
        }
 
        return 0;
-#else
-       RTE_SET_USED(dev);
-       return -1;
 #endif
 }
 
-- 
2.53.0

Reply via email to