]> git.droids-corp.org - dpdk.git/commitdiff
net/ice: improve performance of Rx timestamp offload
authorWenjun Wu <wenjun1.wu@intel.com>
Mon, 28 Feb 2022 07:36:07 +0000 (15:36 +0800)
committerQi Zhang <qi.z.zhang@intel.com>
Mon, 18 Apr 2022 05:47:18 +0000 (07:47 +0200)
Previously, each time a burst of packets is received, SW reads HW
register and assembles it and the timestamp from descriptor together to
get the complete 64 bits timestamp.

This patch optimizes the algorithm. The SW only needs to check the
monotonicity of the low 32bits timestamp to avoid crossing borders.
Each time before SW receives a burst of packets, it should check the
time difference between current time and last update time to avoid
the low 32 bits timestamp cycling twice.

The patch proved a 50% ~ 70% single core performance improvement on a
main stream Xeon server, this fix the performance gap for some use cases.

Fixes: f9c561ffbccc ("net/ice: fix performance for Rx timestamp")
Cc: stable@dpdk.org
Signed-off-by: Wenjun Wu <wenjun1.wu@intel.com>
Acked-by: Qi Zhang <qi.z.zhang@intel.com>
drivers/net/ice/ice_ethdev.h
drivers/net/ice/ice_rxtx.c

index 09cfb60b0f28708f9a1ddcae7476b013a038c8d1..3ab310628fdfcd000b70e8a47c41e67dd9cd8dc1 100644 (file)
@@ -554,6 +554,9 @@ struct ice_adapter {
        struct rte_timecounter tx_tstamp_tc;
        bool ptp_ena;
        uint64_t time_hw;
+       uint32_t hw_time_high; /* high 32 bits of timestamp */
+       uint32_t hw_time_low; /* low 32 bits of timestamp */
+       uint64_t hw_time_update; /* SW time of HW record updating */
        struct ice_fdir_prof_info fdir_prof_info[ICE_MAX_PTGS];
        struct ice_rss_prof_info rss_prof_info[ICE_MAX_PTGS];
        /* True if DCF state of the associated PF is on */
index 041f4bc91fa6932ef22186766eb7eeb52bf36201..2dd2637fbb6d8e30ba5cb1fa4f753149d5dee8b9 100644 (file)
@@ -1574,9 +1574,10 @@ ice_rx_scan_hw_ring(struct ice_rx_queue *rxq)
        uint64_t pkt_flags = 0;
        uint32_t *ptype_tbl = rxq->vsi->adapter->ptype_tbl;
 #ifndef RTE_LIBRTE_ICE_16BYTE_RX_DESC
+       bool is_tsinit = false;
+       uint64_t ts_ns;
        struct ice_vsi *vsi = rxq->vsi;
        struct ice_hw *hw = ICE_VSI_TO_HW(vsi);
-       uint64_t ts_ns;
        struct ice_adapter *ad = rxq->vsi->adapter;
 #endif
        rxdp = &rxq->rx_ring[rxq->rx_tail];
@@ -1588,8 +1589,14 @@ ice_rx_scan_hw_ring(struct ice_rx_queue *rxq)
        if (!(stat_err0 & (1 << ICE_RX_FLEX_DESC_STATUS0_DD_S)))
                return 0;
 
-       if (rxq->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP)
-               rxq->hw_register_set = 1;
+#ifndef RTE_LIBRTE_ICE_16BYTE_RX_DESC
+       if (rxq->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) {
+               uint64_t sw_cur_time = rte_get_timer_cycles() / (rte_get_timer_hz() / 1000);
+
+               if (unlikely(sw_cur_time - ad->hw_time_update > 4))
+                       is_tsinit = 1;
+       }
+#endif
 
        /**
         * Scan LOOK_AHEAD descriptors at a time to determine which
@@ -1625,14 +1632,26 @@ ice_rx_scan_hw_ring(struct ice_rx_queue *rxq)
                        rxd_to_pkt_fields_ops[rxq->rxdid](rxq, mb, &rxdp[j]);
 #ifndef RTE_LIBRTE_ICE_16BYTE_RX_DESC
                        if (ice_timestamp_dynflag > 0) {
-                               ts_ns = ice_tstamp_convert_32b_64b(hw, ad,
-                                       rxq->hw_register_set,
-                                       rte_le_to_cpu_32(rxdp[j].wb.flex_ts.ts_high));
-                               rxq->hw_register_set = 0;
+                               rxq->time_high =
+                               rte_le_to_cpu_32(rxdp[j].wb.flex_ts.ts_high);
+                               if (unlikely(is_tsinit)) {
+                                       ts_ns = ice_tstamp_convert_32b_64b(hw, ad, 1,
+                                                                          rxq->time_high);
+                                       ad->hw_time_low = (uint32_t)ts_ns;
+                                       ad->hw_time_high = (uint32_t)(ts_ns >> 32);
+                                       is_tsinit = false;
+                               } else {
+                                       if (rxq->time_high < ad->hw_time_low)
+                                               ad->hw_time_high += 1;
+                                       ts_ns = (uint64_t)ad->hw_time_high << 32 | rxq->time_high;
+                                       ad->hw_time_low = rxq->time_high;
+                               }
+                               ad->hw_time_update = rte_get_timer_cycles() /
+                                                    (rte_get_timer_hz() / 1000);
                                *RTE_MBUF_DYNFIELD(mb,
-                                       ice_timestamp_dynfield_offset,
-                                       rte_mbuf_timestamp_t *) = ts_ns;
-                               mb->ol_flags |= ice_timestamp_dynflag;
+                                                  ice_timestamp_dynfield_offset,
+                                                  rte_mbuf_timestamp_t *) = ts_ns;
+                               pkt_flags |= ice_timestamp_dynflag;
                        }
 
                        if (ad->ptp_ena && ((mb->packet_type &
@@ -1831,14 +1850,19 @@ ice_recv_scattered_pkts(void *rx_queue,
        uint64_t pkt_flags;
        uint32_t *ptype_tbl = rxq->vsi->adapter->ptype_tbl;
 #ifndef RTE_LIBRTE_ICE_16BYTE_RX_DESC
+       bool is_tsinit = false;
+       uint64_t ts_ns;
        struct ice_vsi *vsi = rxq->vsi;
        struct ice_hw *hw = ICE_VSI_TO_HW(vsi);
-       uint64_t ts_ns;
        struct ice_adapter *ad = rxq->vsi->adapter;
-#endif
 
-       if (rxq->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP)
-               rxq->hw_register_set = 1;
+       if (rxq->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) {
+               uint64_t sw_cur_time = rte_get_timer_cycles() / (rte_get_timer_hz() / 1000);
+
+               if (unlikely(sw_cur_time - ad->hw_time_update > 4))
+                       is_tsinit = true;
+       }
+#endif
 
        while (nb_rx < nb_pkts) {
                rxdp = &rx_ring[rx_id];
@@ -1951,14 +1975,25 @@ ice_recv_scattered_pkts(void *rx_queue,
                pkt_flags = ice_rxd_error_to_pkt_flags(rx_stat_err0);
 #ifndef RTE_LIBRTE_ICE_16BYTE_RX_DESC
                if (ice_timestamp_dynflag > 0) {
-                       ts_ns = ice_tstamp_convert_32b_64b(hw, ad,
-                               rxq->hw_register_set,
-                               rte_le_to_cpu_32(rxd.wb.flex_ts.ts_high));
-                       rxq->hw_register_set = 0;
-                       *RTE_MBUF_DYNFIELD(first_seg,
-                               ice_timestamp_dynfield_offset,
-                               rte_mbuf_timestamp_t *) = ts_ns;
-                       first_seg->ol_flags |= ice_timestamp_dynflag;
+                       rxq->time_high =
+                          rte_le_to_cpu_32(rxd.wb.flex_ts.ts_high);
+                       if (unlikely(is_tsinit)) {
+                               ts_ns = ice_tstamp_convert_32b_64b(hw, ad, 1, rxq->time_high);
+                               ad->hw_time_low = (uint32_t)ts_ns;
+                               ad->hw_time_high = (uint32_t)(ts_ns >> 32);
+                               is_tsinit = false;
+                       } else {
+                               if (rxq->time_high < ad->hw_time_low)
+                                       ad->hw_time_high += 1;
+                               ts_ns = (uint64_t)ad->hw_time_high << 32 | rxq->time_high;
+                               ad->hw_time_low = rxq->time_high;
+                       }
+                       ad->hw_time_update = rte_get_timer_cycles() /
+                                            (rte_get_timer_hz() / 1000);
+                       *RTE_MBUF_DYNFIELD(rxm,
+                                          (ice_timestamp_dynfield_offset),
+                                          rte_mbuf_timestamp_t *) = ts_ns;
+                       pkt_flags |= ice_timestamp_dynflag;
                }
 
                if (ad->ptp_ena && ((first_seg->packet_type & RTE_PTYPE_L2_MASK)
@@ -2325,14 +2360,19 @@ ice_recv_pkts(void *rx_queue,
        uint64_t pkt_flags;
        uint32_t *ptype_tbl = rxq->vsi->adapter->ptype_tbl;
 #ifndef RTE_LIBRTE_ICE_16BYTE_RX_DESC
+       bool is_tsinit = false;
+       uint64_t ts_ns;
        struct ice_vsi *vsi = rxq->vsi;
        struct ice_hw *hw = ICE_VSI_TO_HW(vsi);
-       uint64_t ts_ns;
        struct ice_adapter *ad = rxq->vsi->adapter;
-#endif
 
-       if (rxq->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP)
-               rxq->hw_register_set = 1;
+       if (rxq->offloads & RTE_ETH_RX_OFFLOAD_TIMESTAMP) {
+               uint64_t sw_cur_time = rte_get_timer_cycles() / (rte_get_timer_hz() / 1000);
+
+               if (unlikely(sw_cur_time - ad->hw_time_update > 4))
+                       is_tsinit = 1;
+       }
+#endif
 
        while (nb_rx < nb_pkts) {
                rxdp = &rx_ring[rx_id];
@@ -2386,14 +2426,25 @@ ice_recv_pkts(void *rx_queue,
                pkt_flags = ice_rxd_error_to_pkt_flags(rx_stat_err0);
 #ifndef RTE_LIBRTE_ICE_16BYTE_RX_DESC
                if (ice_timestamp_dynflag > 0) {
-                       ts_ns = ice_tstamp_convert_32b_64b(hw, ad,
-                               rxq->hw_register_set,
-                               rte_le_to_cpu_32(rxd.wb.flex_ts.ts_high));
-                       rxq->hw_register_set = 0;
+                       rxq->time_high =
+                          rte_le_to_cpu_32(rxd.wb.flex_ts.ts_high);
+                       if (unlikely(is_tsinit)) {
+                               ts_ns = ice_tstamp_convert_32b_64b(hw, ad, 1, rxq->time_high);
+                               ad->hw_time_low = (uint32_t)ts_ns;
+                               ad->hw_time_high = (uint32_t)(ts_ns >> 32);
+                               is_tsinit = false;
+                       } else {
+                               if (rxq->time_high < ad->hw_time_low)
+                                       ad->hw_time_high += 1;
+                               ts_ns = (uint64_t)ad->hw_time_high << 32 | rxq->time_high;
+                               ad->hw_time_low = rxq->time_high;
+                       }
+                       ad->hw_time_update = rte_get_timer_cycles() /
+                                            (rte_get_timer_hz() / 1000);
                        *RTE_MBUF_DYNFIELD(rxm,
-                               ice_timestamp_dynfield_offset,
-                               rte_mbuf_timestamp_t *) = ts_ns;
-                       rxm->ol_flags |= ice_timestamp_dynflag;
+                                          (ice_timestamp_dynfield_offset),
+                                          rte_mbuf_timestamp_t *) = ts_ns;
+                       pkt_flags |= ice_timestamp_dynflag;
                }
 
                if (ad->ptp_ena && ((rxm->packet_type & RTE_PTYPE_L2_MASK) ==
@@ -2408,6 +2459,7 @@ ice_recv_pkts(void *rx_queue,
                /* copy old mbuf to rx_pkts */
                rx_pkts[nb_rx++] = rxm;
        }
+
        rxq->rx_tail = rx_id;
        /**
         * If the number of free RX descriptors is greater than the RX free