[dpdk-dev] [PATCH v2 3/3] net/mlx5: add hardware timestamp

Raslan Darawsheh rasland at mellanox.com
Thu Aug 24 09:46:33 CEST 2017


Expose a new capapilty of Rx hw timestamp and
added new device args to enable it hw_timestamp.
It will add the raw hw timestamp into the packets.

Its expected that it will lower down the performance since using it
will disable the cqe comprission, and will add extra checkes in
the vec rx path.

Signed-off-by: Raslan Darawsheh <rasland at mellanox.com>
---
 doc/guides/nics/mlx5.rst             |  5 +++++
 drivers/net/mlx5/mlx5.c              | 23 +++++++++++++++++++++++
 drivers/net/mlx5/mlx5.h              |  1 +
 drivers/net/mlx5/mlx5_ethdev.c       |  3 ++-
 drivers/net/mlx5/mlx5_rxq.c          |  3 +++
 drivers/net/mlx5/mlx5_rxtx.c         |  5 +++++
 drivers/net/mlx5/mlx5_rxtx.h         |  3 ++-
 drivers/net/mlx5/mlx5_rxtx_vec_sse.c | 13 ++++++++++++-
 8 files changed, 53 insertions(+), 3 deletions(-)

diff --git a/doc/guides/nics/mlx5.rst b/doc/guides/nics/mlx5.rst
index f4cb18b..7dbd844 100644
--- a/doc/guides/nics/mlx5.rst
+++ b/doc/guides/nics/mlx5.rst
@@ -268,6 +268,11 @@ Run-time configuration
 
   Enabled by default.
 
+- ``rx_timestamp`` parameter [int]
+
+ A nonzero value enables Rx timestamp.
+ When hw timestamp is enabled, packets will have raw hw timestamp.
+
 Prerequisites
 -------------
 
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index b7e5046..4b3a3ab 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -94,6 +94,9 @@
 /* Device parameter to enable hardware TSO offload. */
 #define MLX5_TSO "tso"
 
+/* Device parameter to enable hardware timestamp offload. */
+#define MLX5_RX_TIMESTAMP "rx_timestamp"
+
 /* Device parameter to enable hardware Tx vector. */
 #define MLX5_TX_VEC_EN "tx_vec_en"
 
@@ -113,6 +116,7 @@ struct mlx5_args {
 	int tso;
 	int tx_vec_en;
 	int rx_vec_en;
+	int hw_timestamp;
 };
 /**
  * Retrieve integer value from environment variable.
@@ -336,6 +340,8 @@ mlx5_args_check(const char *key, const char *val, void *opaque)
 		args->tx_vec_en = !!tmp;
 	} else if (strcmp(MLX5_RX_VEC_EN, key) == 0) {
 		args->rx_vec_en = !!tmp;
+	} else if (strcmp(MLX5_RX_TIMESTAMP, key) == 0) {
+		args->hw_timestamp = !!tmp;
 	} else {
 		WARN("%s: unknown parameter", key);
 		return -EINVAL;
@@ -367,6 +373,7 @@ mlx5_args(struct mlx5_args *args, struct rte_devargs *devargs)
 		MLX5_TSO,
 		MLX5_TX_VEC_EN,
 		MLX5_RX_VEC_EN,
+		MLX5_RX_TIMESTAMP,
 		NULL,
 	};
 	struct rte_kvargs *kvlist;
@@ -426,6 +433,8 @@ mlx5_args_assign(struct priv *priv, struct mlx5_args *args)
 		priv->tx_vec_en = args->tx_vec_en;
 	if (args->rx_vec_en != MLX5_ARG_UNSET)
 		priv->rx_vec_en = args->rx_vec_en;
+	if (args->hw_timestamp != MLX5_ARG_UNSET)
+		priv->hw_timestamp = args->hw_timestamp;
 }
 
 /**
@@ -573,6 +582,7 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 			.tso = MLX5_ARG_UNSET,
 			.tx_vec_en = MLX5_ARG_UNSET,
 			.rx_vec_en = MLX5_ARG_UNSET,
+			.hw_timestamp = MLX5_ARG_UNSET,
 		};
 
 		exp_device_attr.comp_mask =
@@ -581,6 +591,7 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 			IBV_EXP_DEVICE_ATTR_VLAN_OFFLOADS |
 			IBV_EXP_DEVICE_ATTR_RX_PAD_END_ALIGN |
 			IBV_EXP_DEVICE_ATTR_TSO_CAPS |
+			IBV_EXP_DEVICE_ATTR_WITH_TIMESTAMP_MASK |
 			0;
 
 		DEBUG("using port %u (%08" PRIx32 ")", port, test);
@@ -662,6 +673,18 @@ mlx5_pci_probe(struct rte_pci_driver *pci_drv, struct rte_pci_device *pci_dev)
 					 IBV_EXP_DEVICE_VXLAN_SUPPORT);
 		DEBUG("L2 tunnel checksum offloads are %ssupported",
 		      (priv->hw_csum_l2tun ? "" : "not "));
+		if (priv->hw_timestamp) {
+			priv->hw_timestamp =
+				(exp_device_attr.comp_mask |
+				 IBV_EXP_DEVICE_ATTR_WITH_TIMESTAMP_MASK);
+			DEBUG("Timestamping offload is %ssupported",
+			      (priv->hw_timestamp ? "" : "not "));
+			priv->cqe_comp = (priv->hw_timestamp ?
+					  0 : priv->cqe_comp);
+			DEBUG("%s",
+			      (priv->hw_timestamp ?
+			      "cqe compression is disabled" : ""));
+		}
 
 		priv->ind_table_max_size = exp_device_attr.rx_hash_caps.max_rwq_indirection_table_size;
 		/* Remove this check once DPDK supports larger/variable
diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h
index 43c5384..4d19351 100644
--- a/drivers/net/mlx5/mlx5.h
+++ b/drivers/net/mlx5/mlx5.h
@@ -120,6 +120,7 @@ struct priv {
 	unsigned int allmulti_req:1; /* All multicast mode requested. */
 	unsigned int hw_csum:1; /* Checksum offload is supported. */
 	unsigned int hw_csum_l2tun:1; /* Same for L2 tunnels. */
+	unsigned int hw_timestamp:1; /* rx timestamp offload is supported. */
 	unsigned int hw_vlan_strip:1; /* VLAN stripping is supported. */
 	unsigned int hw_fcs_strip:1; /* FCS stripping is supported. */
 	unsigned int hw_padding:1; /* End alignment padding is supported. */
diff --git a/drivers/net/mlx5/mlx5_ethdev.c b/drivers/net/mlx5/mlx5_ethdev.c
index b0eb3cd..1942de7 100644
--- a/drivers/net/mlx5/mlx5_ethdev.c
+++ b/drivers/net/mlx5/mlx5_ethdev.c
@@ -686,7 +686,8 @@ mlx5_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
 		  DEV_RX_OFFLOAD_UDP_CKSUM |
 		  DEV_RX_OFFLOAD_TCP_CKSUM) :
 		 0) |
-		(priv->hw_vlan_strip ? DEV_RX_OFFLOAD_VLAN_STRIP : 0);
+		(priv->hw_vlan_strip ? DEV_RX_OFFLOAD_VLAN_STRIP : 0) |
+		(priv->hw_timestamp ? DEV_RX_OFFLOAD_TIMESTAMP : 0);
 	if (!priv->mps)
 		info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT;
 	if (priv->hw_csum)
diff --git a/drivers/net/mlx5/mlx5_rxq.c b/drivers/net/mlx5/mlx5_rxq.c
index 74387a7..c8ccde2 100644
--- a/drivers/net/mlx5/mlx5_rxq.c
+++ b/drivers/net/mlx5/mlx5_rxq.c
@@ -929,6 +929,7 @@ rxq_ctrl_setup(struct rte_eth_dev *dev, struct rxq_ctrl *rxq_ctrl,
 	if (priv->hw_csum_l2tun)
 		tmpl.rxq.csum_l2tun =
 			!!dev->data->dev_conf.rxmode.hw_ip_checksum;
+	tmpl.rxq.timestamp = priv->hw_timestamp;
 	/* Use the entire RX mempool as the memory region. */
 	tmpl.mr = mlx5_mp2mr(priv->pd, mp);
 	if (tmpl.mr == NULL) {
@@ -950,6 +951,8 @@ rxq_ctrl_setup(struct rte_eth_dev *dev, struct rxq_ctrl *rxq_ctrl,
 	attr.cq = (struct ibv_exp_cq_init_attr){
 		.comp_mask = 0,
 	};
+	if (priv->hw_timestamp)
+		attr.cq.flags |= IBV_EXP_CQ_TIMESTAMP;
 	if (priv->cqe_comp) {
 		attr.cq.comp_mask |= IBV_EXP_CQ_INIT_ATTR_FLAGS;
 		attr.cq.flags |= IBV_EXP_CQ_COMPRESSED_CQE;
diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index b07bcd1..47344f2 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -1865,6 +1865,11 @@ mlx5_rx_burst(void *dpdk_rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
 					PKT_RX_VLAN_STRIPPED;
 				pkt->vlan_tci = ntohs(cqe->vlan_info);
 			}
+			if (rxq->timestamp) {
+				pkt->timestamp =
+					rte_be_to_cpu_64(cqe->timestamp);
+				pkt->ol_flags |= PKT_RX_TIMESTAMP;
+			}
 			if (rxq->crc_present)
 				len -= ETHER_CRC_LEN;
 			PKT_LEN(pkt) = len;
diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h
index 7de1d10..05d750b 100644
--- a/drivers/net/mlx5/mlx5_rxtx.h
+++ b/drivers/net/mlx5/mlx5_rxtx.h
@@ -107,6 +107,7 @@ struct rxq_zip {
 struct rxq {
 	unsigned int csum:1; /* Enable checksum offloading. */
 	unsigned int csum_l2tun:1; /* Same for L2 tunnels. */
+	unsigned int timestamp:1; /* Enable timestamp offloading. */
 	unsigned int vlan_strip:1; /* Enable VLAN stripping. */
 	unsigned int crc_present:1; /* CRC must be subtracted. */
 	unsigned int sges_n:2; /* Log 2 of SGEs (max buffers per packet). */
@@ -117,7 +118,7 @@ struct rxq {
 	unsigned int mark:1; /* Marked flow available on the queue. */
 	unsigned int pending_err:1; /* CQE error needs to be handled. */
 	unsigned int trim_elts:1; /* Whether elts needs clean-up. */
-	unsigned int :6; /* Remaining bits. */
+	unsigned int :5; /* Remaining bits. */
 	volatile uint32_t *rq_db;
 	volatile uint32_t *cq_db;
 	uint16_t rq_ci;
diff --git a/drivers/net/mlx5/mlx5_rxtx_vec_sse.c b/drivers/net/mlx5/mlx5_rxtx_vec_sse.c
index 8560f74..8b25578 100644
--- a/drivers/net/mlx5/mlx5_rxtx_vec_sse.c
+++ b/drivers/net/mlx5/mlx5_rxtx_vec_sse.c
@@ -752,7 +752,8 @@ rxq_cq_to_ptype_oflags_v(struct rxq *rxq, __m128i cqes[4], __m128i op_err,
 {
 	__m128i pinfo0, pinfo1;
 	__m128i pinfo, ptype;
-	__m128i ol_flags = _mm_set1_epi32(rxq->rss_hash * PKT_RX_RSS_HASH);
+	__m128i ol_flags = _mm_set1_epi32(rxq->rss_hash * PKT_RX_RSS_HASH |
+					  rxq->timestamp * PKT_RX_TIMESTAMP);
 	__m128i cv_flags;
 	const __m128i zero = _mm_setzero_si128();
 	const __m128i ptype_mask =
@@ -1214,6 +1215,16 @@ rxq_burst_v(struct rxq *rxq, struct rte_mbuf **pkts, uint16_t pkts_n)
 		rxq->pending_err |= !!_mm_cvtsi128_si64(opcode);
 		/* D.5 fill in mbuf - rearm_data and packet_type. */
 		rxq_cq_to_ptype_oflags_v(rxq, cqes, opcode, &pkts[pos]);
+		if (rxq->timestamp) {
+			pkts[pos]->timestamp =
+				rte_be_to_cpu_64(cq[pos].timestamp);
+			pkts[pos + 1]->timestamp =
+				rte_be_to_cpu_64(cq[pos + 1].timestamp);
+			pkts[pos + 2]->timestamp =
+				rte_be_to_cpu_64(cq[pos + 2].timestamp);
+			pkts[pos + 3]->timestamp =
+				rte_be_to_cpu_64(cq[pos + 3].timestamp);
+		}
 #ifdef MLX5_PMD_SOFT_COUNTERS
 		/* Add up received bytes count. */
 		byte_cnt = _mm_shuffle_epi8(op_own, len_shuf_mask);
-- 
2.7.4



More information about the dev mailing list