@@ -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
-------------
@@ -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
@@ -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. */
@@ -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)
@@ -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;
@@ -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;
@@ -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;
@@ -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);