* [dpdk-dev] [PATCH 1/6] ethdev: add descriptor status API
2017-03-01 17:19 ` [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors Olivier Matz
@ 2017-03-01 17:19 ` Olivier Matz
2017-03-01 18:22 ` Andrew Rybchenko
2017-03-01 17:19 ` [dpdk-dev] [PATCH 2/6] net/ixgbe: implement " Olivier Matz
` (8 subsequent siblings)
9 siblings, 1 reply; 72+ messages in thread
From: Olivier Matz @ 2017-03-01 17:19 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson
Introduce a new API to get the status of a descriptor.
For Rx, it is almost similar to rx_descriptor_done API, except it
differentiates "used" descriptors (which are hold by the driver and not
returned to the hardware).
For Tx, it is a new API.
The descriptor_done() API, and probably the rx_queue_count() API could
be replaced by this new API as soon as it is implemented on all PMDs.
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
lib/librte_ether/rte_ethdev.h | 86 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 97f3e2d..9ac9c61 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1179,6 +1179,14 @@ typedef uint32_t (*eth_rx_queue_count_t)(struct rte_eth_dev *dev,
typedef int (*eth_rx_descriptor_done_t)(void *rxq, uint16_t offset);
/**< @internal Check DD bit of specific RX descriptor */
+typedef int (*eth_rx_descriptor_status_t)(struct rte_eth_dev *dev,
+ uint16_t rx_queue_id, uint16_t offset);
+/**< @internal Check the status of a Rx descriptor */
+
+typedef int (*eth_tx_descriptor_status_t)(struct rte_eth_dev *dev,
+ uint16_t tx_queue_id, uint16_t offset);
+/**< @internal Check the status of a Tx descriptor */
+
typedef int (*eth_fw_version_get_t)(struct rte_eth_dev *dev,
char *fw_version, size_t fw_size);
/**< @internal Get firmware information of an Ethernet device. */
@@ -1483,6 +1491,10 @@ struct eth_dev_ops {
eth_queue_release_t rx_queue_release; /**< Release RX queue. */
eth_rx_queue_count_t rx_queue_count;/**< Get Rx queue count. */
eth_rx_descriptor_done_t rx_descriptor_done; /**< Check rxd DD bit. */
+ eth_rx_descriptor_status_t rx_descriptor_status;
+ /**< Check the status of a Rx descriptor. */
+ eth_tx_descriptor_status_t tx_descriptor_status;
+ /**< Check the status of a Tx descriptor. */
eth_rx_enable_intr_t rx_queue_intr_enable; /**< Enable Rx queue interrupt. */
eth_rx_disable_intr_t rx_queue_intr_disable; /**< Disable Rx queue interrupt. */
eth_tx_queue_setup_t tx_queue_setup;/**< Set up device TX queue. */
@@ -2768,6 +2780,80 @@ rte_eth_rx_descriptor_done(uint8_t port_id, uint16_t queue_id, uint16_t offset)
dev->data->rx_queues[queue_id], offset);
}
+#define RTE_ETH_RX_DESC_AVAIL 0 /**< Desc available for hw. */
+#define RTE_ETH_RX_DESC_DONE 1 /**< Desc done, filled by hw. */
+#define RTE_ETH_RX_DESC_USED 2 /**< Desc used by driver. */
+
+/**
+ * Check the status of a Rx descriptor in the queue
+ *
+ * @param port_id
+ * The port identifier of the Ethernet device.
+ * @param queue_id
+ * The Rx queue identifier on this port.
+ * @param offset
+ * The offset of the descriptor starting from tail (0 is the next
+ * packet to be received by the driver).
+ *
+ * @return
+ * - (RTE_ETH_DESC_AVAIL): Descriptor is available for the hardware to
+ * receive a packet.
+ * - (RTE_ETH_DESC_DONE): Descriptor is done, it is filled by hw, but
+ * not yet processed by the driver (i.e. in the receive queue).
+ * - (RTE_ETH_DESC_USED): Descriptor is unavailable (hold by driver,
+ * not yet returned to hw).
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-EINVAL) bad descriptor offset.
+ * - (-ENOTSUP) if the device does not support this function.
+ */
+static inline int
+rte_eth_rx_descriptor_status(uint8_t port_id, uint16_t queue_id,
+ uint16_t offset)
+{
+ struct rte_eth_dev *dev;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+ dev = &rte_eth_devices[port_id];
+ RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_descriptor_status, -ENOTSUP);
+
+ return (*dev->dev_ops->rx_descriptor_status)(dev, queue_id, offset);
+}
+
+#define RTE_ETH_TX_DESC_FULL 0 /**< Desc filled by pmd for hw, waiting xmit. */
+#define RTE_ETH_TX_DESC_DONE 1 /**< Desc done, packet is transmitted. */
+
+/**
+ * Check the status of a Tx descriptor in the queue.
+ *
+ * @param port_id
+ * The port identifier of the Ethernet device.
+ * @param queue_id
+ * The Tx queue identifier on this port.
+ * @param offset
+ * The offset of the descriptor starting from tail (0 is the place where
+ * the next packet will be send).
+ *
+ * @return
+ * - (RTE_ETH_DESC_FULL) Descriptor is being processed by the hw, i.e.
+ * in the transmit queue.
+ * - (RTE_ETH_DESC_DONE) Hardware is done with this descriptor, it can be
+ * reused by the driver.
+ * - (-ENODEV) if *port_id* invalid.
+ * - (-EINVAL) bad descriptor offset.
+ * - (-ENOTSUP) if the device does not support this function.
+ */
+static inline int rte_eth_tx_descriptor_status(uint8_t port_id,
+ uint16_t queue_id, uint16_t offset)
+{
+ struct rte_eth_dev *dev;
+
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+ dev = &rte_eth_devices[port_id];
+ RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_descriptor_status, -ENOTSUP);
+
+ return (*dev->dev_ops->tx_descriptor_status)(dev, queue_id, offset);
+}
+
/**
* Send a burst of output packets on a transmit queue of an Ethernet device.
*
--
2.8.1
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 1/6] ethdev: add descriptor status API
2017-03-01 17:19 ` [dpdk-dev] [PATCH 1/6] ethdev: add descriptor status API Olivier Matz
@ 2017-03-01 18:22 ` Andrew Rybchenko
2017-03-02 13:57 ` Olivier Matz
0 siblings, 1 reply; 72+ messages in thread
From: Andrew Rybchenko @ 2017-03-01 18:22 UTC (permalink / raw)
To: Olivier Matz, dev, thomas.monjalon, konstantin.ananyev,
wenzhuo.lu, helin.zhang, jingjing.wu, adrien.mazarguil,
nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson
On 03/01/2017 08:19 PM, Olivier Matz wrote:
> Introduce a new API to get the status of a descriptor.
>
> For Rx, it is almost similar to rx_descriptor_done API, except it
> differentiates "used" descriptors (which are hold by the driver and not
> returned to the hardware).
>
> For Tx, it is a new API.
>
> The descriptor_done() API, and probably the rx_queue_count() API could
> be replaced by this new API as soon as it is implemented on all PMDs.
>
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> ---
> lib/librte_ether/rte_ethdev.h | 86 +++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 86 insertions(+)
>
> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> index 97f3e2d..9ac9c61 100644
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -1179,6 +1179,14 @@ typedef uint32_t (*eth_rx_queue_count_t)(struct rte_eth_dev *dev,
> typedef int (*eth_rx_descriptor_done_t)(void *rxq, uint16_t offset);
> /**< @internal Check DD bit of specific RX descriptor */
>
> +typedef int (*eth_rx_descriptor_status_t)(struct rte_eth_dev *dev,
> + uint16_t rx_queue_id, uint16_t offset);
> +/**< @internal Check the status of a Rx descriptor */
> +
> +typedef int (*eth_tx_descriptor_status_t)(struct rte_eth_dev *dev,
> + uint16_t tx_queue_id, uint16_t offset);
> +/**< @internal Check the status of a Tx descriptor */
> +
> typedef int (*eth_fw_version_get_t)(struct rte_eth_dev *dev,
> char *fw_version, size_t fw_size);
> /**< @internal Get firmware information of an Ethernet device. */
> @@ -1483,6 +1491,10 @@ struct eth_dev_ops {
> eth_queue_release_t rx_queue_release; /**< Release RX queue. */
> eth_rx_queue_count_t rx_queue_count;/**< Get Rx queue count. */
> eth_rx_descriptor_done_t rx_descriptor_done; /**< Check rxd DD bit. */
> + eth_rx_descriptor_status_t rx_descriptor_status;
> + /**< Check the status of a Rx descriptor. */
> + eth_tx_descriptor_status_t tx_descriptor_status;
> + /**< Check the status of a Tx descriptor. */
> eth_rx_enable_intr_t rx_queue_intr_enable; /**< Enable Rx queue interrupt. */
> eth_rx_disable_intr_t rx_queue_intr_disable; /**< Disable Rx queue interrupt. */
> eth_tx_queue_setup_t tx_queue_setup;/**< Set up device TX queue. */
> @@ -2768,6 +2780,80 @@ rte_eth_rx_descriptor_done(uint8_t port_id, uint16_t queue_id, uint16_t offset)
> dev->data->rx_queues[queue_id], offset);
> }
>
> +#define RTE_ETH_RX_DESC_AVAIL 0 /**< Desc available for hw. */
> +#define RTE_ETH_RX_DESC_DONE 1 /**< Desc done, filled by hw. */
> +#define RTE_ETH_RX_DESC_USED 2 /**< Desc used by driver. */
> +
> +/**
> + * Check the status of a Rx descriptor in the queue
I think it would be useful to highlight caller context.
Should it be the same CPU which receives packets from the queue?
> + *
> + * @param port_id
> + * The port identifier of the Ethernet device.
> + * @param queue_id
> + * The Rx queue identifier on this port.
> + * @param offset
> + * The offset of the descriptor starting from tail (0 is the next
> + * packet to be received by the driver).
> + * @return
> + * - (RTE_ETH_DESC_AVAIL): Descriptor is available for the hardware to
> + * receive a packet.
> + * - (RTE_ETH_DESC_DONE): Descriptor is done, it is filled by hw, but
> + * not yet processed by the driver (i.e. in the receive queue).
> + * - (RTE_ETH_DESC_USED): Descriptor is unavailable (hold by driver,
> + * not yet returned to hw).
It looks like it is the most suitable for descriptors which are reserved
and never used.
> + * - (-ENODEV) if *port_id* invalid.
> + * - (-EINVAL) bad descriptor offset.
> + * - (-ENOTSUP) if the device does not support this function.
What should be returned if queue_id is invalid?
What should be returned if the queue is stopped?
> + */
> +static inline int
> +rte_eth_rx_descriptor_status(uint8_t port_id, uint16_t queue_id,
> + uint16_t offset)
> +{
> + struct rte_eth_dev *dev;
> +
> + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> + dev = &rte_eth_devices[port_id];
> + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_descriptor_status, -ENOTSUP);
> +
May be it makes sense to range check queue_id here to avoid such code in
each PMD?
> + return (*dev->dev_ops->rx_descriptor_status)(dev, queue_id, offset);
> +}
> +
> +#define RTE_ETH_TX_DESC_FULL 0 /**< Desc filled by pmd for hw, waiting xmit. */
> +#define RTE_ETH_TX_DESC_DONE 1 /**< Desc done, packet is transmitted. */
I see no value suitable for descriptor which is never used.
> +/**
> + * Check the status of a Tx descriptor in the queue.
> + *
> + * @param port_id
> + * The port identifier of the Ethernet device.
> + * @param queue_id
> + * The Tx queue identifier on this port.
> + * @param offset
> + * The offset of the descriptor starting from tail (0 is the place where
> + * the next packet will be send).
> + *
> + * @return
> + * - (RTE_ETH_DESC_FULL) Descriptor is being processed by the hw, i.e.
> + * in the transmit queue.
> + * - (RTE_ETH_DESC_DONE) Hardware is done with this descriptor, it can be
> + * reused by the driver.
> + * - (-ENODEV) if *port_id* invalid.
> + * - (-EINVAL) bad descriptor offset.
> + * - (-ENOTSUP) if the device does not support this function.
> + */
> +static inline int rte_eth_tx_descriptor_status(uint8_t port_id,
> + uint16_t queue_id, uint16_t offset)
> +{
> + struct rte_eth_dev *dev;
> +
> + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> + dev = &rte_eth_devices[port_id];
> + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_descriptor_status, -ENOTSUP);
> +
> + return (*dev->dev_ops->tx_descriptor_status)(dev, queue_id, offset);
> +}
> +
> /**
> * Send a burst of output packets on a transmit queue of an Ethernet device.
> *
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 1/6] ethdev: add descriptor status API
2017-03-01 18:22 ` Andrew Rybchenko
@ 2017-03-02 13:57 ` Olivier Matz
2017-03-02 14:19 ` Andrew Rybchenko
0 siblings, 1 reply; 72+ messages in thread
From: Olivier Matz @ 2017-03-02 13:57 UTC (permalink / raw)
To: Andrew Rybchenko
Cc: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro,
ferruh.yigit, bruce.richardson
Hi Andrew,
Thank you for the review. Comments inline.
On Wed, 1 Mar 2017 21:22:14 +0300, Andrew Rybchenko <arybchenko@solarflare.com> wrote:
> On 03/01/2017 08:19 PM, Olivier Matz wrote:
> > Introduce a new API to get the status of a descriptor.
> >
> > For Rx, it is almost similar to rx_descriptor_done API, except it
> > differentiates "used" descriptors (which are hold by the driver and not
> > returned to the hardware).
> >
> > For Tx, it is a new API.
> >
> > The descriptor_done() API, and probably the rx_queue_count() API could
> > be replaced by this new API as soon as it is implemented on all PMDs.
> >
> > Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> > ---
> > lib/librte_ether/rte_ethdev.h | 86 +++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 86 insertions(+)
> >
> > diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> > index 97f3e2d..9ac9c61 100644
> > --- a/lib/librte_ether/rte_ethdev.h
> > +++ b/lib/librte_ether/rte_ethdev.h
> > @@ -1179,6 +1179,14 @@ typedef uint32_t (*eth_rx_queue_count_t)(struct rte_eth_dev *dev,
> > typedef int (*eth_rx_descriptor_done_t)(void *rxq, uint16_t offset);
> > /**< @internal Check DD bit of specific RX descriptor */
> >
> > +typedef int (*eth_rx_descriptor_status_t)(struct rte_eth_dev *dev,
> > + uint16_t rx_queue_id, uint16_t offset);
> > +/**< @internal Check the status of a Rx descriptor */
> > +
> > +typedef int (*eth_tx_descriptor_status_t)(struct rte_eth_dev *dev,
> > + uint16_t tx_queue_id, uint16_t offset);
> > +/**< @internal Check the status of a Tx descriptor */
> > +
> > typedef int (*eth_fw_version_get_t)(struct rte_eth_dev *dev,
> > char *fw_version, size_t fw_size);
> > /**< @internal Get firmware information of an Ethernet device. */
> > @@ -1483,6 +1491,10 @@ struct eth_dev_ops {
> > eth_queue_release_t rx_queue_release; /**< Release RX queue. */
> > eth_rx_queue_count_t rx_queue_count;/**< Get Rx queue count. */
> > eth_rx_descriptor_done_t rx_descriptor_done; /**< Check rxd DD bit. */
> > + eth_rx_descriptor_status_t rx_descriptor_status;
> > + /**< Check the status of a Rx descriptor. */
> > + eth_tx_descriptor_status_t tx_descriptor_status;
> > + /**< Check the status of a Tx descriptor. */
> > eth_rx_enable_intr_t rx_queue_intr_enable; /**< Enable Rx queue interrupt. */
> > eth_rx_disable_intr_t rx_queue_intr_disable; /**< Disable Rx queue interrupt. */
> > eth_tx_queue_setup_t tx_queue_setup;/**< Set up device TX queue. */
> > @@ -2768,6 +2780,80 @@ rte_eth_rx_descriptor_done(uint8_t port_id, uint16_t queue_id, uint16_t offset)
> > dev->data->rx_queues[queue_id], offset);
> > }
> >
> > +#define RTE_ETH_RX_DESC_AVAIL 0 /**< Desc available for hw. */
> > +#define RTE_ETH_RX_DESC_DONE 1 /**< Desc done, filled by hw. */
> > +#define RTE_ETH_RX_DESC_USED 2 /**< Desc used by driver. */
> > +
> > +/**
> > + * Check the status of a Rx descriptor in the queue
>
> I think it would be useful to highlight caller context.
> Should it be the same CPU which receives packets from the queue?
Yes, you are right it would be useful. I suggest the following sentences:
This function should be called on a dataplane core like the
Rx function. They should not be called concurrently on the same
queue.
>
> > + *
> > + * @param port_id
> > + * The port identifier of the Ethernet device.
> > + * @param queue_id
> > + * The Rx queue identifier on this port.
> > + * @param offset
> > + * The offset of the descriptor starting from tail (0 is the next
> > + * packet to be received by the driver).
> > + * @return
> > + * - (RTE_ETH_DESC_AVAIL): Descriptor is available for the hardware to
> > + * receive a packet.
> > + * - (RTE_ETH_DESC_DONE): Descriptor is done, it is filled by hw, but
> > + * not yet processed by the driver (i.e. in the receive queue).
> > + * - (RTE_ETH_DESC_USED): Descriptor is unavailable (hold by driver,
> > + * not yet returned to hw).
>
> It looks like it is the most suitable for descriptors which are reserved
> and never used.
Can you give some more details about what is a reserved but never
used descriptor? (same question for Tx)
>
> > + * - (-ENODEV) if *port_id* invalid.
> > + * - (-EINVAL) bad descriptor offset.
> > + * - (-ENOTSUP) if the device does not support this function.
>
> What should be returned if queue_id is invalid?
I'd say -ENODEV too. On the other hand, adding these checks is
maybe not a good idea as we are in dataplane.
The previous API rx_descriptor_done() API was taking the queue
pointer as parameter, like Rx/Tx functions. It's probably a better
idea.
> What should be returned if the queue is stopped?
For the same performance reasons, I think we should just highlight
in the API that this dataplane function should not be called on a
stopped queue.
>
> > + */
> > +static inline int
> > +rte_eth_rx_descriptor_status(uint8_t port_id, uint16_t queue_id,
> > + uint16_t offset)
> > +{
> > + struct rte_eth_dev *dev;
> > +
> > + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> > + dev = &rte_eth_devices[port_id];
> > + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_descriptor_status, -ENOTSUP);
> > +
>
> May be it makes sense to range check queue_id here to avoid such code in
> each PMD?
If we keep this API, yes. If we switch to a queue pointer as proposed
above, we will assume (and highlight in the API doc) that the pointer
must be valid, like for Rx/Tx funcs.
Olivier
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 1/6] ethdev: add descriptor status API
2017-03-02 13:57 ` Olivier Matz
@ 2017-03-02 14:19 ` Andrew Rybchenko
2017-03-02 14:54 ` Olivier Matz
0 siblings, 1 reply; 72+ messages in thread
From: Andrew Rybchenko @ 2017-03-02 14:19 UTC (permalink / raw)
To: Olivier Matz
Cc: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro,
ferruh.yigit, bruce.richardson
Hi Olivier,
On 03/02/2017 04:57 PM, Olivier Matz wrote:
> Hi Andrew,
>
> Thank you for the review. Comments inline.
>
> On Wed, 1 Mar 2017 21:22:14 +0300, Andrew Rybchenko <arybchenko@solarflare.com> wrote:
>> On 03/01/2017 08:19 PM, Olivier Matz wrote:
>>> Introduce a new API to get the status of a descriptor.
>>>
>>> For Rx, it is almost similar to rx_descriptor_done API, except it
>>> differentiates "used" descriptors (which are hold by the driver and not
>>> returned to the hardware).
>>>
>>> For Tx, it is a new API.
>>>
>>> The descriptor_done() API, and probably the rx_queue_count() API could
>>> be replaced by this new API as soon as it is implemented on all PMDs.
>>>
>>> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
>>> ---
>>> lib/librte_ether/rte_ethdev.h | 86 +++++++++++++++++++++++++++++++++++++++++++
>>> 1 file changed, 86 insertions(+)
>>>
>>> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
>>> index 97f3e2d..9ac9c61 100644
>>> --- a/lib/librte_ether/rte_ethdev.h
>>> +++ b/lib/librte_ether/rte_ethdev.h
>>> @@ -1179,6 +1179,14 @@ typedef uint32_t (*eth_rx_queue_count_t)(struct rte_eth_dev *dev,
>>> typedef int (*eth_rx_descriptor_done_t)(void *rxq, uint16_t offset);
>>> /**< @internal Check DD bit of specific RX descriptor */
>>>
>>> +typedef int (*eth_rx_descriptor_status_t)(struct rte_eth_dev *dev,
>>> + uint16_t rx_queue_id, uint16_t offset);
>>> +/**< @internal Check the status of a Rx descriptor */
>>> +
>>> +typedef int (*eth_tx_descriptor_status_t)(struct rte_eth_dev *dev,
>>> + uint16_t tx_queue_id, uint16_t offset);
>>> +/**< @internal Check the status of a Tx descriptor */
>>> +
>>> typedef int (*eth_fw_version_get_t)(struct rte_eth_dev *dev,
>>> char *fw_version, size_t fw_size);
>>> /**< @internal Get firmware information of an Ethernet device. */
>>> @@ -1483,6 +1491,10 @@ struct eth_dev_ops {
>>> eth_queue_release_t rx_queue_release; /**< Release RX queue. */
>>> eth_rx_queue_count_t rx_queue_count;/**< Get Rx queue count. */
>>> eth_rx_descriptor_done_t rx_descriptor_done; /**< Check rxd DD bit. */
>>> + eth_rx_descriptor_status_t rx_descriptor_status;
>>> + /**< Check the status of a Rx descriptor. */
>>> + eth_tx_descriptor_status_t tx_descriptor_status;
>>> + /**< Check the status of a Tx descriptor. */
>>> eth_rx_enable_intr_t rx_queue_intr_enable; /**< Enable Rx queue interrupt. */
>>> eth_rx_disable_intr_t rx_queue_intr_disable; /**< Disable Rx queue interrupt. */
>>> eth_tx_queue_setup_t tx_queue_setup;/**< Set up device TX queue. */
>>> @@ -2768,6 +2780,80 @@ rte_eth_rx_descriptor_done(uint8_t port_id, uint16_t queue_id, uint16_t offset)
>>> dev->data->rx_queues[queue_id], offset);
>>> }
>>>
>>> +#define RTE_ETH_RX_DESC_AVAIL 0 /**< Desc available for hw. */
>>> +#define RTE_ETH_RX_DESC_DONE 1 /**< Desc done, filled by hw. */
>>> +#define RTE_ETH_RX_DESC_USED 2 /**< Desc used by driver. */
>>> +
>>> +/**
>>> + * Check the status of a Rx descriptor in the queue
>> I think it would be useful to highlight caller context.
>> Should it be the same CPU which receives packets from the queue?
> Yes, you are right it would be useful. I suggest the following sentences:
>
> This function should be called on a dataplane core like the
> Rx function. They should not be called concurrently on the same
> queue.
The first sentence looks fine. "They" (functions?, dataplane cores?) is
unclear for me in the second. May be the first one is simply sufficient.
>>> + *
>>> + * @param port_id
>>> + * The port identifier of the Ethernet device.
>>> + * @param queue_id
>>> + * The Rx queue identifier on this port.
>>> + * @param offset
>>> + * The offset of the descriptor starting from tail (0 is the next
>>> + * packet to be received by the driver).
>>> + * @return
>>> + * - (RTE_ETH_DESC_AVAIL): Descriptor is available for the hardware to
>>> + * receive a packet.
>>> + * - (RTE_ETH_DESC_DONE): Descriptor is done, it is filled by hw, but
>>> + * not yet processed by the driver (i.e. in the receive queue).
>>> + * - (RTE_ETH_DESC_USED): Descriptor is unavailable (hold by driver,
>>> + * not yet returned to hw).
>> It looks like it is the most suitable for descriptors which are reserved
>> and never used.
> Can you give some more details about what is a reserved but never
> used descriptor? (same question for Tx)
Our HW has a requirement to keep few descriptors always unused (i.e.
some gap between tail and head). It is just a few descriptors, but
invalid descriptor status may misguide application. E.g. if Rx queue
size is 512 and offset 510, it will always be unused (since it is
reserved). It is not an indication that core is too slow and can't keep
the pace.
>>> + * - (-ENODEV) if *port_id* invalid.
>>> + * - (-EINVAL) bad descriptor offset.
>>> + * - (-ENOTSUP) if the device does not support this function.
>> What should be returned if queue_id is invalid?
> I'd say -ENODEV too. On the other hand, adding these checks is
> maybe not a good idea as we are in dataplane.
>
> The previous API rx_descriptor_done() API was taking the queue
> pointer as parameter, like Rx/Tx functions. It's probably a better
> idea.
I think so too since Rx burst callback (used nearby as above descriptor
says) gets queue pointer.
>> What should be returned if the queue is stopped?
> For the same performance reasons, I think we should just highlight
> in the API that this dataplane function should not be called on a
> stopped queue.
OK.
>>> + */
>>> +static inline int
>>> +rte_eth_rx_descriptor_status(uint8_t port_id, uint16_t queue_id,
>>> + uint16_t offset)
>>> +{
>>> + struct rte_eth_dev *dev;
>>> +
>>> + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
>>> + dev = &rte_eth_devices[port_id];
>>> + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_descriptor_status, -ENOTSUP);
>>> +
>> May be it makes sense to range check queue_id here to avoid such code in
>> each PMD?
> If we keep this API, yes. If we switch to a queue pointer as proposed
> above, we will assume (and highlight in the API doc) that the pointer
> must be valid, like for Rx/Tx funcs.
I've simply seen patches which add the queue id range check in the
generic place.
But I think switching to queue pointer is a better idea.
Thanks,
Andrew.
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 1/6] ethdev: add descriptor status API
2017-03-02 14:19 ` Andrew Rybchenko
@ 2017-03-02 14:54 ` Olivier Matz
2017-03-02 15:05 ` Andrew Rybchenko
0 siblings, 1 reply; 72+ messages in thread
From: Olivier Matz @ 2017-03-02 14:54 UTC (permalink / raw)
To: Andrew Rybchenko
Cc: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro,
ferruh.yigit, bruce.richardson
> >>> + * Check the status of a Rx descriptor in the queue
> >> I think it would be useful to highlight caller context.
> >> Should it be the same CPU which receives packets from the queue?
> > Yes, you are right it would be useful. I suggest the following sentences:
> >
> > This function should be called on a dataplane core like the
> > Rx function. They should not be called concurrently on the same
> > queue.
>
> The first sentence looks fine. "They" (functions?, dataplane cores?) is
> unclear for me in the second. May be the first one is simply sufficient.
Ok, I'll keep the first one at least, and see if I can reword the
second one to make it clear.
> >>> + *
> >>> + * @param port_id
> >>> + * The port identifier of the Ethernet device.
> >>> + * @param queue_id
> >>> + * The Rx queue identifier on this port.
> >>> + * @param offset
> >>> + * The offset of the descriptor starting from tail (0 is the next
> >>> + * packet to be received by the driver).
> >>> + * @return
> >>> + * - (RTE_ETH_DESC_AVAIL): Descriptor is available for the hardware to
> >>> + * receive a packet.
> >>> + * - (RTE_ETH_DESC_DONE): Descriptor is done, it is filled by hw, but
> >>> + * not yet processed by the driver (i.e. in the receive queue).
> >>> + * - (RTE_ETH_DESC_USED): Descriptor is unavailable (hold by driver,
> >>> + * not yet returned to hw).
> >> It looks like it is the most suitable for descriptors which are reserved
> >> and never used.
> > Can you give some more details about what is a reserved but never
> > used descriptor? (same question for Tx)
>
> Our HW has a requirement to keep few descriptors always unused (i.e.
> some gap between tail and head). It is just a few descriptors, but
> invalid descriptor status may misguide application. E.g. if Rx queue
> size is 512 and offset 510, it will always be unused (since it is
> reserved). It is not an indication that core is too slow and can't keep
> the pace.
Understood.
I can change _USED into _UNAVAIL (add it for Tx), with the following
description:
- (RTE_ETH_DESC_UNAVAIL): Descriptor is unavailable: either hold by driver
and not yet returned to hw, or reserved by the hardware.
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 1/6] ethdev: add descriptor status API
2017-03-02 14:54 ` Olivier Matz
@ 2017-03-02 15:05 ` Andrew Rybchenko
2017-03-02 15:14 ` Olivier Matz
0 siblings, 1 reply; 72+ messages in thread
From: Andrew Rybchenko @ 2017-03-02 15:05 UTC (permalink / raw)
To: Olivier Matz, Andrew Rybchenko
Cc: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro,
ferruh.yigit, bruce.richardson
On 03/02/2017 05:54 PM, Olivier Matz wrote:
>>>>> + *
>>>>> + * @param port_id
>>>>> + * The port identifier of the Ethernet device.
>>>>> + * @param queue_id
>>>>> + * The Rx queue identifier on this port.
>>>>> + * @param offset
>>>>> + * The offset of the descriptor starting from tail (0 is the next
>>>>> + * packet to be received by the driver).
>>>>> + * @return
>>>>> + * - (RTE_ETH_DESC_AVAIL): Descriptor is available for the hardware to
>>>>> + * receive a packet.
>>>>> + * - (RTE_ETH_DESC_DONE): Descriptor is done, it is filled by hw, but
>>>>> + * not yet processed by the driver (i.e. in the receive queue).
>>>>> + * - (RTE_ETH_DESC_USED): Descriptor is unavailable (hold by driver,
>>>>> + * not yet returned to hw).
>>>> It looks like it is the most suitable for descriptors which are reserved
>>>> and never used.
>>> Can you give some more details about what is a reserved but never
>>> used descriptor? (same question for Tx)
>> Our HW has a requirement to keep few descriptors always unused (i.e.
>> some gap between tail and head). It is just a few descriptors, but
>> invalid descriptor status may misguide application. E.g. if Rx queue
>> size is 512 and offset 510, it will always be unused (since it is
>> reserved). It is not an indication that core is too slow and can't keep
>> the pace.
> Understood.
>
> I can change _USED into _UNAVAIL (add it for Tx), with the following
> description:
>
> - (RTE_ETH_DESC_UNAVAIL): Descriptor is unavailable: either hold by driver
> and not yet returned to hw, or reserved by the hardware.
Looks good. Do I understand correctly that it will be reported for
descriptors which are not refilled (posted to HW) because of rx_free_thresh?
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 1/6] ethdev: add descriptor status API
2017-03-02 15:05 ` Andrew Rybchenko
@ 2017-03-02 15:14 ` Olivier Matz
0 siblings, 0 replies; 72+ messages in thread
From: Olivier Matz @ 2017-03-02 15:14 UTC (permalink / raw)
To: Andrew Rybchenko
Cc: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro,
ferruh.yigit, bruce.richardson
On Thu, 2 Mar 2017 18:05:52 +0300, Andrew Rybchenko <arybchenko@solarflare.com> wrote:
> On 03/02/2017 05:54 PM, Olivier Matz wrote:
> >>>>> + *
> >>>>> + * @param port_id
> >>>>> + * The port identifier of the Ethernet device.
> >>>>> + * @param queue_id
> >>>>> + * The Rx queue identifier on this port.
> >>>>> + * @param offset
> >>>>> + * The offset of the descriptor starting from tail (0 is the next
> >>>>> + * packet to be received by the driver).
> >>>>> + * @return
> >>>>> + * - (RTE_ETH_DESC_AVAIL): Descriptor is available for the hardware to
> >>>>> + * receive a packet.
> >>>>> + * - (RTE_ETH_DESC_DONE): Descriptor is done, it is filled by hw, but
> >>>>> + * not yet processed by the driver (i.e. in the receive queue).
> >>>>> + * - (RTE_ETH_DESC_USED): Descriptor is unavailable (hold by driver,
> >>>>> + * not yet returned to hw).
> >>>> It looks like it is the most suitable for descriptors which are reserved
> >>>> and never used.
> >>> Can you give some more details about what is a reserved but never
> >>> used descriptor? (same question for Tx)
> >> Our HW has a requirement to keep few descriptors always unused (i.e.
> >> some gap between tail and head). It is just a few descriptors, but
> >> invalid descriptor status may misguide application. E.g. if Rx queue
> >> size is 512 and offset 510, it will always be unused (since it is
> >> reserved). It is not an indication that core is too slow and can't keep
> >> the pace.
> > Understood.
> >
> > I can change _USED into _UNAVAIL (add it for Tx), with the following
> > description:
> >
> > - (RTE_ETH_DESC_UNAVAIL): Descriptor is unavailable: either hold by driver
> > and not yet returned to hw, or reserved by the hardware.
>
> Looks good. Do I understand correctly that it will be reported for
> descriptors which are not refilled (posted to HW) because of rx_free_thresh?
>
Yes
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH 2/6] net/ixgbe: implement descriptor status API
2017-03-01 17:19 ` [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors Olivier Matz
2017-03-01 17:19 ` [dpdk-dev] [PATCH 1/6] ethdev: add descriptor status API Olivier Matz
@ 2017-03-01 17:19 ` Olivier Matz
2017-03-01 17:19 ` [dpdk-dev] [PATCH 3/6] net/e1000: implement descriptor status API (igb) Olivier Matz
` (7 subsequent siblings)
9 siblings, 0 replies; 72+ messages in thread
From: Olivier Matz @ 2017-03-01 17:19 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
drivers/net/ixgbe/ixgbe_ethdev.c | 4 +++
drivers/net/ixgbe/ixgbe_ethdev.h | 5 ++++
drivers/net/ixgbe/ixgbe_rxtx.c | 55 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 64 insertions(+)
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 7169007..34bd681 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -554,6 +554,8 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
.rx_queue_release = ixgbe_dev_rx_queue_release,
.rx_queue_count = ixgbe_dev_rx_queue_count,
.rx_descriptor_done = ixgbe_dev_rx_descriptor_done,
+ .rx_descriptor_status = ixgbe_dev_rx_descriptor_status,
+ .tx_descriptor_status = ixgbe_dev_tx_descriptor_status,
.tx_queue_setup = ixgbe_dev_tx_queue_setup,
.tx_queue_release = ixgbe_dev_tx_queue_release,
.dev_led_on = ixgbe_dev_led_on,
@@ -632,6 +634,8 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops = {
.rx_queue_setup = ixgbe_dev_rx_queue_setup,
.rx_queue_release = ixgbe_dev_rx_queue_release,
.rx_descriptor_done = ixgbe_dev_rx_descriptor_done,
+ .rx_descriptor_status = ixgbe_dev_rx_descriptor_status,
+ .tx_descriptor_status = ixgbe_dev_tx_descriptor_status,
.tx_queue_setup = ixgbe_dev_tx_queue_setup,
.tx_queue_release = ixgbe_dev_tx_queue_release,
.rx_queue_intr_enable = ixgbevf_dev_rx_queue_intr_enable,
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index 680d5d9..085e598 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -516,6 +516,11 @@ uint32_t ixgbe_dev_rx_queue_count(struct rte_eth_dev *dev,
int ixgbe_dev_rx_descriptor_done(void *rx_queue, uint16_t offset);
int ixgbevf_dev_rx_descriptor_done(void *rx_queue, uint16_t offset);
+int ixgbe_dev_rx_descriptor_status(struct rte_eth_dev *dev,
+ uint16_t rx_queue_id, uint16_t offset);
+int ixgbe_dev_tx_descriptor_status(struct rte_eth_dev *dev,
+ uint16_t tx_queue_id, uint16_t offset);
+
int ixgbe_dev_rx_init(struct rte_eth_dev *dev);
void ixgbe_dev_tx_init(struct rte_eth_dev *dev);
diff --git a/drivers/net/ixgbe/ixgbe_rxtx.c b/drivers/net/ixgbe/ixgbe_rxtx.c
index 9502432..0826a45 100644
--- a/drivers/net/ixgbe/ixgbe_rxtx.c
+++ b/drivers/net/ixgbe/ixgbe_rxtx.c
@@ -2950,6 +2950,61 @@ ixgbe_dev_rx_descriptor_done(void *rx_queue, uint16_t offset)
rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD));
}
+int
+ixgbe_dev_rx_descriptor_status(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+ uint16_t offset)
+{
+ volatile uint32_t *status;
+ struct ixgbe_rx_queue *rxq;
+ uint32_t nb_hold, desc;
+
+ rxq = dev->data->rx_queues[rx_queue_id];
+ if (unlikely(offset >= rxq->nb_rx_desc))
+ return -EINVAL;
+
+#ifdef RTE_IXGBE_INC_VECTOR
+ if (rxq->rx_using_sse)
+ nb_hold = rxq->rxrearm_nb;
+ else
+#endif
+ nb_hold = rxq->nb_rx_hold;
+ if (offset >= rxq->nb_rx_desc - nb_hold)
+ return RTE_ETH_RX_DESC_USED;
+
+ desc = rxq->rx_tail + offset;
+ if (desc >= rxq->nb_rx_desc)
+ desc -= rxq->nb_rx_desc;
+
+ status = &rxq->rx_ring[desc].wb.upper.status_error;
+ if (*status & rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD))
+ return RTE_ETH_RX_DESC_DONE;
+
+ return RTE_ETH_RX_DESC_AVAIL;
+}
+
+int
+ixgbe_dev_tx_descriptor_status(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+ uint16_t offset)
+{
+ volatile uint32_t *status;
+ struct ixgbe_tx_queue *txq;
+ uint32_t desc;
+
+ txq = dev->data->tx_queues[tx_queue_id];
+ if (unlikely(offset >= txq->nb_tx_desc))
+ return -EINVAL;
+
+ desc = txq->tx_tail + offset;
+ /* go to next desc that has the RS bit */
+ desc = ((desc + txq->tx_rs_thresh - 1) / txq->tx_rs_thresh) *
+ txq->tx_rs_thresh;
+ status = &txq->tx_ring[desc].wb.status;
+ if (*status & rte_cpu_to_le_32(IXGBE_ADVTXD_STAT_DD))
+ return RTE_ETH_TX_DESC_DONE;
+
+ return RTE_ETH_TX_DESC_FULL;
+}
+
void __attribute__((cold))
ixgbe_dev_clear_queues(struct rte_eth_dev *dev)
{
--
2.8.1
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH 3/6] net/e1000: implement descriptor status API (igb)
2017-03-01 17:19 ` [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors Olivier Matz
2017-03-01 17:19 ` [dpdk-dev] [PATCH 1/6] ethdev: add descriptor status API Olivier Matz
2017-03-01 17:19 ` [dpdk-dev] [PATCH 2/6] net/ixgbe: implement " Olivier Matz
@ 2017-03-01 17:19 ` Olivier Matz
2017-03-02 1:28 ` Lu, Wenzhuo
2017-03-01 17:19 ` [dpdk-dev] [PATCH 4/6] net/e1000: implement descriptor status API (em) Olivier Matz
` (6 subsequent siblings)
9 siblings, 1 reply; 72+ messages in thread
From: Olivier Matz @ 2017-03-01 17:19 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
drivers/net/e1000/e1000_ethdev.h | 5 +++++
drivers/net/e1000/igb_ethdev.c | 2 ++
drivers/net/e1000/igb_rxtx.c | 46 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 53 insertions(+)
diff --git a/drivers/net/e1000/e1000_ethdev.h b/drivers/net/e1000/e1000_ethdev.h
index 81a6dbb..2b63b1a 100644
--- a/drivers/net/e1000/e1000_ethdev.h
+++ b/drivers/net/e1000/e1000_ethdev.h
@@ -311,6 +311,11 @@ uint32_t eth_igb_rx_queue_count(struct rte_eth_dev *dev,
int eth_igb_rx_descriptor_done(void *rx_queue, uint16_t offset);
+int eth_igb_rx_descriptor_status(struct rte_eth_dev *dev,
+ uint16_t rx_queue_id, uint16_t offset);
+int eth_igb_tx_descriptor_status(struct rte_eth_dev *dev,
+ uint16_t tx_queue_id, uint16_t offset);
+
int eth_igb_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
uint16_t nb_tx_desc, unsigned int socket_id,
const struct rte_eth_txconf *tx_conf);
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index a112b38..f6ed824 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -406,6 +406,8 @@ static const struct eth_dev_ops eth_igb_ops = {
.rx_queue_release = eth_igb_rx_queue_release,
.rx_queue_count = eth_igb_rx_queue_count,
.rx_descriptor_done = eth_igb_rx_descriptor_done,
+ .rx_descriptor_status = eth_igb_rx_descriptor_status,
+ .tx_descriptor_status = eth_igb_tx_descriptor_status,
.tx_queue_setup = eth_igb_tx_queue_setup,
.tx_queue_release = eth_igb_tx_queue_release,
.dev_led_on = eth_igb_led_on,
diff --git a/drivers/net/e1000/igb_rxtx.c b/drivers/net/e1000/igb_rxtx.c
index c9cf392..838413c 100644
--- a/drivers/net/e1000/igb_rxtx.c
+++ b/drivers/net/e1000/igb_rxtx.c
@@ -1606,6 +1606,52 @@ eth_igb_rx_descriptor_done(void *rx_queue, uint16_t offset)
return !!(rxdp->wb.upper.status_error & E1000_RXD_STAT_DD);
}
+int
+eth_igb_rx_descriptor_status(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+ uint16_t offset)
+{
+ volatile uint32_t *status;
+ struct igb_rx_queue *rxq;
+ uint32_t desc;
+
+ rxq = dev->data->rx_queues[rx_queue_id];
+ if (unlikely(offset >= rxq->nb_rx_desc))
+ return -EINVAL;
+
+ if (offset >= rxq->nb_rx_desc - rxq->nb_rx_hold)
+ return RTE_ETH_RX_DESC_USED;
+
+ desc = rxq->rx_tail + offset;
+ if (desc >= rxq->nb_rx_desc)
+ desc -= rxq->nb_rx_desc;
+
+ status = &rxq->rx_ring[desc].wb.upper.status_error;
+ if (*status & rte_cpu_to_le_32(E1000_RXD_STAT_DD))
+ return RTE_ETH_RX_DESC_DONE;
+
+ return RTE_ETH_RX_DESC_AVAIL;
+}
+
+int
+eth_igb_tx_descriptor_status(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+ uint16_t offset)
+{
+ volatile uint32_t *status;
+ struct igb_tx_queue *txq;
+ uint32_t desc;
+
+ txq = dev->data->tx_queues[tx_queue_id];
+ if (unlikely(offset >= txq->nb_tx_desc))
+ return -EINVAL;
+
+ desc = txq->tx_tail + offset;
+ status = &txq->tx_ring[desc].wb.status;
+ if (*status & rte_cpu_to_le_32(E1000_TXD_STAT_DD))
+ return RTE_ETH_TX_DESC_DONE;
+
+ return RTE_ETH_TX_DESC_FULL;
+}
+
void
igb_dev_clear_queues(struct rte_eth_dev *dev)
{
--
2.8.1
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 3/6] net/e1000: implement descriptor status API (igb)
2017-03-01 17:19 ` [dpdk-dev] [PATCH 3/6] net/e1000: implement descriptor status API (igb) Olivier Matz
@ 2017-03-02 1:28 ` Lu, Wenzhuo
2017-03-02 13:58 ` Olivier Matz
0 siblings, 1 reply; 72+ messages in thread
From: Lu, Wenzhuo @ 2017-03-02 1:28 UTC (permalink / raw)
To: Olivier Matz, dev, thomas.monjalon, Ananyev, Konstantin, Zhang,
Helin, Wu, Jingjing, adrien.mazarguil, nelio.laranjeiro
Cc: Yigit, Ferruh, Richardson, Bruce
Hi Olivier,
> -----Original Message-----
> From: Olivier Matz [mailto:olivier.matz@6wind.com]
> Sent: Thursday, March 2, 2017 1:19 AM
> To: dev@dpdk.org; thomas.monjalon@6wind.com; Ananyev, Konstantin; Lu,
> Wenzhuo; Zhang, Helin; Wu, Jingjing; adrien.mazarguil@6wind.com;
> nelio.laranjeiro@6wind.com
> Cc: Yigit, Ferruh; Richardson, Bruce
> Subject: [PATCH 3/6] net/e1000: implement descriptor status API (igb)
>
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> +
> +int
> +eth_igb_tx_descriptor_status(struct rte_eth_dev *dev, uint16_t tx_queue_id,
> + uint16_t offset)
> +{
> + volatile uint32_t *status;
> + struct igb_tx_queue *txq;
> + uint32_t desc;
> +
> + txq = dev->data->tx_queues[tx_queue_id];
> + if (unlikely(offset >= txq->nb_tx_desc))
> + return -EINVAL;
> +
> + desc = txq->tx_tail + offset;
Should we check nb_tx_desc here? The same for em.
> + status = &txq->tx_ring[desc].wb.status;
> + if (*status & rte_cpu_to_le_32(E1000_TXD_STAT_DD))
> + return RTE_ETH_TX_DESC_DONE;
> +
> + return RTE_ETH_TX_DESC_FULL;
> +}
> +
> void
> igb_dev_clear_queues(struct rte_eth_dev *dev) {
> --
> 2.8.1
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 3/6] net/e1000: implement descriptor status API (igb)
2017-03-02 1:28 ` Lu, Wenzhuo
@ 2017-03-02 13:58 ` Olivier Matz
0 siblings, 0 replies; 72+ messages in thread
From: Olivier Matz @ 2017-03-02 13:58 UTC (permalink / raw)
To: Lu, Wenzhuo
Cc: dev, thomas.monjalon, Ananyev, Konstantin, Zhang, Helin, Wu,
Jingjing, adrien.mazarguil, nelio.laranjeiro, Yigit, Ferruh,
Richardson, Bruce
Hi Wenzhuo,
On Thu, 2 Mar 2017 01:28:21 +0000, "Lu, Wenzhuo" <wenzhuo.lu@intel.com> wrote:
> Hi Olivier,
>
> > -----Original Message-----
> > From: Olivier Matz [mailto:olivier.matz@6wind.com]
> > Sent: Thursday, March 2, 2017 1:19 AM
> > To: dev@dpdk.org; thomas.monjalon@6wind.com; Ananyev, Konstantin; Lu,
> > Wenzhuo; Zhang, Helin; Wu, Jingjing; adrien.mazarguil@6wind.com;
> > nelio.laranjeiro@6wind.com
> > Cc: Yigit, Ferruh; Richardson, Bruce
> > Subject: [PATCH 3/6] net/e1000: implement descriptor status API (igb)
> >
> > Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> > +
> > +int
> > +eth_igb_tx_descriptor_status(struct rte_eth_dev *dev, uint16_t tx_queue_id,
> > + uint16_t offset)
> > +{
> > + volatile uint32_t *status;
> > + struct igb_tx_queue *txq;
> > + uint32_t desc;
> > +
> > + txq = dev->data->tx_queues[tx_queue_id];
> > + if (unlikely(offset >= txq->nb_tx_desc))
> > + return -EINVAL;
> > +
> > + desc = txq->tx_tail + offset;
> Should we check nb_tx_desc here? The same for em.
Correct, thanks.
Olivier
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH 4/6] net/e1000: implement descriptor status API (em)
2017-03-01 17:19 ` [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors Olivier Matz
` (2 preceding siblings ...)
2017-03-01 17:19 ` [dpdk-dev] [PATCH 3/6] net/e1000: implement descriptor status API (igb) Olivier Matz
@ 2017-03-01 17:19 ` Olivier Matz
2017-03-02 1:22 ` Lu, Wenzhuo
2017-03-01 17:19 ` [dpdk-dev] [PATCH 5/6] net/mlx5: implement descriptor status API Olivier Matz
` (5 subsequent siblings)
9 siblings, 1 reply; 72+ messages in thread
From: Olivier Matz @ 2017-03-01 17:19 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
drivers/net/e1000/e1000_ethdev.h | 5 ++++
drivers/net/e1000/em_ethdev.c | 2 ++
drivers/net/e1000/em_rxtx.c | 49 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 56 insertions(+)
diff --git a/drivers/net/e1000/e1000_ethdev.h b/drivers/net/e1000/e1000_ethdev.h
index 2b63b1a..e3fd7fc 100644
--- a/drivers/net/e1000/e1000_ethdev.h
+++ b/drivers/net/e1000/e1000_ethdev.h
@@ -380,6 +380,11 @@ uint32_t eth_em_rx_queue_count(struct rte_eth_dev *dev,
int eth_em_rx_descriptor_done(void *rx_queue, uint16_t offset);
+int eth_em_rx_descriptor_status(struct rte_eth_dev *dev,
+ uint16_t rx_queue_id, uint16_t offset);
+int eth_em_tx_descriptor_status(struct rte_eth_dev *dev,
+ uint16_t tx_queue_id, uint16_t offset);
+
int eth_em_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
uint16_t nb_tx_desc, unsigned int socket_id,
const struct rte_eth_txconf *tx_conf);
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 4066ef9..4f34c14 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -205,6 +205,8 @@ static const struct eth_dev_ops eth_em_ops = {
.rx_queue_release = eth_em_rx_queue_release,
.rx_queue_count = eth_em_rx_queue_count,
.rx_descriptor_done = eth_em_rx_descriptor_done,
+ .rx_descriptor_status = eth_em_rx_descriptor_status,
+ .tx_descriptor_status = eth_em_tx_descriptor_status,
.tx_queue_setup = eth_em_tx_queue_setup,
.tx_queue_release = eth_em_tx_queue_release,
.rx_queue_intr_enable = eth_em_rx_queue_intr_enable,
diff --git a/drivers/net/e1000/em_rxtx.c b/drivers/net/e1000/em_rxtx.c
index d099d6a..1651454 100644
--- a/drivers/net/e1000/em_rxtx.c
+++ b/drivers/net/e1000/em_rxtx.c
@@ -1473,6 +1473,55 @@ eth_em_rx_descriptor_done(void *rx_queue, uint16_t offset)
return !!(rxdp->status & E1000_RXD_STAT_DD);
}
+int
+eth_em_rx_descriptor_status(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+ uint16_t offset)
+{
+ volatile uint8_t *status;
+ struct em_rx_queue *rxq;
+ uint32_t desc;
+
+ rxq = dev->data->rx_queues[rx_queue_id];
+ if (unlikely(offset >= rxq->nb_rx_desc))
+ return -EINVAL;
+
+ if (offset >= rxq->nb_rx_desc - rxq->nb_rx_hold)
+ return RTE_ETH_RX_DESC_USED;
+
+ desc = rxq->rx_tail + offset;
+ if (desc >= rxq->nb_rx_desc)
+ desc -= rxq->nb_rx_desc;
+
+ status = &rxq->rx_ring[desc].status;
+ if (*status & E1000_RXD_STAT_DD)
+ return RTE_ETH_RX_DESC_DONE;
+
+ return RTE_ETH_RX_DESC_AVAIL;
+}
+
+int
+eth_em_tx_descriptor_status(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+ uint16_t offset)
+{
+ volatile uint8_t *status;
+ struct em_tx_queue *txq;
+ uint32_t desc;
+
+ txq = dev->data->tx_queues[tx_queue_id];
+ if (unlikely(offset >= txq->nb_tx_desc))
+ return -EINVAL;
+
+ desc = txq->tx_tail + offset;
+ /* go to next desc that has the RS bit */
+ desc = ((desc + txq->tx_rs_thresh - 1) / txq->tx_rs_thresh) *
+ txq->tx_rs_thresh;
+ status = &txq->tx_ring[desc].upper.fields.status;
+ if (*status & E1000_TXD_STAT_DD)
+ return RTE_ETH_TX_DESC_DONE;
+
+ return RTE_ETH_TX_DESC_FULL;
+}
+
void
em_dev_clear_queues(struct rte_eth_dev *dev)
{
--
2.8.1
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 4/6] net/e1000: implement descriptor status API (em)
2017-03-01 17:19 ` [dpdk-dev] [PATCH 4/6] net/e1000: implement descriptor status API (em) Olivier Matz
@ 2017-03-02 1:22 ` Lu, Wenzhuo
2017-03-02 14:46 ` Olivier Matz
0 siblings, 1 reply; 72+ messages in thread
From: Lu, Wenzhuo @ 2017-03-02 1:22 UTC (permalink / raw)
To: Olivier Matz, dev, thomas.monjalon, Ananyev, Konstantin, Zhang,
Helin, Wu, Jingjing, adrien.mazarguil, nelio.laranjeiro
Cc: Yigit, Ferruh, Richardson, Bruce
Hi Oliver,
> -----Original Message-----
> From: Olivier Matz [mailto:olivier.matz@6wind.com]
> Sent: Thursday, March 2, 2017 1:19 AM
> To: dev@dpdk.org; thomas.monjalon@6wind.com; Ananyev, Konstantin; Lu,
> Wenzhuo; Zhang, Helin; Wu, Jingjing; adrien.mazarguil@6wind.com;
> nelio.laranjeiro@6wind.com
> Cc: Yigit, Ferruh; Richardson, Bruce
> Subject: [PATCH 4/6] net/e1000: implement descriptor status API (em)
>
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> +int
> +eth_em_tx_descriptor_status(struct rte_eth_dev *dev, uint16_t tx_queue_id,
> + uint16_t offset)
> +{
> + volatile uint8_t *status;
> + struct em_tx_queue *txq;
> + uint32_t desc;
> +
> + txq = dev->data->tx_queues[tx_queue_id];
> + if (unlikely(offset >= txq->nb_tx_desc))
> + return -EINVAL;
> +
> + desc = txq->tx_tail + offset;
> + /* go to next desc that has the RS bit */
> + desc = ((desc + txq->tx_rs_thresh - 1) / txq->tx_rs_thresh) *
> + txq->tx_rs_thresh;
The descriptor may be changed here. So the return value may not be for the offset one. Why?
> + status = &txq->tx_ring[desc].upper.fields.status;
> + if (*status & E1000_TXD_STAT_DD)
> + return RTE_ETH_TX_DESC_DONE;
> +
> + return RTE_ETH_TX_DESC_FULL;
> +}
> +
> void
> em_dev_clear_queues(struct rte_eth_dev *dev) {
> --
> 2.8.1
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 4/6] net/e1000: implement descriptor status API (em)
2017-03-02 1:22 ` Lu, Wenzhuo
@ 2017-03-02 14:46 ` Olivier Matz
2017-03-03 1:15 ` Lu, Wenzhuo
0 siblings, 1 reply; 72+ messages in thread
From: Olivier Matz @ 2017-03-02 14:46 UTC (permalink / raw)
To: Lu, Wenzhuo
Cc: dev, thomas.monjalon, Ananyev, Konstantin, Zhang, Helin, Wu,
Jingjing, adrien.mazarguil, nelio.laranjeiro, Yigit, Ferruh,
Richardson, Bruce
Hi Wenzhuo,
On Thu, 2 Mar 2017 01:22:25 +0000, "Lu, Wenzhuo" <wenzhuo.lu@intel.com> wrote:
> Hi Oliver,
>
> > -----Original Message-----
> > From: Olivier Matz [mailto:olivier.matz@6wind.com]
> > Sent: Thursday, March 2, 2017 1:19 AM
> > To: dev@dpdk.org; thomas.monjalon@6wind.com; Ananyev, Konstantin; Lu,
> > Wenzhuo; Zhang, Helin; Wu, Jingjing; adrien.mazarguil@6wind.com;
> > nelio.laranjeiro@6wind.com
> > Cc: Yigit, Ferruh; Richardson, Bruce
> > Subject: [PATCH 4/6] net/e1000: implement descriptor status API (em)
> >
> > Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> > +int
> > +eth_em_tx_descriptor_status(struct rte_eth_dev *dev, uint16_t tx_queue_id,
> > + uint16_t offset)
> > +{
> > + volatile uint8_t *status;
> > + struct em_tx_queue *txq;
> > + uint32_t desc;
> > +
> > + txq = dev->data->tx_queues[tx_queue_id];
> > + if (unlikely(offset >= txq->nb_tx_desc))
> > + return -EINVAL;
> > +
> > + desc = txq->tx_tail + offset;
> > + /* go to next desc that has the RS bit */
> > + desc = ((desc + txq->tx_rs_thresh - 1) / txq->tx_rs_thresh) *
> > + txq->tx_rs_thresh;
> The descriptor may be changed here. So the return value may not be for the offset one. Why?
Yes, desc index can change. From what I understand, the
"descriptor done" (DD) bit is only set on descriptors which are
flagged with the "report status" (RS) bit.
Here is an example from:
http://www.dpdk.org/ml/archives/dev/2016-November/050679.html
|----------------------------------------------------------------|
| D R R R |
| ............xxxxxxxxxxxxxxxxxxxxxxxxx |
| <descs sent><- descs not sent yet -> |
| ............xxxxxxxxxxxxxxxxxxxxxxxxx |
|----------------------------------------------------------------|
^last_desc_cleaned=8 ^next_rs=47
^next_dd=15 ^tail=45
^hw_head=20
<---- nb_used --------->
The hardware is currently processing the descriptor 20
'R' means the descriptor has the RS bit
'D' means the descriptor has the DD + RS bits
'x' are packets in txq (not sent)
'.' are packet already sent but not freed by sw
Regards,
Olivier
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 4/6] net/e1000: implement descriptor status API (em)
2017-03-02 14:46 ` Olivier Matz
@ 2017-03-03 1:15 ` Lu, Wenzhuo
0 siblings, 0 replies; 72+ messages in thread
From: Lu, Wenzhuo @ 2017-03-03 1:15 UTC (permalink / raw)
To: Olivier Matz
Cc: dev, thomas.monjalon, Ananyev, Konstantin, Zhang, Helin, Wu,
Jingjing, adrien.mazarguil, nelio.laranjeiro, Yigit, Ferruh,
Richardson, Bruce
Hi Olivier,
> -----Original Message-----
> From: Olivier Matz [mailto:olivier.matz@6wind.com]
> Sent: Thursday, March 2, 2017 10:47 PM
> To: Lu, Wenzhuo
> Cc: dev@dpdk.org; thomas.monjalon@6wind.com; Ananyev, Konstantin; Zhang,
> Helin; Wu, Jingjing; adrien.mazarguil@6wind.com; nelio.laranjeiro@6wind.com;
> Yigit, Ferruh; Richardson, Bruce
> Subject: Re: [PATCH 4/6] net/e1000: implement descriptor status API (em)
>
> Hi Wenzhuo,
>
> On Thu, 2 Mar 2017 01:22:25 +0000, "Lu, Wenzhuo" <wenzhuo.lu@intel.com>
> wrote:
> > Hi Oliver,
> >
> > > -----Original Message-----
> > > From: Olivier Matz [mailto:olivier.matz@6wind.com]
> > > Sent: Thursday, March 2, 2017 1:19 AM
> > > To: dev@dpdk.org; thomas.monjalon@6wind.com; Ananyev, Konstantin;
> > > Lu, Wenzhuo; Zhang, Helin; Wu, Jingjing; adrien.mazarguil@6wind.com;
> > > nelio.laranjeiro@6wind.com
> > > Cc: Yigit, Ferruh; Richardson, Bruce
> > > Subject: [PATCH 4/6] net/e1000: implement descriptor status API (em)
> > >
> > > Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> > > +int
> > > +eth_em_tx_descriptor_status(struct rte_eth_dev *dev, uint16_t
> tx_queue_id,
> > > + uint16_t offset)
> > > +{
> > > + volatile uint8_t *status;
> > > + struct em_tx_queue *txq;
> > > + uint32_t desc;
> > > +
> > > + txq = dev->data->tx_queues[tx_queue_id];
> > > + if (unlikely(offset >= txq->nb_tx_desc))
> > > + return -EINVAL;
> > > +
> > > + desc = txq->tx_tail + offset;
> > > + /* go to next desc that has the RS bit */
> > > + desc = ((desc + txq->tx_rs_thresh - 1) / txq->tx_rs_thresh) *
> > > + txq->tx_rs_thresh;
> > The descriptor may be changed here. So the return value may not be for the
> offset one. Why?
>
> Yes, desc index can change. From what I understand, the "descriptor done" (DD)
> bit is only set on descriptors which are flagged with the "report status" (RS) bit.
Yes, you're right. Sorry for the noise :)
>
> Here is an example from:
> http://www.dpdk.org/ml/archives/dev/2016-November/050679.html
>
> |----------------------------------------------------------------|
> | D R R R |
> | ............xxxxxxxxxxxxxxxxxxxxxxxxx |
> | <descs sent><- descs not sent yet -> |
> | ............xxxxxxxxxxxxxxxxxxxxxxxxx |
> |----------------------------------------------------------------|
> ^last_desc_cleaned=8 ^next_rs=47
> ^next_dd=15 ^tail=45
> ^hw_head=20
>
> <---- nb_used --------->
>
> The hardware is currently processing the descriptor 20 'R' means the descriptor
> has the RS bit 'D' means the descriptor has the DD + RS bits 'x' are packets in txq
> (not sent) '.' are packet already sent but not freed by sw
>
>
> Regards,
> Olivier
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH 5/6] net/mlx5: implement descriptor status API
2017-03-01 17:19 ` [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors Olivier Matz
` (3 preceding siblings ...)
2017-03-01 17:19 ` [dpdk-dev] [PATCH 4/6] net/e1000: implement descriptor status API (em) Olivier Matz
@ 2017-03-01 17:19 ` Olivier Matz
2017-03-02 7:56 ` Nélio Laranjeiro
2017-03-01 17:19 ` [dpdk-dev] [PATCH 6/6] net/i40e: " Olivier Matz
` (4 subsequent siblings)
9 siblings, 1 reply; 72+ messages in thread
From: Olivier Matz @ 2017-03-01 17:19 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson
Since there is no "descriptor done" flag like on Intel drivers, the
approach is different on mlx5 driver.
- for Tx, we call txq_complete() to free descriptors processed by
the hw, then we check if the descriptor is between tail and head
- for Rx, we need to browse the cqes, managing compressed ones,
to get the number of used descriptors.
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
drivers/net/mlx5/mlx5.c | 2 ++
drivers/net/mlx5/mlx5_rxtx.c | 83 ++++++++++++++++++++++++++++++++++++++++++++
drivers/net/mlx5/mlx5_rxtx.h | 2 ++
3 files changed, 87 insertions(+)
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index d4bd469..4a6450c 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -222,6 +222,8 @@ static const struct eth_dev_ops mlx5_dev_ops = {
.rss_hash_update = mlx5_rss_hash_update,
.rss_hash_conf_get = mlx5_rss_hash_conf_get,
.filter_ctrl = mlx5_dev_filter_ctrl,
+ .rx_descriptor_status = mlx5_rx_descriptor_status,
+ .tx_descriptor_status = mlx5_tx_descriptor_status,
};
static struct {
diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index 88b0354..b3375f6 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -345,6 +345,89 @@ mlx5_tx_dbrec(struct txq *txq, volatile struct mlx5_wqe *wqe)
}
/**
+ * DPDK callback to check the status of a tx descriptor.
+ *
+ * @param dev
+ * Pointer to Ethernet device structure.
+ * @param[in] tx_queue_id
+ * The identifier of the tx queue.
+ * @param[in] offset
+ * The index of the descriptor in the ring.
+ *
+ * @return
+ * The status of the tx descriptor.
+ */
+int
+mlx5_tx_descriptor_status(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+ uint16_t offset)
+{
+ struct txq *txq = dev->data->tx_queues[tx_queue_id];
+ const unsigned int elts_n = 1 << txq->elts_n;
+ const unsigned int elts_cnt = elts_n - 1;
+ unsigned int used;
+
+ txq_complete(txq);
+
+ used = (txq->elts_head - txq->elts_tail) & elts_cnt;
+ if (offset < used)
+ return RTE_ETH_TX_DESC_FULL;
+ return RTE_ETH_TX_DESC_DONE;
+}
+
+/**
+ * DPDK callback to check the status of a rx descriptor.
+ *
+ * @param dev
+ * Pointer to Ethernet device structure.
+ * @param[in] tx_queue_id
+ * The identifier of the rx queue.
+ * @param[in] offset
+ * The index of the descriptor in the ring.
+ *
+ * @return
+ * The status of the rx descriptor.
+ */
+int
+mlx5_rx_descriptor_status(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+ uint16_t offset)
+{
+ struct rxq *rxq = dev->data->rx_queues[rx_queue_id];
+ struct rxq_zip *zip = &rxq->zip;
+ volatile struct mlx5_cqe *cqe;
+ const unsigned int cqe_n = (1 << rxq->cqe_n);
+ const unsigned int cqe_cnt = cqe_n - 1;
+ unsigned int cq_ci;
+ unsigned int used;
+
+ /* if we are processing a compressed cqe */
+ if (zip->ai) {
+ used = zip->cqe_cnt - zip->ca;
+ cq_ci = zip->cq_ci;
+ } else {
+ used = 0;
+ cq_ci = rxq->cq_ci;
+ }
+ cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
+ while (check_cqe(cqe, cqe_n, cq_ci) == 0) {
+ int8_t op_own;
+ unsigned int n;
+
+ op_own = cqe->op_own;
+ if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED)
+ n = ntohl(cqe->byte_cnt);
+ else
+ n = 1;
+ cq_ci += n;
+ used += n;
+ cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
+ }
+ used = RTE_MIN(used, (1U << rxq->elts_n) - 1);
+ if (offset < used)
+ return RTE_ETH_RX_DESC_DONE;
+ return RTE_ETH_RX_DESC_AVAIL;
+}
+
+/**
* DPDK callback for TX.
*
* @param dpdk_txq
diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h
index 41a34d7..e864dcd 100644
--- a/drivers/net/mlx5/mlx5_rxtx.h
+++ b/drivers/net/mlx5/mlx5_rxtx.h
@@ -323,6 +323,8 @@ uint16_t mlx5_tx_burst_mpw_inline(void *, struct rte_mbuf **, uint16_t);
uint16_t mlx5_rx_burst(void *, struct rte_mbuf **, uint16_t);
uint16_t removed_tx_burst(void *, struct rte_mbuf **, uint16_t);
uint16_t removed_rx_burst(void *, struct rte_mbuf **, uint16_t);
+int mlx5_rx_descriptor_status(struct rte_eth_dev *, uint16_t, uint16_t);
+int mlx5_tx_descriptor_status(struct rte_eth_dev *, uint16_t, uint16_t);
/* mlx5_mr.c */
--
2.8.1
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 5/6] net/mlx5: implement descriptor status API
2017-03-01 17:19 ` [dpdk-dev] [PATCH 5/6] net/mlx5: implement descriptor status API Olivier Matz
@ 2017-03-02 7:56 ` Nélio Laranjeiro
0 siblings, 0 replies; 72+ messages in thread
From: Nélio Laranjeiro @ 2017-03-02 7:56 UTC (permalink / raw)
To: Olivier Matz
Cc: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, ferruh.yigit,
bruce.richardson
Hi Olivier,
On Wed, Mar 01, 2017 at 06:19:11PM +0100, Olivier Matz wrote:
> Since there is no "descriptor done" flag like on Intel drivers, the
> approach is different on mlx5 driver.
> - for Tx, we call txq_complete() to free descriptors processed by
> the hw, then we check if the descriptor is between tail and head
> - for Rx, we need to browse the cqes, managing compressed ones,
> to get the number of used descriptors.
>
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> ---
> drivers/net/mlx5/mlx5.c | 2 ++
> drivers/net/mlx5/mlx5_rxtx.c | 83 ++++++++++++++++++++++++++++++++++++++++++++
> drivers/net/mlx5/mlx5_rxtx.h | 2 ++
> 3 files changed, 87 insertions(+)
>
> diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
> index d4bd469..4a6450c 100644
> --- a/drivers/net/mlx5/mlx5.c
> +++ b/drivers/net/mlx5/mlx5.c
> @@ -222,6 +222,8 @@ static const struct eth_dev_ops mlx5_dev_ops = {
> .rss_hash_update = mlx5_rss_hash_update,
> .rss_hash_conf_get = mlx5_rss_hash_conf_get,
> .filter_ctrl = mlx5_dev_filter_ctrl,
> + .rx_descriptor_status = mlx5_rx_descriptor_status,
> + .tx_descriptor_status = mlx5_tx_descriptor_status,
> };
>
> static struct {
> diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
> index 88b0354..b3375f6 100644
> --- a/drivers/net/mlx5/mlx5_rxtx.c
> +++ b/drivers/net/mlx5/mlx5_rxtx.c
> @@ -345,6 +345,89 @@ mlx5_tx_dbrec(struct txq *txq, volatile struct mlx5_wqe *wqe)
> }
>
> /**
> + * DPDK callback to check the status of a tx descriptor.
> + *
> + * @param dev
> + * Pointer to Ethernet device structure.
> + * @param[in] tx_queue_id
> + * The identifier of the tx queue.
> + * @param[in] offset
> + * The index of the descriptor in the ring.
> + *
> + * @return
> + * The status of the tx descriptor.
> + */
> +int
> +mlx5_tx_descriptor_status(struct rte_eth_dev *dev, uint16_t tx_queue_id,
> + uint16_t offset)
> +{
> + struct txq *txq = dev->data->tx_queues[tx_queue_id];
> + const unsigned int elts_n = 1 << txq->elts_n;
> + const unsigned int elts_cnt = elts_n - 1;
> + unsigned int used;
> +
> + txq_complete(txq);
> +
If you submit a v2 please remove this empty line.
> + used = (txq->elts_head - txq->elts_tail) & elts_cnt;
> + if (offset < used)
> + return RTE_ETH_TX_DESC_FULL;
> + return RTE_ETH_TX_DESC_DONE;
> +}
> +
> +/**
> + * DPDK callback to check the status of a rx descriptor.
> + *
> + * @param dev
> + * Pointer to Ethernet device structure.
> + * @param[in] tx_queue_id
> + * The identifier of the rx queue.
> + * @param[in] offset
> + * The index of the descriptor in the ring.
> + *
> + * @return
> + * The status of the rx descriptor.
> + */
> +int
> +mlx5_rx_descriptor_status(struct rte_eth_dev *dev, uint16_t rx_queue_id,
> + uint16_t offset)
> +{
> + struct rxq *rxq = dev->data->rx_queues[rx_queue_id];
> + struct rxq_zip *zip = &rxq->zip;
> + volatile struct mlx5_cqe *cqe;
> + const unsigned int cqe_n = (1 << rxq->cqe_n);
> + const unsigned int cqe_cnt = cqe_n - 1;
> + unsigned int cq_ci;
> + unsigned int used;
> +
> + /* if we are processing a compressed cqe */
> + if (zip->ai) {
> + used = zip->cqe_cnt - zip->ca;
> + cq_ci = zip->cq_ci;
> + } else {
> + used = 0;
> + cq_ci = rxq->cq_ci;
> + }
> + cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
> + while (check_cqe(cqe, cqe_n, cq_ci) == 0) {
> + int8_t op_own;
> + unsigned int n;
> +
> + op_own = cqe->op_own;
> + if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED)
> + n = ntohl(cqe->byte_cnt);
> + else
> + n = 1;
> + cq_ci += n;
> + used += n;
> + cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
> + }
> + used = RTE_MIN(used, (1U << rxq->elts_n) - 1);
> + if (offset < used)
> + return RTE_ETH_RX_DESC_DONE;
> + return RTE_ETH_RX_DESC_AVAIL;
> +}
> +
> +/**
> * DPDK callback for TX.
> *
> * @param dpdk_txq
> diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h
> index 41a34d7..e864dcd 100644
> --- a/drivers/net/mlx5/mlx5_rxtx.h
> +++ b/drivers/net/mlx5/mlx5_rxtx.h
> @@ -323,6 +323,8 @@ uint16_t mlx5_tx_burst_mpw_inline(void *, struct rte_mbuf **, uint16_t);
> uint16_t mlx5_rx_burst(void *, struct rte_mbuf **, uint16_t);
> uint16_t removed_tx_burst(void *, struct rte_mbuf **, uint16_t);
> uint16_t removed_rx_burst(void *, struct rte_mbuf **, uint16_t);
> +int mlx5_rx_descriptor_status(struct rte_eth_dev *, uint16_t, uint16_t);
> +int mlx5_tx_descriptor_status(struct rte_eth_dev *, uint16_t, uint16_t);
>
> /* mlx5_mr.c */
>
> --
> 2.8.1
Acked-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
--
Nélio Laranjeiro
6WIND
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH 6/6] net/i40e: implement descriptor status API
2017-03-01 17:19 ` [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors Olivier Matz
` (4 preceding siblings ...)
2017-03-01 17:19 ` [dpdk-dev] [PATCH 5/6] net/mlx5: implement descriptor status API Olivier Matz
@ 2017-03-01 17:19 ` Olivier Matz
2017-03-01 18:02 ` [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors Andrew Rybchenko
` (3 subsequent siblings)
9 siblings, 0 replies; 72+ messages in thread
From: Olivier Matz @ 2017-03-01 17:19 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
drivers/net/i40e/i40e_ethdev.c | 2 ++
drivers/net/i40e/i40e_ethdev_vf.c | 2 ++
drivers/net/i40e/i40e_rxtx.c | 56 +++++++++++++++++++++++++++++++++++++++
drivers/net/i40e/i40e_rxtx.h | 4 +++
4 files changed, 64 insertions(+)
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 303027b..8b5fd54 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -479,6 +479,8 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
.rx_queue_release = i40e_dev_rx_queue_release,
.rx_queue_count = i40e_dev_rx_queue_count,
.rx_descriptor_done = i40e_dev_rx_descriptor_done,
+ .rx_descriptor_status = i40e_dev_rx_descriptor_status,
+ .tx_descriptor_status = i40e_dev_tx_descriptor_status,
.tx_queue_setup = i40e_dev_tx_queue_setup,
.tx_queue_release = i40e_dev_tx_queue_release,
.dev_led_on = i40e_dev_led_on,
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 55fd344..d3659c9 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -217,6 +217,8 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = {
.rx_queue_intr_enable = i40evf_dev_rx_queue_intr_enable,
.rx_queue_intr_disable = i40evf_dev_rx_queue_intr_disable,
.rx_descriptor_done = i40e_dev_rx_descriptor_done,
+ .rx_descriptor_status = i40e_dev_rx_descriptor_status,
+ .tx_descriptor_status = i40e_dev_tx_descriptor_status,
.tx_queue_setup = i40e_dev_tx_queue_setup,
.tx_queue_release = i40e_dev_tx_queue_release,
.rx_queue_count = i40e_dev_rx_queue_count,
diff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c
index 45af0d7..b912689 100644
--- a/drivers/net/i40e/i40e_rxtx.c
+++ b/drivers/net/i40e/i40e_rxtx.c
@@ -1929,6 +1929,62 @@ i40e_dev_rx_descriptor_done(void *rx_queue, uint16_t offset)
}
int
+i40e_dev_rx_descriptor_status(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+ uint16_t offset)
+{
+ struct i40e_rx_queue *rxq;
+ volatile uint64_t *status;
+ uint64_t mask;
+ uint32_t desc;
+
+ rxq = dev->data->rx_queues[rx_queue_id];
+ if (unlikely(offset >= rxq->nb_rx_desc))
+ return -EINVAL;
+
+ if (offset >= rxq->nb_rx_desc - rxq->nb_rx_hold)
+ return RTE_ETH_RX_DESC_USED;
+
+ desc = rxq->rx_tail + offset;
+ if (desc >= rxq->nb_rx_desc)
+ desc -= rxq->nb_rx_desc;
+
+ status = &rxq->rx_ring[desc].wb.qword1.status_error_len;
+ mask = rte_le_to_cpu_64((1ULL << I40E_RX_DESC_STATUS_DD_SHIFT)
+ << I40E_RXD_QW1_STATUS_SHIFT);
+ if (*status & mask)
+ return RTE_ETH_RX_DESC_DONE;
+
+ return RTE_ETH_RX_DESC_AVAIL;
+}
+
+int
+i40e_dev_tx_descriptor_status(struct rte_eth_dev *dev, uint16_t tx_queue_id,
+ uint16_t offset)
+{
+ struct i40e_tx_queue *txq;
+ volatile uint64_t *status;
+ uint64_t mask, expect;
+ uint32_t desc;
+
+ txq = dev->data->tx_queues[tx_queue_id];
+ if (unlikely(offset >= txq->nb_tx_desc))
+ return -EINVAL;
+
+ desc = txq->tx_tail + offset;
+ if (desc >= txq->nb_tx_desc)
+ desc -= txq->nb_tx_desc;
+
+ status = &txq->tx_ring[desc].cmd_type_offset_bsz;
+ mask = rte_le_to_cpu_64(I40E_TXD_QW1_DTYPE_MASK);
+ expect = rte_cpu_to_le_64(
+ I40E_TX_DESC_DTYPE_DESC_DONE << I40E_TXD_QW1_DTYPE_SHIFT);
+ if ((*status & mask) == expect)
+ return RTE_ETH_TX_DESC_DONE;
+
+ return RTE_ETH_TX_DESC_FULL;
+}
+
+int
i40e_dev_tx_queue_setup(struct rte_eth_dev *dev,
uint16_t queue_idx,
uint16_t nb_desc,
diff --git a/drivers/net/i40e/i40e_rxtx.h b/drivers/net/i40e/i40e_rxtx.h
index 9df8a56..c32519e 100644
--- a/drivers/net/i40e/i40e_rxtx.h
+++ b/drivers/net/i40e/i40e_rxtx.h
@@ -246,6 +246,10 @@ void i40e_rx_queue_release_mbufs(struct i40e_rx_queue *rxq);
uint32_t i40e_dev_rx_queue_count(struct rte_eth_dev *dev,
uint16_t rx_queue_id);
int i40e_dev_rx_descriptor_done(void *rx_queue, uint16_t offset);
+int i40e_dev_rx_descriptor_status(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+ uint16_t offset);
+int i40e_dev_tx_descriptor_status(struct rte_eth_dev *dev, uint16_t rx_queue_id,
+ uint16_t offset);
uint16_t i40e_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
uint16_t nb_pkts);
--
2.8.1
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
2017-03-01 17:19 ` [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors Olivier Matz
` (5 preceding siblings ...)
2017-03-01 17:19 ` [dpdk-dev] [PATCH 6/6] net/i40e: " Olivier Matz
@ 2017-03-01 18:02 ` Andrew Rybchenko
2017-03-02 13:40 ` Olivier Matz
2017-03-01 18:07 ` Stephen Hemminger
` (2 subsequent siblings)
9 siblings, 1 reply; 72+ messages in thread
From: Andrew Rybchenko @ 2017-03-01 18:02 UTC (permalink / raw)
To: Olivier Matz, dev, thomas.monjalon, konstantin.ananyev,
wenzhuo.lu, helin.zhang, jingjing.wu, adrien.mazarguil,
nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson
On 03/01/2017 08:19 PM, Olivier Matz wrote:
> This patchset introduces a new ethdev API:
> - rte_eth_rx_descriptor_status()
> - rte_eth_tx_descriptor_status()
May be corresponding features should be added to the NICs documentation?
> The Rx API is aims to replace rte_eth_rx_descriptor_done() which
> does almost the same, but does not differentiate the case of a
> descriptor used by the driver (not returned to the hw).
>
> The usage of these functions can be:
> - on Rx, anticipate that the cpu is not fast enough to process
> all incoming packets, and take dispositions to solve the
> problem (add more cpus, drop specific packets, ...)
> - on Tx, detect that the link is overloaded, and take dispositions
> to solve the problem (notify flow control, drop specific
> packets)
>
> The patchset updates ixgbe, i40e, e1000, mlx5.
> The other drivers that implement the descriptor_done() API are
> fm10k, sfc, virtio. They are not updated.
> If the new API is accepted, the descriptor_done() can be deprecated,
> and examples/l3fwd-power will be updated to.
>
>
> RFC->v1:
> - instead of optimizing an API that returns the number of used
> descriptors like rx_queue_count(), use a more simple API that
> returns the status of a descriptor, like rx_descriptor_done().
> - remove ethdev api rework (first 2 patches), they have been
> sent separately
>
>
> Olivier Matz (6):
> ethdev: add descriptor status API
> net/ixgbe: implement descriptor status API
> net/e1000: implement descriptor status API (igb)
> net/e1000: implement descriptor status API (em)
> net/mlx5: implement descriptor status API
> net/i40e: implement descriptor status API
>
> drivers/net/e1000/e1000_ethdev.h | 10 +++++
> drivers/net/e1000/em_ethdev.c | 2 +
> drivers/net/e1000/em_rxtx.c | 49 ++++++++++++++++++++++
> drivers/net/e1000/igb_ethdev.c | 2 +
> drivers/net/e1000/igb_rxtx.c | 46 +++++++++++++++++++++
> drivers/net/i40e/i40e_ethdev.c | 2 +
> drivers/net/i40e/i40e_ethdev_vf.c | 2 +
> drivers/net/i40e/i40e_rxtx.c | 56 +++++++++++++++++++++++++
> drivers/net/i40e/i40e_rxtx.h | 4 ++
> drivers/net/ixgbe/ixgbe_ethdev.c | 4 ++
> drivers/net/ixgbe/ixgbe_ethdev.h | 5 +++
> drivers/net/ixgbe/ixgbe_rxtx.c | 55 +++++++++++++++++++++++++
> drivers/net/mlx5/mlx5.c | 2 +
> drivers/net/mlx5/mlx5_rxtx.c | 83 +++++++++++++++++++++++++++++++++++++
> drivers/net/mlx5/mlx5_rxtx.h | 2 +
> lib/librte_ether/rte_ethdev.h | 86 +++++++++++++++++++++++++++++++++++++++
> 16 files changed, 410 insertions(+)
>
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
2017-03-01 18:02 ` [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors Andrew Rybchenko
@ 2017-03-02 13:40 ` Olivier Matz
2017-03-06 10:41 ` Thomas Monjalon
0 siblings, 1 reply; 72+ messages in thread
From: Olivier Matz @ 2017-03-02 13:40 UTC (permalink / raw)
To: Andrew Rybchenko
Cc: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro,
ferruh.yigit, bruce.richardson
On Wed, 1 Mar 2017 21:02:16 +0300, Andrew Rybchenko <arybchenko@solarflare.com> wrote:
> On 03/01/2017 08:19 PM, Olivier Matz wrote:
> > This patchset introduces a new ethdev API:
> > - rte_eth_rx_descriptor_status()
> > - rte_eth_tx_descriptor_status()
>
> May be corresponding features should be added to the NICs documentation?
Yes, good idea.
I propose to use these straightforward names: "Rx Descriptor Status"
and "Tx Descriptor Status".
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
2017-03-02 13:40 ` Olivier Matz
@ 2017-03-06 10:41 ` Thomas Monjalon
0 siblings, 0 replies; 72+ messages in thread
From: Thomas Monjalon @ 2017-03-06 10:41 UTC (permalink / raw)
To: Olivier Matz
Cc: Andrew Rybchenko, dev, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro,
ferruh.yigit, bruce.richardson
2017-03-02 14:40, Olivier Matz:
> On Wed, 1 Mar 2017 21:02:16 +0300, Andrew Rybchenko <arybchenko@solarflare.com> wrote:
> > On 03/01/2017 08:19 PM, Olivier Matz wrote:
> > > This patchset introduces a new ethdev API:
> > > - rte_eth_rx_descriptor_status()
> > > - rte_eth_tx_descriptor_status()
> >
> > May be corresponding features should be added to the NICs documentation?
>
> Yes, good idea.
>
> I propose to use these straightforward names: "Rx Descriptor Status"
> and "Tx Descriptor Status".
Yes
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
2017-03-01 17:19 ` [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors Olivier Matz
` (6 preceding siblings ...)
2017-03-01 18:02 ` [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors Andrew Rybchenko
@ 2017-03-01 18:07 ` Stephen Hemminger
2017-03-02 13:43 ` Olivier Matz
2017-03-02 15:32 ` Bruce Richardson
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 " Olivier Matz
9 siblings, 1 reply; 72+ messages in thread
From: Stephen Hemminger @ 2017-03-01 18:07 UTC (permalink / raw)
To: Olivier Matz
Cc: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro,
ferruh.yigit, bruce.richardson
On Wed, 1 Mar 2017 18:19:06 +0100
Olivier Matz <olivier.matz@6wind.com> wrote:
> This patchset introduces a new ethdev API:
> - rte_eth_rx_descriptor_status()
> - rte_eth_tx_descriptor_status()
>
> The Rx API is aims to replace rte_eth_rx_descriptor_done() which
> does almost the same, but does not differentiate the case of a
> descriptor used by the driver (not returned to the hw).
>
> The usage of these functions can be:
> - on Rx, anticipate that the cpu is not fast enough to process
> all incoming packets, and take dispositions to solve the
> problem (add more cpus, drop specific packets, ...)
> - on Tx, detect that the link is overloaded, and take dispositions
> to solve the problem (notify flow control, drop specific
> packets)
>
> The patchset updates ixgbe, i40e, e1000, mlx5.
> The other drivers that implement the descriptor_done() API are
> fm10k, sfc, virtio. They are not updated.
> If the new API is accepted, the descriptor_done() can be deprecated,
> and examples/l3fwd-power will be updated to.
>
>
> RFC->v1:
> - instead of optimizing an API that returns the number of used
> descriptors like rx_queue_count(), use a more simple API that
> returns the status of a descriptor, like rx_descriptor_done().
> - remove ethdev api rework (first 2 patches), they have been
> sent separately
>
>
> Olivier Matz (6):
> ethdev: add descriptor status API
> net/ixgbe: implement descriptor status API
> net/e1000: implement descriptor status API (igb)
> net/e1000: implement descriptor status API (em)
> net/mlx5: implement descriptor status API
> net/i40e: implement descriptor status API
>
> drivers/net/e1000/e1000_ethdev.h | 10 +++++
> drivers/net/e1000/em_ethdev.c | 2 +
> drivers/net/e1000/em_rxtx.c | 49 ++++++++++++++++++++++
> drivers/net/e1000/igb_ethdev.c | 2 +
> drivers/net/e1000/igb_rxtx.c | 46 +++++++++++++++++++++
> drivers/net/i40e/i40e_ethdev.c | 2 +
> drivers/net/i40e/i40e_ethdev_vf.c | 2 +
> drivers/net/i40e/i40e_rxtx.c | 56 +++++++++++++++++++++++++
> drivers/net/i40e/i40e_rxtx.h | 4 ++
> drivers/net/ixgbe/ixgbe_ethdev.c | 4 ++
> drivers/net/ixgbe/ixgbe_ethdev.h | 5 +++
> drivers/net/ixgbe/ixgbe_rxtx.c | 55 +++++++++++++++++++++++++
> drivers/net/mlx5/mlx5.c | 2 +
> drivers/net/mlx5/mlx5_rxtx.c | 83 +++++++++++++++++++++++++++++++++++++
> drivers/net/mlx5/mlx5_rxtx.h | 2 +
> lib/librte_ether/rte_ethdev.h | 86 +++++++++++++++++++++++++++++++++++++++
> 16 files changed, 410 insertions(+)
>
Could you update examples to use this?
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
2017-03-01 18:07 ` Stephen Hemminger
@ 2017-03-02 13:43 ` Olivier Matz
2017-03-06 10:41 ` Thomas Monjalon
0 siblings, 1 reply; 72+ messages in thread
From: Olivier Matz @ 2017-03-02 13:43 UTC (permalink / raw)
To: Stephen Hemminger
Cc: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro,
ferruh.yigit, bruce.richardson
Hi Stephen,
On Wed, 1 Mar 2017 10:07:06 -0800, Stephen Hemminger <stephen@networkplumber.org> wrote:
> On Wed, 1 Mar 2017 18:19:06 +0100
> Olivier Matz <olivier.matz@6wind.com> wrote:
>
> > This patchset introduces a new ethdev API:
> > - rte_eth_rx_descriptor_status()
> > - rte_eth_tx_descriptor_status()
> >
> > The Rx API is aims to replace rte_eth_rx_descriptor_done() which
> > does almost the same, but does not differentiate the case of a
> > descriptor used by the driver (not returned to the hw).
> >
> > The usage of these functions can be:
> > - on Rx, anticipate that the cpu is not fast enough to process
> > all incoming packets, and take dispositions to solve the
> > problem (add more cpus, drop specific packets, ...)
> > - on Tx, detect that the link is overloaded, and take dispositions
> > to solve the problem (notify flow control, drop specific
> > packets)
> >
> > The patchset updates ixgbe, i40e, e1000, mlx5.
> > The other drivers that implement the descriptor_done() API are
> > fm10k, sfc, virtio. They are not updated.
> > If the new API is accepted, the descriptor_done() can be deprecated,
> > and examples/l3fwd-power will be updated to.
> >
> >
> > RFC->v1:
> > - instead of optimizing an API that returns the number of used
> > descriptors like rx_queue_count(), use a more simple API that
> > returns the status of a descriptor, like rx_descriptor_done().
> > - remove ethdev api rework (first 2 patches), they have been
> > sent separately
> >
> >
> > Olivier Matz (6):
> > ethdev: add descriptor status API
> > net/ixgbe: implement descriptor status API
> > net/e1000: implement descriptor status API (igb)
> > net/e1000: implement descriptor status API (em)
> > net/mlx5: implement descriptor status API
> > net/i40e: implement descriptor status API
> >
> > drivers/net/e1000/e1000_ethdev.h | 10 +++++
> > drivers/net/e1000/em_ethdev.c | 2 +
> > drivers/net/e1000/em_rxtx.c | 49 ++++++++++++++++++++++
> > drivers/net/e1000/igb_ethdev.c | 2 +
> > drivers/net/e1000/igb_rxtx.c | 46 +++++++++++++++++++++
> > drivers/net/i40e/i40e_ethdev.c | 2 +
> > drivers/net/i40e/i40e_ethdev_vf.c | 2 +
> > drivers/net/i40e/i40e_rxtx.c | 56 +++++++++++++++++++++++++
> > drivers/net/i40e/i40e_rxtx.h | 4 ++
> > drivers/net/ixgbe/ixgbe_ethdev.c | 4 ++
> > drivers/net/ixgbe/ixgbe_ethdev.h | 5 +++
> > drivers/net/ixgbe/ixgbe_rxtx.c | 55 +++++++++++++++++++++++++
> > drivers/net/mlx5/mlx5.c | 2 +
> > drivers/net/mlx5/mlx5_rxtx.c | 83 +++++++++++++++++++++++++++++++++++++
> > drivers/net/mlx5/mlx5_rxtx.h | 2 +
> > lib/librte_ether/rte_ethdev.h | 86 +++++++++++++++++++++++++++++++++++++++
> > 16 files changed, 410 insertions(+)
> >
>
> Could you update examples to use this?
I can update examples/l3fwd-power, but it will break the
support for drivers that do not implement the new API. Maybe we could
do this in a second time, after all drivers are converted?
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
2017-03-02 13:43 ` Olivier Matz
@ 2017-03-06 10:41 ` Thomas Monjalon
0 siblings, 0 replies; 72+ messages in thread
From: Thomas Monjalon @ 2017-03-06 10:41 UTC (permalink / raw)
To: Olivier Matz
Cc: Stephen Hemminger, dev, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro,
ferruh.yigit, bruce.richardson
2017-03-02 14:43, Olivier Matz:
> Hi Stephen,
>
> On Wed, 1 Mar 2017 10:07:06 -0800, Stephen Hemminger <stephen@networkplumber.org> wrote:
> > On Wed, 1 Mar 2017 18:19:06 +0100
> > Olivier Matz <olivier.matz@6wind.com> wrote:
> >
> > > This patchset introduces a new ethdev API:
> > > - rte_eth_rx_descriptor_status()
> > > - rte_eth_tx_descriptor_status()
[...]
> > Could you update examples to use this?
>
> I can update examples/l3fwd-power, but it will break the
> support for drivers that do not implement the new API. Maybe we could
> do this in a second time, after all drivers are converted?
Yes, good idea
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
2017-03-01 17:19 ` [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors Olivier Matz
` (7 preceding siblings ...)
2017-03-01 18:07 ` Stephen Hemminger
@ 2017-03-02 15:32 ` Bruce Richardson
2017-03-02 16:14 ` Olivier Matz
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 " Olivier Matz
9 siblings, 1 reply; 72+ messages in thread
From: Bruce Richardson @ 2017-03-02 15:32 UTC (permalink / raw)
To: Olivier Matz
Cc: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro,
ferruh.yigit
On Wed, Mar 01, 2017 at 06:19:06PM +0100, Olivier Matz wrote:
> This patchset introduces a new ethdev API:
> - rte_eth_rx_descriptor_status()
> - rte_eth_tx_descriptor_status()
>
> The Rx API is aims to replace rte_eth_rx_descriptor_done() which
> does almost the same, but does not differentiate the case of a
> descriptor used by the driver (not returned to the hw).
>
> The usage of these functions can be:
> - on Rx, anticipate that the cpu is not fast enough to process
> all incoming packets, and take dispositions to solve the
> problem (add more cpus, drop specific packets, ...)
> - on Tx, detect that the link is overloaded, and take dispositions
> to solve the problem (notify flow control, drop specific
> packets)
>
Looking at it from a slightly higher level, are these APIs really going
to help in these situations? If something is overloaded, doing more work
by querying the ring status only makes things worse. I suspect that in
most cases better results can be got by just looking at the results of
RX and TX burst functions. For example, if RX burst is always returning
a full set of packets, chances are you are overloaded, or at least have
no scope for an unexpected burst or event.
Are these really needed for real applications? I suspect our trivial
l3fwd power example can be made to work ok without them.
Regards,
/Bruce
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
2017-03-02 15:32 ` Bruce Richardson
@ 2017-03-02 16:14 ` Olivier Matz
2017-03-03 16:18 ` Venkatesan, Venky
0 siblings, 1 reply; 72+ messages in thread
From: Olivier Matz @ 2017-03-02 16:14 UTC (permalink / raw)
To: Bruce Richardson
Cc: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro,
ferruh.yigit
On Thu, 2 Mar 2017 15:32:15 +0000, Bruce Richardson <bruce.richardson@intel.com> wrote:
> On Wed, Mar 01, 2017 at 06:19:06PM +0100, Olivier Matz wrote:
> > This patchset introduces a new ethdev API:
> > - rte_eth_rx_descriptor_status()
> > - rte_eth_tx_descriptor_status()
> >
> > The Rx API is aims to replace rte_eth_rx_descriptor_done() which
> > does almost the same, but does not differentiate the case of a
> > descriptor used by the driver (not returned to the hw).
> >
> > The usage of these functions can be:
> > - on Rx, anticipate that the cpu is not fast enough to process
> > all incoming packets, and take dispositions to solve the
> > problem (add more cpus, drop specific packets, ...)
> > - on Tx, detect that the link is overloaded, and take dispositions
> > to solve the problem (notify flow control, drop specific
> > packets)
> >
> Looking at it from a slightly higher level, are these APIs really going
> to help in these situations? If something is overloaded, doing more work
> by querying the ring status only makes things worse. I suspect that in
> most cases better results can be got by just looking at the results of
> RX and TX burst functions. For example, if RX burst is always returning
> a full set of packets, chances are you are overloaded, or at least have
> no scope for an unexpected burst or event.
>
> Are these really needed for real applications? I suspect our trivial
> l3fwd power example can be made to work ok without them.
The l3fwd example uses the rte_eth_rx_descriptor_done() API, which
is very similar to what I'm adding here. The differences are:
- the new lib provides a Tx counterpart
- it differentiates done/avail/hold descriptors
The alternative was to update the descriptor_done API, but
I think we agreed to do that in this thread:
http://www.dpdk.org/ml/archives/dev/2017-January/054947.html
About the usefulness of the API, I confirm it is useful: for
instance, you can detect that you ring is more than half-full, and
take dispositions to increase your processing power or select the
packets you want to drop first.
Regards
Olivier
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
2017-03-02 16:14 ` Olivier Matz
@ 2017-03-03 16:18 ` Venkatesan, Venky
2017-03-03 16:45 ` Olivier Matz
0 siblings, 1 reply; 72+ messages in thread
From: Venkatesan, Venky @ 2017-03-03 16:18 UTC (permalink / raw)
To: Olivier Matz, Richardson, Bruce
Cc: dev, thomas.monjalon, Ananyev, Konstantin, Lu, Wenzhuo, Zhang,
Helin, Wu, Jingjing, adrien.mazarguil, nelio.laranjeiro, Yigit,
Ferruh
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Olivier Matz
> Sent: Thursday, March 2, 2017 8:15 AM
> To: Richardson, Bruce <bruce.richardson@intel.com>
> Cc: dev@dpdk.org; thomas.monjalon@6wind.com; Ananyev, Konstantin
> <konstantin.ananyev@intel.com>; Lu, Wenzhuo <wenzhuo.lu@intel.com>;
> Zhang, Helin <helin.zhang@intel.com>; Wu, Jingjing
> <jingjing.wu@intel.com>; adrien.mazarguil@6wind.com;
> nelio.laranjeiro@6wind.com; Yigit, Ferruh <ferruh.yigit@intel.com>
> Subject: Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
>
> On Thu, 2 Mar 2017 15:32:15 +0000, Bruce Richardson
> <bruce.richardson@intel.com> wrote:
> > On Wed, Mar 01, 2017 at 06:19:06PM +0100, Olivier Matz wrote:
> > > This patchset introduces a new ethdev API:
> > > - rte_eth_rx_descriptor_status()
> > > - rte_eth_tx_descriptor_status()
> > >
> > > The Rx API is aims to replace rte_eth_rx_descriptor_done() which
> > > does almost the same, but does not differentiate the case of a
> > > descriptor used by the driver (not returned to the hw).
> > >
> > > The usage of these functions can be:
> > > - on Rx, anticipate that the cpu is not fast enough to process
> > > all incoming packets, and take dispositions to solve the
> > > problem (add more cpus, drop specific packets, ...)
> > > - on Tx, detect that the link is overloaded, and take dispositions
> > > to solve the problem (notify flow control, drop specific
> > > packets)
> > >
> > Looking at it from a slightly higher level, are these APIs really
> > going to help in these situations? If something is overloaded, doing
> > more work by querying the ring status only makes things worse. I
> > suspect that in most cases better results can be got by just looking
> > at the results of RX and TX burst functions. For example, if RX burst
> > is always returning a full set of packets, chances are you are
> > overloaded, or at least have no scope for an unexpected burst or event.
> >
> > Are these really needed for real applications? I suspect our trivial
> > l3fwd power example can be made to work ok without them.
>
> The l3fwd example uses the rte_eth_rx_descriptor_done() API, which is very
> similar to what I'm adding here. The differences are:
>
> - the new lib provides a Tx counterpart
> - it differentiates done/avail/hold descriptors
>
> The alternative was to update the descriptor_done API, but I think we
> agreed to do that in this thread:
> http://www.dpdk.org/ml/archives/dev/2017-January/054947.html
>
> About the usefulness of the API, I confirm it is useful: for instance, you can
> detect that you ring is more than half-full, and take dispositions to increase
> your processing power or select the packets you want to drop first.
>
For either of those cases, you could still implement this in your application without any of these APIs. Simply keep reading rx_burst() till it returns zero. You now have all the packets that you want - look at how many and increase your processing power, or drop them.
The issue I have with this newer instantiation of the API is that it is essentially to pick up a descriptor at a specified offset. In most cases, if you plan to read far enough ahead with the API (let's say 16 or 32 ahead, or even more), you are almost always guaranteed an L1/L2 miss - essentially making it a costly API call. In cases that don't have something like Data Direct I/O (DDIO), you are now going to hit memory and stall the CPU for a long time. In any case, the API becomes pretty useless unless you want to stay within a smaller look ahead offset. The rx_burst() methodology simply works better in most circumstances, and allows application level control.
So, NAK. My suggestion would be to go back to the older API.
-Venky
> Regards
> Olivier
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
2017-03-03 16:18 ` Venkatesan, Venky
@ 2017-03-03 16:45 ` Olivier Matz
2017-03-03 18:46 ` Venkatesan, Venky
0 siblings, 1 reply; 72+ messages in thread
From: Olivier Matz @ 2017-03-03 16:45 UTC (permalink / raw)
To: Venkatesan, Venky
Cc: Richardson, Bruce, dev, thomas.monjalon, Ananyev, Konstantin, Lu,
Wenzhuo, Zhang, Helin, Wu, Jingjing, adrien.mazarguil,
nelio.laranjeiro, Yigit, Ferruh
Hi Venky,
On Fri, 3 Mar 2017 16:18:52 +0000, "Venkatesan, Venky" <venky.venkatesan@intel.com> wrote:
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Olivier Matz
> > Sent: Thursday, March 2, 2017 8:15 AM
> > To: Richardson, Bruce <bruce.richardson@intel.com>
> > Cc: dev@dpdk.org; thomas.monjalon@6wind.com; Ananyev, Konstantin
> > <konstantin.ananyev@intel.com>; Lu, Wenzhuo <wenzhuo.lu@intel.com>;
> > Zhang, Helin <helin.zhang@intel.com>; Wu, Jingjing
> > <jingjing.wu@intel.com>; adrien.mazarguil@6wind.com;
> > nelio.laranjeiro@6wind.com; Yigit, Ferruh <ferruh.yigit@intel.com>
> > Subject: Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
> >
> > On Thu, 2 Mar 2017 15:32:15 +0000, Bruce Richardson
> > <bruce.richardson@intel.com> wrote:
> > > On Wed, Mar 01, 2017 at 06:19:06PM +0100, Olivier Matz wrote:
> > > > This patchset introduces a new ethdev API:
> > > > - rte_eth_rx_descriptor_status()
> > > > - rte_eth_tx_descriptor_status()
> > > >
> > > > The Rx API is aims to replace rte_eth_rx_descriptor_done() which
> > > > does almost the same, but does not differentiate the case of a
> > > > descriptor used by the driver (not returned to the hw).
> > > >
> > > > The usage of these functions can be:
> > > > - on Rx, anticipate that the cpu is not fast enough to process
> > > > all incoming packets, and take dispositions to solve the
> > > > problem (add more cpus, drop specific packets, ...)
> > > > - on Tx, detect that the link is overloaded, and take dispositions
> > > > to solve the problem (notify flow control, drop specific
> > > > packets)
> > > >
> > > Looking at it from a slightly higher level, are these APIs really
> > > going to help in these situations? If something is overloaded, doing
> > > more work by querying the ring status only makes things worse. I
> > > suspect that in most cases better results can be got by just looking
> > > at the results of RX and TX burst functions. For example, if RX burst
> > > is always returning a full set of packets, chances are you are
> > > overloaded, or at least have no scope for an unexpected burst or event.
> > >
> > > Are these really needed for real applications? I suspect our trivial
> > > l3fwd power example can be made to work ok without them.
> >
> > The l3fwd example uses the rte_eth_rx_descriptor_done() API, which is very
> > similar to what I'm adding here. The differences are:
> >
> > - the new lib provides a Tx counterpart
> > - it differentiates done/avail/hold descriptors
> >
> > The alternative was to update the descriptor_done API, but I think we
> > agreed to do that in this thread:
> > http://www.dpdk.org/ml/archives/dev/2017-January/054947.html
> >
> > About the usefulness of the API, I confirm it is useful: for instance, you can
> > detect that you ring is more than half-full, and take dispositions to increase
> > your processing power or select the packets you want to drop first.
> >
> For either of those cases, you could still implement this in your application without any of these APIs. Simply keep reading rx_burst() till it returns zero. You now have all the packets that you want - look at how many and increase your processing power, or drop them.
In my use case, I may have several thresholds, so it gives a fast information
about the ring status.
Keeping reading rx_burst() until it returns 0 will not work if the packet
rate is higher than (or close to) what the cpu is able to eat.
>
> The issue I have with this newer instantiation of the API is that it is essentially to pick up a descriptor at a specified offset. In most cases, if you plan to read far enough ahead with the API (let's say 16 or 32 ahead, or even more), you are almost always guaranteed an L1/L2 miss - essentially making it a costly API call. In cases that don't have something like Data Direct I/O (DDIO), you are now going to hit memory and stall the CPU for a long time. In any case, the API becomes pretty useless unless you want to stay within a smaller look ahead offset. The rx_burst() methodology simply works better in most circumstances, and allows application level control.
>
> So, NAK. My suggestion would be to go back to the older API.
I don't understand the reason of your nack.
The old API is there (for Rx it works the same), and it is illustrated
in an example. Since your arguments also applies to the old API, so why
are you saying we should keep the older API?
For Tx, I want to know if I have enough room to send my packets before
doing it. There is no API yet to do that.
And yes, this could trigger cache misses, but in some situations
it's preferable to be a bit slower (all tests are not test-iofwd)
and be able to anticipate that the ring is getting full.
Regards,
Olivier
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
2017-03-03 16:45 ` Olivier Matz
@ 2017-03-03 18:46 ` Venkatesan, Venky
2017-03-04 20:45 ` Olivier Matz
0 siblings, 1 reply; 72+ messages in thread
From: Venkatesan, Venky @ 2017-03-03 18:46 UTC (permalink / raw)
To: Olivier Matz
Cc: Richardson, Bruce, dev, thomas.monjalon, Ananyev, Konstantin, Lu,
Wenzhuo, Zhang, Helin, Wu, Jingjing, adrien.mazarguil,
nelio.laranjeiro, Yigit, Ferruh
Hi Olivier,
> -----Original Message-----
> From: Olivier Matz [mailto:olivier.matz@6wind.com]
> Sent: Friday, March 3, 2017 8:45 AM
> To: Venkatesan, Venky <venky.venkatesan@intel.com>
> Cc: Richardson, Bruce <bruce.richardson@intel.com>; dev@dpdk.org;
> thomas.monjalon@6wind.com; Ananyev, Konstantin
> <konstantin.ananyev@intel.com>; Lu, Wenzhuo <wenzhuo.lu@intel.com>;
> Zhang, Helin <helin.zhang@intel.com>; Wu, Jingjing
> <jingjing.wu@intel.com>; adrien.mazarguil@6wind.com;
> nelio.laranjeiro@6wind.com; Yigit, Ferruh <ferruh.yigit@intel.com>
> Subject: Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
>
> Hi Venky,
>
> On Fri, 3 Mar 2017 16:18:52 +0000, "Venkatesan, Venky"
> <venky.venkatesan@intel.com> wrote:
> > > -----Original Message-----
> > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Olivier Matz
> > > Sent: Thursday, March 2, 2017 8:15 AM
> > > To: Richardson, Bruce <bruce.richardson@intel.com>
> > > Cc: dev@dpdk.org; thomas.monjalon@6wind.com; Ananyev, Konstantin
> > > <konstantin.ananyev@intel.com>; Lu, Wenzhuo
> <wenzhuo.lu@intel.com>;
> > > Zhang, Helin <helin.zhang@intel.com>; Wu, Jingjing
> > > <jingjing.wu@intel.com>; adrien.mazarguil@6wind.com;
> > > nelio.laranjeiro@6wind.com; Yigit, Ferruh <ferruh.yigit@intel.com>
> > > Subject: Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx
> > > descriptors
> > >
> > > On Thu, 2 Mar 2017 15:32:15 +0000, Bruce Richardson
> > > <bruce.richardson@intel.com> wrote:
> > > > On Wed, Mar 01, 2017 at 06:19:06PM +0100, Olivier Matz wrote:
> > > > > This patchset introduces a new ethdev API:
> > > > > - rte_eth_rx_descriptor_status()
> > > > > - rte_eth_tx_descriptor_status()
> > > > >
> > > > > The Rx API is aims to replace rte_eth_rx_descriptor_done() which
> > > > > does almost the same, but does not differentiate the case of a
> > > > > descriptor used by the driver (not returned to the hw).
> > > > >
> > > > > The usage of these functions can be:
> > > > > - on Rx, anticipate that the cpu is not fast enough to process
> > > > > all incoming packets, and take dispositions to solve the
> > > > > problem (add more cpus, drop specific packets, ...)
> > > > > - on Tx, detect that the link is overloaded, and take dispositions
> > > > > to solve the problem (notify flow control, drop specific
> > > > > packets)
> > > > >
> > > > Looking at it from a slightly higher level, are these APIs really
> > > > going to help in these situations? If something is overloaded,
> > > > doing more work by querying the ring status only makes things
> > > > worse. I suspect that in most cases better results can be got by
> > > > just looking at the results of RX and TX burst functions. For
> > > > example, if RX burst is always returning a full set of packets,
> > > > chances are you are overloaded, or at least have no scope for an
> unexpected burst or event.
> > > >
> > > > Are these really needed for real applications? I suspect our
> > > > trivial l3fwd power example can be made to work ok without them.
> > >
> > > The l3fwd example uses the rte_eth_rx_descriptor_done() API, which
> > > is very similar to what I'm adding here. The differences are:
> > >
> > > - the new lib provides a Tx counterpart
> > > - it differentiates done/avail/hold descriptors
> > >
> > > The alternative was to update the descriptor_done API, but I think
> > > we agreed to do that in this thread:
> > > http://www.dpdk.org/ml/archives/dev/2017-January/054947.html
> > >
> > > About the usefulness of the API, I confirm it is useful: for
> > > instance, you can detect that you ring is more than half-full, and
> > > take dispositions to increase your processing power or select the packets
> you want to drop first.
> > >
> > For either of those cases, you could still implement this in your application
> without any of these APIs. Simply keep reading rx_burst() till it returns zero.
> You now have all the packets that you want - look at how many and increase
> your processing power, or drop them.
>
> In my use case, I may have several thresholds, so it gives a fast information
> about the ring status.
The problem is that it costs too much to return that status. Let me explain it this way - when processing a burst, it takes the IXGBE driver ~20 - 25 cycles to process a packet. Assuming memory latency is 75ns, a miss to memory costs ~150 cycles at 2.0 GHz, or 215 cycles at 3.0 GHz. Either way, it is between 7 - 10 packet times if you miss to memory. In the case you are suggesting where the CPU isn't able to keep up with the packets, all we've have really done is to make it harder for the CPU to keep up.
Could you use an RX alternative that returns a 0 or 1 if there are more packets remaining in the ring? That will be lower cost to implement (as a separate API or even as a part of the Rx_burst API itself). But touching the ring at a random offset is almost always going to be a performance problem.
>
> Keeping reading rx_burst() until it returns 0 will not work if the packet rate is
> higher than (or close to) what the cpu is able to eat.
>
If the packet input rate is higher than what the CPU is capable of handling, reading the packets gives you the option of dropping those that you consider lower priority - if you have an application that takes 400 cycles to process a packet, but the input rate is a packet every 100 cycles, then what you have to look at is to read the packets, figure out a lighter weight way of determining a drop per packet (easy suggestion, use the RX filter API to tag packets) and drop them within 10-20 cycles per packet. Ideally, you would do this by draining some percentage of the descriptor ring and prioritizing and dropping those. A second, even better alternative is to use NIC facilities to prioritize packets into different queues. I don't see how adding another 150 cycles to the budget helps you keep up with packets.
> >
> > The issue I have with this newer instantiation of the API is that it is
> essentially to pick up a descriptor at a specified offset. In most cases, if you
> plan to read far enough ahead with the API (let's say 16 or 32 ahead, or even
> more), you are almost always guaranteed an L1/L2 miss - essentially making it
> a costly API call. In cases that don't have something like Data Direct I/O
> (DDIO), you are now going to hit memory and stall the CPU for a long time. In
> any case, the API becomes pretty useless unless you want to stay within a
> smaller look ahead offset. The rx_burst() methodology simply works better
> in most circumstances, and allows application level control.
> >
> > So, NAK. My suggestion would be to go back to the older API.
>
> I don't understand the reason of your nack.
> The old API is there (for Rx it works the same), and it is illustrated in an
> example. Since your arguments also applies to the old API, so why are you
> saying we should keep the older API?
>
I am not a fan of the old API either. In hindsight, it was a mistake (which we didn't catch in time). As Bruce suggested, the example should be reworked to work without the API, and deprecate it.
> For Tx, I want to know if I have enough room to send my packets before
> doing it. There is no API yet to do that.
>
Yes. This could be a lightweight API if it returned a count (txq->nb_tx_free) instead of actually touching the ring, which is what I have a problem with. If the implementation changes to that, that may be okay to do. The Tx API has more merit than the Rx API, but not coded around an offset.
> And yes, this could trigger cache misses, but in some situations it's preferable
> to be a bit slower (all tests are not test-iofwd) and be able to anticipate that
> the ring is getting full.
>
>
> Regards,
> Olivier
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
2017-03-03 18:46 ` Venkatesan, Venky
@ 2017-03-04 20:45 ` Olivier Matz
2017-03-06 11:02 ` Thomas Monjalon
0 siblings, 1 reply; 72+ messages in thread
From: Olivier Matz @ 2017-03-04 20:45 UTC (permalink / raw)
To: Venkatesan, Venky, thomas.monjalon
Cc: Richardson, Bruce, dev, Ananyev, Konstantin, Lu, Wenzhuo, Zhang,
Helin, Wu, Jingjing, adrien.mazarguil, nelio.laranjeiro, Yigit,
Ferruh
On Fri, 3 Mar 2017 18:46:52 +0000, "Venkatesan, Venky" <venky.venkatesan@intel.com> wrote:
> Hi Olivier,
>
> > -----Original Message-----
> > From: Olivier Matz [mailto:olivier.matz@6wind.com]
> > Sent: Friday, March 3, 2017 8:45 AM
> > To: Venkatesan, Venky <venky.venkatesan@intel.com>
> > Cc: Richardson, Bruce <bruce.richardson@intel.com>; dev@dpdk.org;
> > thomas.monjalon@6wind.com; Ananyev, Konstantin
> > <konstantin.ananyev@intel.com>; Lu, Wenzhuo <wenzhuo.lu@intel.com>;
> > Zhang, Helin <helin.zhang@intel.com>; Wu, Jingjing
> > <jingjing.wu@intel.com>; adrien.mazarguil@6wind.com;
> > nelio.laranjeiro@6wind.com; Yigit, Ferruh <ferruh.yigit@intel.com>
> > Subject: Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
> >
> > Hi Venky,
> >
> > On Fri, 3 Mar 2017 16:18:52 +0000, "Venkatesan, Venky"
> > <venky.venkatesan@intel.com> wrote:
> > > > -----Original Message-----
> > > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Olivier Matz
> > > > Sent: Thursday, March 2, 2017 8:15 AM
> > > > To: Richardson, Bruce <bruce.richardson@intel.com>
> > > > Cc: dev@dpdk.org; thomas.monjalon@6wind.com; Ananyev, Konstantin
> > > > <konstantin.ananyev@intel.com>; Lu, Wenzhuo
> > <wenzhuo.lu@intel.com>;
> > > > Zhang, Helin <helin.zhang@intel.com>; Wu, Jingjing
> > > > <jingjing.wu@intel.com>; adrien.mazarguil@6wind.com;
> > > > nelio.laranjeiro@6wind.com; Yigit, Ferruh <ferruh.yigit@intel.com>
> > > > Subject: Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx
> > > > descriptors
> > > >
> > > > On Thu, 2 Mar 2017 15:32:15 +0000, Bruce Richardson
> > > > <bruce.richardson@intel.com> wrote:
> > > > > On Wed, Mar 01, 2017 at 06:19:06PM +0100, Olivier Matz wrote:
> > > > > > This patchset introduces a new ethdev API:
> > > > > > - rte_eth_rx_descriptor_status()
> > > > > > - rte_eth_tx_descriptor_status()
> > > > > >
> > > > > > The Rx API is aims to replace rte_eth_rx_descriptor_done() which
> > > > > > does almost the same, but does not differentiate the case of a
> > > > > > descriptor used by the driver (not returned to the hw).
> > > > > >
> > > > > > The usage of these functions can be:
> > > > > > - on Rx, anticipate that the cpu is not fast enough to process
> > > > > > all incoming packets, and take dispositions to solve the
> > > > > > problem (add more cpus, drop specific packets, ...)
> > > > > > - on Tx, detect that the link is overloaded, and take dispositions
> > > > > > to solve the problem (notify flow control, drop specific
> > > > > > packets)
> > > > > >
> > > > > Looking at it from a slightly higher level, are these APIs really
> > > > > going to help in these situations? If something is overloaded,
> > > > > doing more work by querying the ring status only makes things
> > > > > worse. I suspect that in most cases better results can be got by
> > > > > just looking at the results of RX and TX burst functions. For
> > > > > example, if RX burst is always returning a full set of packets,
> > > > > chances are you are overloaded, or at least have no scope for an
> > unexpected burst or event.
> > > > >
> > > > > Are these really needed for real applications? I suspect our
> > > > > trivial l3fwd power example can be made to work ok without them.
> > > >
> > > > The l3fwd example uses the rte_eth_rx_descriptor_done() API, which
> > > > is very similar to what I'm adding here. The differences are:
> > > >
> > > > - the new lib provides a Tx counterpart
> > > > - it differentiates done/avail/hold descriptors
> > > >
> > > > The alternative was to update the descriptor_done API, but I think
> > > > we agreed to do that in this thread:
> > > > http://www.dpdk.org/ml/archives/dev/2017-January/054947.html
> > > >
> > > > About the usefulness of the API, I confirm it is useful: for
> > > > instance, you can detect that you ring is more than half-full, and
> > > > take dispositions to increase your processing power or select the packets
> > you want to drop first.
> > > >
> > > For either of those cases, you could still implement this in your application
> > without any of these APIs. Simply keep reading rx_burst() till it returns zero.
> > You now have all the packets that you want - look at how many and increase
> > your processing power, or drop them.
> >
> > In my use case, I may have several thresholds, so it gives a fast information
> > about the ring status.
>
> The problem is that it costs too much to return that status. Let me explain it this way - when processing a burst, it takes the IXGBE driver ~20 - 25 cycles to process a packet. Assuming memory latency is 75ns, a miss to memory costs ~150 cycles at 2.0 GHz, or 215 cycles at 3.0 GHz. Either way, it is between 7 - 10 packet times if you miss to memory. In the case you are suggesting where the CPU isn't able to keep up with the packets, all we've have really done is to make it harder for the CPU to keep up.
Did you do the test to validate what you say? I did it.
Let's add the following patch to testpmd:
--- a/app/test-pmd/iofwd.c
+++ b/app/test-pmd/iofwd.c
@@ -92,6 +92,8 @@ pkt_burst_io_forward(struct fwd_stream *fs)
start_tsc = rte_rdtsc();
#endif
+ rte_eth_rx_descriptor_status(fs->rx_port, fs->rx_queue, 128);
+
/*
* Receive a burst of packets and forward them.
*/
If I measure the performance in iofwd (nb_rxd=512), I see no difference
between the results with and without the patch.
To me, your calculation does not apply to a real life application:
- this function is called once per burst (32 or 64), so the penalty
of 200 cycles (if any) has to be divided by the number of packets
- you need to take in account the number of cycles for the whole
processing of a packet, not for the ixgbe driver only. If you
are doing forwarding, you are at least at 100 cycles / packet for
a benchmark test case. I don't even talk about IPsec.
So, the penalty, in the worst case (burst of 32, 100c/pkt) is ~6%.
Given the information it provides, it is acceptable to me.
Note we are talking here about an optional API, that would only impact
people that use it.
> Could you use an RX alternative that returns a 0 or 1 if there are more packets remaining in the ring? That will be lower cost to implement (as a separate API or even as a part of the Rx_burst API itself). But touching the ring at a random offset is almost always going to be a performance problem.
About returning 0 or 1 if there are more packets in the ring, it does
not solve my issue since I want to know if the number of descriptor is
above or below a configurable threshold.
Also, changing the Rx burst function is much more likely to be refused
than adding an optional API.
> > Keeping reading rx_burst() until it returns 0 will not work if the packet rate is
> > higher than (or close to) what the cpu is able to eat.
> >
>
> If the packet input rate is higher than what the CPU is capable of handling, reading the packets gives you the option of dropping those that you consider lower priority - if you have an application that takes 400 cycles to process a packet, but the input rate is a packet every 100 cycles, then what you have to look at is to read the packets, figure out a lighter weight way of determining a drop per packet (easy suggestion, use the RX filter API to tag packets) and drop them within 10-20 cycles per packet. Ideally, you would do this by draining some percentage of the descriptor ring and prioritizing and dropping those. A second, even better alternative is to use NIC facilities to prioritize packets into different queues. I don't see how adding another 150 cycles to the budget helps you keep up with packets.
The RX filter API is not available on all drivers, and is not as flexible
as a software filter. If I use this new API, I don't need to call this
software filter when the CPU is not overload, saving cycles in the common
case.
Trying to read all the packets in the ring before processing them is not
an option either, especially if the ring size is large (4096). This would
consumes more mbufs (hw ring + sw processing queue), it will also break
the mbuf prefetch policies done in the drivers.
> > > The issue I have with this newer instantiation of the API is that it is
> > essentially to pick up a descriptor at a specified offset. In most cases, if you
> > plan to read far enough ahead with the API (let's say 16 or 32 ahead, or even
> > more), you are almost always guaranteed an L1/L2 miss - essentially making it
> > a costly API call. In cases that don't have something like Data Direct I/O
> > (DDIO), you are now going to hit memory and stall the CPU for a long time. In
> > any case, the API becomes pretty useless unless you want to stay within a
> > smaller look ahead offset. The rx_burst() methodology simply works better
> > in most circumstances, and allows application level control.
> > >
> > > So, NAK. My suggestion would be to go back to the older API.
> >
> > I don't understand the reason of your nack.
> > The old API is there (for Rx it works the same), and it is illustrated in an
> > example. Since your arguments also applies to the old API, so why are you
> > saying we should keep the older API?
> >
>
> I am not a fan of the old API either. In hindsight, it was a mistake (which we didn't catch in time). As Bruce suggested, the example should be reworked to work without the API, and deprecate it.
Before deprecating an API, I think we should check if people are using
it and if it can really be replaced. I think there are many things that
could be deprecated before this one.
> > For Tx, I want to know if I have enough room to send my packets before
> > doing it. There is no API yet to do that.
> >
>
> Yes. This could be a lightweight API if it returned a count (txq->nb_tx_free) instead of actually touching the ring, which is what I have a problem with. If the implementation changes to that, that may be okay to do. The Tx API has more merit than the Rx API, but not coded around an offset.
Returning txq->nb_tx_free does not work because it is a software view,
which becomes wrong as soon as the hardware has send the packets.
Example:
1. Send many packets at very high rate, the tx ring becomes full
2. wait that packets are transmitted
3. read nb_tx_free, it returns 0, which is not what I want
So in my case there is a also a need for a Tx descriptor status API.
Thomas, you are the maintainer of ethdev API, do you have an opinion?
Regards,
Olivier
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors
2017-03-04 20:45 ` Olivier Matz
@ 2017-03-06 11:02 ` Thomas Monjalon
0 siblings, 0 replies; 72+ messages in thread
From: Thomas Monjalon @ 2017-03-06 11:02 UTC (permalink / raw)
To: Olivier Matz
Cc: Venkatesan, Venky, Richardson, Bruce, dev, Ananyev, Konstantin,
Lu, Wenzhuo, Zhang, Helin, Wu, Jingjing, adrien.mazarguil,
nelio.laranjeiro, Yigit, Ferruh
2017-03-04 21:45, Olivier Matz:
> "Venkatesan, Venky" <venky.venkatesan@intel.com> wrote:
> > From: Olivier Matz
> > > On Fri, 3 Mar 2017 16:18:52 +0000, "Venkatesan, Venky" wrote:
> > > > From: Olivier Matz
> > > > > On Thu, 2 Mar 2017 15:32:15 +0000, Bruce Richardson wrote:
> > > > > > On Wed, Mar 01, 2017 at 06:19:06PM +0100, Olivier Matz wrote:
> > > > > > > The usage of these functions can be:
> > > > > > > - on Rx, anticipate that the cpu is not fast enough to process
> > > > > > > all incoming packets, and take dispositions to solve the
> > > > > > > problem (add more cpus, drop specific packets, ...)
> > > > > > > - on Tx, detect that the link is overloaded, and take dispositions
> > > > > > > to solve the problem (notify flow control, drop specific
> > > > > > > packets)
> > > > > > >
[...]
> > > > > > Are these really needed for real applications? I suspect our
> > > > > > trivial l3fwd power example can be made to work ok without them.
OK, please remove the use of such old API in the example.
[...]
> So, the penalty, in the worst case (burst of 32, 100c/pkt) is ~6%.
> Given the information it provides, it is acceptable to me.
Any penalty is acceptable, given it is not mandatory to call these functions.
> Note we are talking here about an optional API, that would only impact
> people that use it.
Yes, it just brings more information and can be used for some debug measures.
[...]
> Also, changing the Rx burst function is much more likely to be refused
> than adding an optional API.
Yes, changing Rx/Tx API is not really an option and does not bring so much
benefits.
[...]
> > > > So, NAK. My suggestion would be to go back to the older API.
> > >
> > > I don't understand the reason of your nack.
> > > The old API is there (for Rx it works the same), and it is illustrated in an
> > > example. Since your arguments also applies to the old API, so why are you
> > > saying we should keep the older API?
> > >
> >
> > I am not a fan of the old API either. In hindsight, it was a mistake
> > (which we didn't catch in time). As Bruce suggested, the example
> > should be reworked to work without the API, and deprecate it.
Agreed to deprecate the old API.
However, there is no relation with this new optional API.
> Before deprecating an API, I think we should check if people are using
> it and if it can really be replaced. I think there are many things that
> could be deprecated before this one.
Yes we can discuss a lot of things but let's focus on this one :)
> > > For Tx, I want to know if I have enough room to send my packets before
> > > doing it. There is no API yet to do that.
> >
> > Yes. This could be a lightweight API if it returned a count (txq->nb_tx_free) instead of actually touching the ring, which is what I have a problem with. If the implementation changes to that, that may be okay to do. The Tx API has more merit than the Rx API, but not coded around an offset.
>
> Returning txq->nb_tx_free does not work because it is a software view,
> which becomes wrong as soon as the hardware has send the packets.
> Example:
> 1. Send many packets at very high rate, the tx ring becomes full
> 2. wait that packets are transmitted
> 3. read nb_tx_free, it returns 0, which is not what I want
>
> So in my case there is a also a need for a Tx descriptor status API.
>
> Thomas, you are the maintainer of ethdev API, do you have an opinion?
You show some benefits and it does not hurt any existing API.
So we cannot reject such a feature, even if its best use is for debug
or specific applications.
I think the concern here was the fear of seeing this called in some
benchmark applications. You just have to highlight in the API doc that
there are some performance penalties.
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH v2 0/6] get status of Rx and Tx descriptors
2017-03-01 17:19 ` [dpdk-dev] [PATCH 0/6] get status of Rx and Tx descriptors Olivier Matz
` (8 preceding siblings ...)
2017-03-02 15:32 ` Bruce Richardson
@ 2017-03-07 15:59 ` Olivier Matz
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 1/6] ethdev: add descriptor status API Olivier Matz
` (6 more replies)
9 siblings, 7 replies; 72+ messages in thread
From: Olivier Matz @ 2017-03-07 15:59 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson, venky.venkatesan, arybchenko
This patchset introduces a new ethdev API:
- rte_eth_rx_descriptor_status()
- rte_eth_tx_descriptor_status()
The Rx API is aims to replace rte_eth_rx_descriptor_done() which
does almost the same, but does not differentiate the case of a
descriptor used by the driver (not returned to the hw).
The usage of these functions can be:
- on Rx, anticipate that the cpu is not fast enough to process
all incoming packets, and take dispositions to solve the
problem (add more cpus, drop specific packets, ...)
- on Tx, detect that the link is overloaded, and take dispositions
to solve the problem (notify flow control, drop specific
packets)
The patchset updates ixgbe, i40e, e1000, mlx5.
The other drivers that implement the descriptor_done() API are
fm10k, sfc, virtio. They are not updated.
If the new API is accepted, the descriptor_done() can be deprecated,
and examples/l3fwd-power will be updated to.
v1->v2:
- replace RTE_ETH_RX_DESC_USED by RTE_ETH_RX_DESC_UNAVAIL: it can be used when
the descriptor is hold by driver or reserved by the hardware.
- add RTE_ETH_TX_DESC_UNAVAIL (same for Tx)
- change the ethdev callback api to use a queue pointer instead of port_id
and queue_id
- like rx_burst/tx_burst, do not check the validity of port_id and queue_id
except in debug mode
- better document the calling context, error status, possible performance
impact
- add the feature in NIC documentation
- fix overflow of descriptor value in tx functions (ixgbe, igb, em)
- fix tx function to only check descs that have the rs bit (i40e)
- mlx: remove empty line
RFC->v1:
- instead of optimizing an API that returns the number of used
descriptors like rx_queue_count(), use a more simple API that
returns the status of a descriptor, like rx_descriptor_done().
- remove ethdev api rework (first 2 patches), they have been
sent separately
Olivier Matz (6):
ethdev: add descriptor status API
net/ixgbe: implement descriptor status API
net/e1000: implement descriptor status API (igb)
net/e1000: implement descriptor status API (em)
net/mlx5: implement descriptor status API
net/i40e: implement descriptor status API
doc/guides/nics/features/default.ini | 2 +
doc/guides/nics/features/e1000.ini | 2 +
doc/guides/nics/features/i40e.ini | 2 +
doc/guides/nics/features/i40e_vec.ini | 2 +
doc/guides/nics/features/i40e_vf.ini | 2 +
doc/guides/nics/features/i40e_vf_vec.ini | 2 +
doc/guides/nics/features/igb.ini | 2 +
doc/guides/nics/features/igb_vf.ini | 2 +
doc/guides/nics/features/ixgbe.ini | 2 +
doc/guides/nics/features/ixgbe_vec.ini | 2 +
doc/guides/nics/features/ixgbe_vf.ini | 2 +
doc/guides/nics/features/ixgbe_vf_vec.ini | 2 +
doc/guides/nics/features/mlx5.ini | 2 +
drivers/net/e1000/e1000_ethdev.h | 6 ++
drivers/net/e1000/em_ethdev.c | 2 +
drivers/net/e1000/em_rxtx.c | 51 ++++++++++++
drivers/net/e1000/igb_ethdev.c | 2 +
drivers/net/e1000/igb_rxtx.c | 45 +++++++++++
drivers/net/i40e/i40e_ethdev.c | 2 +
drivers/net/i40e/i40e_ethdev_vf.c | 2 +
drivers/net/i40e/i40e_rxtx.c | 58 ++++++++++++++
drivers/net/i40e/i40e_rxtx.h | 2 +
drivers/net/ixgbe/ixgbe_ethdev.c | 4 +
drivers/net/ixgbe/ixgbe_ethdev.h | 3 +
drivers/net/ixgbe/ixgbe_rxtx.c | 57 ++++++++++++++
drivers/net/mlx5/mlx5.c | 2 +
drivers/net/mlx5/mlx5_rxtx.c | 76 ++++++++++++++++++
drivers/net/mlx5/mlx5_rxtx.h | 2 +
lib/librte_ether/rte_ethdev.h | 125 ++++++++++++++++++++++++++++++
29 files changed, 465 insertions(+)
--
2.8.1
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH v2 1/6] ethdev: add descriptor status API
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 " Olivier Matz
@ 2017-03-07 15:59 ` Olivier Matz
2017-03-09 11:49 ` Andrew Rybchenko
2017-03-21 8:32 ` Yang, Qiming
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 2/6] net/ixgbe: implement " Olivier Matz
` (5 subsequent siblings)
6 siblings, 2 replies; 72+ messages in thread
From: Olivier Matz @ 2017-03-07 15:59 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson, venky.venkatesan, arybchenko
Introduce a new API to get the status of a descriptor.
For Rx, it is almost similar to rx_descriptor_done API, except it
differentiates "used" descriptors (which are hold by the driver and not
returned to the hardware).
For Tx, it is a new API.
The descriptor_done() API, and probably the rx_queue_count() API could
be replaced by this new API as soon as it is implemented on all PMDs.
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
doc/guides/nics/features/default.ini | 2 +
lib/librte_ether/rte_ethdev.h | 125 +++++++++++++++++++++++++++++++++++
2 files changed, 127 insertions(+)
diff --git a/doc/guides/nics/features/default.ini b/doc/guides/nics/features/default.ini
index 9e363ff..0e6a78d 100644
--- a/doc/guides/nics/features/default.ini
+++ b/doc/guides/nics/features/default.ini
@@ -49,6 +49,8 @@ Inner L3 checksum =
Inner L4 checksum =
Packet type parsing =
Timesync =
+Rx Descriptor Status =
+Tx Descriptor Status =
Basic stats =
Extended stats =
Stats per queue =
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 97f3e2d..904ecbe 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1179,6 +1179,12 @@ typedef uint32_t (*eth_rx_queue_count_t)(struct rte_eth_dev *dev,
typedef int (*eth_rx_descriptor_done_t)(void *rxq, uint16_t offset);
/**< @internal Check DD bit of specific RX descriptor */
+typedef int (*eth_rx_descriptor_status_t)(void *rxq, uint16_t offset);
+/**< @internal Check the status of a Rx descriptor */
+
+typedef int (*eth_tx_descriptor_status_t)(void *txq, uint16_t offset);
+/**< @internal Check the status of a Tx descriptor */
+
typedef int (*eth_fw_version_get_t)(struct rte_eth_dev *dev,
char *fw_version, size_t fw_size);
/**< @internal Get firmware information of an Ethernet device. */
@@ -1483,6 +1489,10 @@ struct eth_dev_ops {
eth_queue_release_t rx_queue_release; /**< Release RX queue. */
eth_rx_queue_count_t rx_queue_count;/**< Get Rx queue count. */
eth_rx_descriptor_done_t rx_descriptor_done; /**< Check rxd DD bit. */
+ eth_rx_descriptor_status_t rx_descriptor_status;
+ /**< Check the status of a Rx descriptor. */
+ eth_tx_descriptor_status_t tx_descriptor_status;
+ /**< Check the status of a Tx descriptor. */
eth_rx_enable_intr_t rx_queue_intr_enable; /**< Enable Rx queue interrupt. */
eth_rx_disable_intr_t rx_queue_intr_disable; /**< Disable Rx queue interrupt. */
eth_tx_queue_setup_t tx_queue_setup;/**< Set up device TX queue. */
@@ -2768,6 +2778,121 @@ rte_eth_rx_descriptor_done(uint8_t port_id, uint16_t queue_id, uint16_t offset)
dev->data->rx_queues[queue_id], offset);
}
+#define RTE_ETH_RX_DESC_AVAIL 0 /**< Desc available for hw. */
+#define RTE_ETH_RX_DESC_DONE 1 /**< Desc done, filled by hw. */
+#define RTE_ETH_RX_DESC_UNAVAIL 2 /**< Desc used by driver or hw. */
+
+/**
+ * Check the status of a Rx descriptor in the queue
+ *
+ * It should be called in a similar context than the Rx function:
+ * - on a dataplane core
+ * - not concurrently on the same queue
+ *
+ * Since it's a dataplane function, no check is performed on port_id and
+ * queue_id. The caller must therefore ensure that the port is enabled
+ * and the queue is configured and running.
+ *
+ * Note: accessing to a random descriptor in the ring may trigger cache
+ * misses and have a performance impact.
+ *
+ * @param port_id
+ * A valid port identifier of the Ethernet device which.
+ * @param queue_id
+ * A valid Rx queue identifier on this port.
+ * @param offset
+ * The offset of the descriptor starting from tail (0 is the next
+ * packet to be received by the driver).
+ *
+ * @return
+ * - (RTE_ETH_RX_DESC_AVAIL): Descriptor is available for the hardware to
+ * receive a packet.
+ * - (RTE_ETH_RX_DESC_DONE): Descriptor is done, it is filled by hw, but
+ * not yet processed by the driver (i.e. in the receive queue).
+ * - (RTE_ETH_RX_DESC_UNAVAIL): Descriptor is unavailable, either hold by
+ * the driver and not yet returned to hw, or reserved by the hw.
+ * - (-EINVAL) bad descriptor offset.
+ * - (-ENOTSUP) if the device does not support this function.
+ * - (-ENODEV) bad port or queue (only if compiled with debug).
+ */
+static inline int
+rte_eth_rx_descriptor_status(uint8_t port_id, uint16_t queue_id,
+ uint16_t offset)
+{
+ struct rte_eth_dev *dev;
+ void *rxq;
+
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+#endif
+ dev = &rte_eth_devices[port_id];
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ if (queue_id >= dev->data->nb_rx_queues)
+ return -ENODEV;
+#endif
+ RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_descriptor_status, -ENOTSUP);
+ rxq = dev->data->rx_queues[queue_id];
+
+ return (*dev->dev_ops->rx_descriptor_status)(rxq, offset);
+}
+
+#define RTE_ETH_TX_DESC_FULL 0 /**< Desc filled for hw, waiting xmit. */
+#define RTE_ETH_TX_DESC_DONE 1 /**< Desc done, packet is transmitted. */
+#define RTE_ETH_TX_DESC_UNAVAIL 2 /**< Desc used by driver or hw. */
+
+/**
+ * Check the status of a Tx descriptor in the queue.
+ *
+ * It should be called in a similar context than the Tx function:
+ * - on a dataplane core
+ * - not concurrently on the same queue
+ *
+ * Since it's a dataplane function, no check is performed on port_id and
+ * queue_id. The caller must therefore ensure that the port is enabled
+ * and the queue is configured and running.
+ *
+ * Note: accessing to a random descriptor in the ring may trigger cache
+ * misses and have a performance impact.
+ *
+ * @param port_id
+ * A valid port identifier of the Ethernet device which.
+ * @param queue_id
+ * A valid Tx queue identifier on this port.
+ * @param offset
+ * The offset of the descriptor starting from tail (0 is the place where
+ * the next packet will be send).
+ *
+ * @return
+ * - (RTE_ETH_TX_DESC_FULL) Descriptor is being processed by the hw, i.e.
+ * in the transmit queue.
+ * - (RTE_ETH_TX_DESC_DONE) Hardware is done with this descriptor, it can
+ * be reused by the driver.
+ * - (RTE_ETH_TX_DESC_UNAVAIL): Descriptor is unavailable, reserved by the
+ * driver or the hardware.
+ * - (-EINVAL) bad descriptor offset.
+ * - (-ENOTSUP) if the device does not support this function.
+ * - (-ENODEV) bad port or queue (only if compiled with debug).
+ */
+static inline int rte_eth_tx_descriptor_status(uint8_t port_id,
+ uint16_t queue_id, uint16_t offset)
+{
+ struct rte_eth_dev *dev;
+ void *txq;
+
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+#endif
+ dev = &rte_eth_devices[port_id];
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ if (queue_id >= dev->data->nb_tx_queues)
+ return -ENODEV;
+#endif
+ RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_descriptor_status, -ENOTSUP);
+ txq = dev->data->tx_queues[queue_id];
+
+ return (*dev->dev_ops->tx_descriptor_status)(txq, offset);
+}
+
/**
* Send a burst of output packets on a transmit queue of an Ethernet device.
*
--
2.8.1
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH v2 1/6] ethdev: add descriptor status API
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 1/6] ethdev: add descriptor status API Olivier Matz
@ 2017-03-09 11:49 ` Andrew Rybchenko
2017-03-21 8:32 ` Yang, Qiming
1 sibling, 0 replies; 72+ messages in thread
From: Andrew Rybchenko @ 2017-03-09 11:49 UTC (permalink / raw)
To: Olivier Matz, dev, thomas.monjalon, konstantin.ananyev,
wenzhuo.lu, helin.zhang, jingjing.wu, adrien.mazarguil,
nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson, venky.venkatesan
On 03/07/2017 06:59 PM, Olivier Matz wrote:
> Introduce a new API to get the status of a descriptor.
>
> For Rx, it is almost similar to rx_descriptor_done API, except it
> differentiates "used" descriptors (which are hold by the driver and not
> returned to the hardware).
>
> For Tx, it is a new API.
>
> The descriptor_done() API, and probably the rx_queue_count() API could
> be replaced by this new API as soon as it is implemented on all PMDs.
>
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> ---
> doc/guides/nics/features/default.ini | 2 +
> lib/librte_ether/rte_ethdev.h | 125 +++++++++++++++++++++++++++++++++++
> 2 files changed, 127 insertions(+)
>
> diff --git a/doc/guides/nics/features/default.ini b/doc/guides/nics/features/default.ini
> index 9e363ff..0e6a78d 100644
> --- a/doc/guides/nics/features/default.ini
> +++ b/doc/guides/nics/features/default.ini
> @@ -49,6 +49,8 @@ Inner L3 checksum =
> Inner L4 checksum =
> Packet type parsing =
> Timesync =
> +Rx Descriptor Status =
> +Tx Descriptor Status =
> Basic stats =
> Extended stats =
> Stats per queue =
> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> index 97f3e2d..904ecbe 100644
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -1179,6 +1179,12 @@ typedef uint32_t (*eth_rx_queue_count_t)(struct rte_eth_dev *dev,
> typedef int (*eth_rx_descriptor_done_t)(void *rxq, uint16_t offset);
> /**< @internal Check DD bit of specific RX descriptor */
>
> +typedef int (*eth_rx_descriptor_status_t)(void *rxq, uint16_t offset);
> +/**< @internal Check the status of a Rx descriptor */
> +
> +typedef int (*eth_tx_descriptor_status_t)(void *txq, uint16_t offset);
> +/**< @internal Check the status of a Tx descriptor */
> +
> typedef int (*eth_fw_version_get_t)(struct rte_eth_dev *dev,
> char *fw_version, size_t fw_size);
> /**< @internal Get firmware information of an Ethernet device. */
> @@ -1483,6 +1489,10 @@ struct eth_dev_ops {
> eth_queue_release_t rx_queue_release; /**< Release RX queue. */
> eth_rx_queue_count_t rx_queue_count;/**< Get Rx queue count. */
> eth_rx_descriptor_done_t rx_descriptor_done; /**< Check rxd DD bit. */
> + eth_rx_descriptor_status_t rx_descriptor_status;
> + /**< Check the status of a Rx descriptor. */
> + eth_tx_descriptor_status_t tx_descriptor_status;
> + /**< Check the status of a Tx descriptor. */
> eth_rx_enable_intr_t rx_queue_intr_enable; /**< Enable Rx queue interrupt. */
> eth_rx_disable_intr_t rx_queue_intr_disable; /**< Disable Rx queue interrupt. */
> eth_tx_queue_setup_t tx_queue_setup;/**< Set up device TX queue. */
> @@ -2768,6 +2778,121 @@ rte_eth_rx_descriptor_done(uint8_t port_id, uint16_t queue_id, uint16_t offset)
> dev->data->rx_queues[queue_id], offset);
> }
>
> +#define RTE_ETH_RX_DESC_AVAIL 0 /**< Desc available for hw. */
> +#define RTE_ETH_RX_DESC_DONE 1 /**< Desc done, filled by hw. */
> +#define RTE_ETH_RX_DESC_UNAVAIL 2 /**< Desc used by driver or hw. */
> +
> +/**
> + * Check the status of a Rx descriptor in the queue
> + *
> + * It should be called in a similar context than the Rx function:
> + * - on a dataplane core
> + * - not concurrently on the same queue
> + *
> + * Since it's a dataplane function, no check is performed on port_id and
> + * queue_id. The caller must therefore ensure that the port is enabled
> + * and the queue is configured and running.
> + *
> + * Note: accessing to a random descriptor in the ring may trigger cache
> + * misses and have a performance impact.
> + *
> + * @param port_id
> + * A valid port identifier of the Ethernet device which.
> + * @param queue_id
> + * A valid Rx queue identifier on this port.
> + * @param offset
> + * The offset of the descriptor starting from tail (0 is the next
> + * packet to be received by the driver).
> + *
> + * @return
> + * - (RTE_ETH_RX_DESC_AVAIL): Descriptor is available for the hardware to
> + * receive a packet.
> + * - (RTE_ETH_RX_DESC_DONE): Descriptor is done, it is filled by hw, but
> + * not yet processed by the driver (i.e. in the receive queue).
> + * - (RTE_ETH_RX_DESC_UNAVAIL): Descriptor is unavailable, either hold by
> + * the driver and not yet returned to hw, or reserved by the hw.
> + * - (-EINVAL) bad descriptor offset.
> + * - (-ENOTSUP) if the device does not support this function.
> + * - (-ENODEV) bad port or queue (only if compiled with debug).
> + */
> +static inline int
> +rte_eth_rx_descriptor_status(uint8_t port_id, uint16_t queue_id,
> + uint16_t offset)
> +{
> + struct rte_eth_dev *dev;
> + void *rxq;
> +
> +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +#endif
> + dev = &rte_eth_devices[port_id];
> +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> + if (queue_id >= dev->data->nb_rx_queues)
> + return -ENODEV;
> +#endif
> + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_descriptor_status, -ENOTSUP);
> + rxq = dev->data->rx_queues[queue_id];
> +
> + return (*dev->dev_ops->rx_descriptor_status)(rxq, offset);
> +}
> +
> +#define RTE_ETH_TX_DESC_FULL 0 /**< Desc filled for hw, waiting xmit. */
> +#define RTE_ETH_TX_DESC_DONE 1 /**< Desc done, packet is transmitted. */
> +#define RTE_ETH_TX_DESC_UNAVAIL 2 /**< Desc used by driver or hw. */
> +
> +/**
> + * Check the status of a Tx descriptor in the queue.
> + *
> + * It should be called in a similar context than the Tx function:
> + * - on a dataplane core
> + * - not concurrently on the same queue
> + *
> + * Since it's a dataplane function, no check is performed on port_id and
> + * queue_id. The caller must therefore ensure that the port is enabled
> + * and the queue is configured and running.
> + *
> + * Note: accessing to a random descriptor in the ring may trigger cache
> + * misses and have a performance impact.
> + *
> + * @param port_id
> + * A valid port identifier of the Ethernet device which.
> + * @param queue_id
> + * A valid Tx queue identifier on this port.
> + * @param offset
> + * The offset of the descriptor starting from tail (0 is the place where
> + * the next packet will be send).
> + *
> + * @return
> + * - (RTE_ETH_TX_DESC_FULL) Descriptor is being processed by the hw, i.e.
> + * in the transmit queue.
> + * - (RTE_ETH_TX_DESC_DONE) Hardware is done with this descriptor, it can
> + * be reused by the driver.
> + * - (RTE_ETH_TX_DESC_UNAVAIL): Descriptor is unavailable, reserved by the
> + * driver or the hardware.
> + * - (-EINVAL) bad descriptor offset.
> + * - (-ENOTSUP) if the device does not support this function.
> + * - (-ENODEV) bad port or queue (only if compiled with debug).
> + */
> +static inline int rte_eth_tx_descriptor_status(uint8_t port_id,
> + uint16_t queue_id, uint16_t offset)
> +{
> + struct rte_eth_dev *dev;
> + void *txq;
> +
> +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
> +#endif
> + dev = &rte_eth_devices[port_id];
> +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> + if (queue_id >= dev->data->nb_tx_queues)
> + return -ENODEV;
> +#endif
> + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_descriptor_status, -ENOTSUP);
> + txq = dev->data->tx_queues[queue_id];
> +
> + return (*dev->dev_ops->tx_descriptor_status)(txq, offset);
> +}
> +
> /**
> * Send a burst of output packets on a transmit queue of an Ethernet device.
> *
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH v2 1/6] ethdev: add descriptor status API
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 1/6] ethdev: add descriptor status API Olivier Matz
2017-03-09 11:49 ` Andrew Rybchenko
@ 2017-03-21 8:32 ` Yang, Qiming
2017-03-24 12:49 ` Olivier Matz
1 sibling, 1 reply; 72+ messages in thread
From: Yang, Qiming @ 2017-03-21 8:32 UTC (permalink / raw)
To: Olivier Matz, dev, thomas.monjalon, Ananyev, Konstantin, Lu,
Wenzhuo, Zhang, Helin, Wu, Jingjing, adrien.mazarguil,
nelio.laranjeiro
Cc: Yigit, Ferruh, Richardson, Bruce, Venkatesan, Venky, arybchenko
Hi, Olivier
You need to add your new API in lib/librte_ether/rte_ether_version.map and doc/guides/rel_notes/release_17_05.rst
> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Olivier Matz
> Sent: Wednesday, March 8, 2017 12:00 AM
> To: dev@dpdk.org; thomas.monjalon@6wind.com; Ananyev, Konstantin
> <konstantin.ananyev@intel.com>; Lu, Wenzhuo <wenzhuo.lu@intel.com>;
> Zhang, Helin <helin.zhang@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>;
> adrien.mazarguil@6wind.com; nelio.laranjeiro@6wind.com
> Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; Richardson, Bruce
> <bruce.richardson@intel.com>; Venkatesan, Venky
> <venky.venkatesan@intel.com>; arybchenko@solarflare.com
> Subject: [dpdk-dev] [PATCH v2 1/6] ethdev: add descriptor status API
>
> Introduce a new API to get the status of a descriptor.
>
> For Rx, it is almost similar to rx_descriptor_done API, except it differentiates
> "used" descriptors (which are hold by the driver and not returned to the
> hardware).
>
> For Tx, it is a new API.
>
> The descriptor_done() API, and probably the rx_queue_count() API could be
> replaced by this new API as soon as it is implemented on all PMDs.
>
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> ---
> doc/guides/nics/features/default.ini | 2 +
> lib/librte_ether/rte_ethdev.h | 125
> +++++++++++++++++++++++++++++++++++
> 2 files changed, 127 insertions(+)
>
> diff --git a/doc/guides/nics/features/default.ini
> b/doc/guides/nics/features/default.ini
> index 9e363ff..0e6a78d 100644
> --- a/doc/guides/nics/features/default.ini
> +++ b/doc/guides/nics/features/default.ini
> @@ -49,6 +49,8 @@ Inner L3 checksum =
> Inner L4 checksum =
> Packet type parsing =
> Timesync =
> +Rx Descriptor Status =
> +Tx Descriptor Status =
> Basic stats =
> Extended stats =
> Stats per queue =
> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> index 97f3e2d..904ecbe 100644
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -1179,6 +1179,12 @@ typedef uint32_t
> (*eth_rx_queue_count_t)(struct rte_eth_dev *dev, typedef int
> (*eth_rx_descriptor_done_t)(void *rxq, uint16_t offset); /**< @internal
> Check DD bit of specific RX descriptor */
>
> +typedef int (*eth_rx_descriptor_status_t)(void *rxq, uint16_t offset);
> +/**< @internal Check the status of a Rx descriptor */
> +
> +typedef int (*eth_tx_descriptor_status_t)(void *txq, uint16_t offset);
> +/**< @internal Check the status of a Tx descriptor */
> +
> typedef int (*eth_fw_version_get_t)(struct rte_eth_dev *dev,
> char *fw_version, size_t fw_size); /**<
> @internal Get firmware information of an Ethernet device. */ @@ -1483,6
> +1489,10 @@ struct eth_dev_ops {
> eth_queue_release_t rx_queue_release; /**< Release RX queue.
> */
> eth_rx_queue_count_t rx_queue_count;/**< Get Rx queue
> count. */
> eth_rx_descriptor_done_t rx_descriptor_done; /**< Check rxd DD
> bit. */
> + eth_rx_descriptor_status_t rx_descriptor_status;
> + /**< Check the status of a Rx descriptor. */
> + eth_tx_descriptor_status_t tx_descriptor_status;
> + /**< Check the status of a Tx descriptor. */
> eth_rx_enable_intr_t rx_queue_intr_enable; /**< Enable Rx
> queue interrupt. */
> eth_rx_disable_intr_t rx_queue_intr_disable; /**< Disable Rx
> queue interrupt. */
> eth_tx_queue_setup_t tx_queue_setup;/**< Set up device TX
> queue. */
> @@ -2768,6 +2778,121 @@ rte_eth_rx_descriptor_done(uint8_t port_id,
> uint16_t queue_id, uint16_t offset)
> dev->data->rx_queues[queue_id], offset); }
>
> +#define RTE_ETH_RX_DESC_AVAIL 0 /**< Desc available for hw. */
> +#define RTE_ETH_RX_DESC_DONE 1 /**< Desc done, filled by hw. */
> +#define RTE_ETH_RX_DESC_UNAVAIL 2 /**< Desc used by driver or hw. */
> +
> +/**
> + * Check the status of a Rx descriptor in the queue
> + *
> + * It should be called in a similar context than the Rx function:
> + * - on a dataplane core
> + * - not concurrently on the same queue
> + *
> + * Since it's a dataplane function, no check is performed on port_id
> +and
> + * queue_id. The caller must therefore ensure that the port is enabled
> + * and the queue is configured and running.
> + *
> + * Note: accessing to a random descriptor in the ring may trigger cache
> + * misses and have a performance impact.
> + *
> + * @param port_id
> + * A valid port identifier of the Ethernet device which.
> + * @param queue_id
> + * A valid Rx queue identifier on this port.
> + * @param offset
> + * The offset of the descriptor starting from tail (0 is the next
> + * packet to be received by the driver).
> + *
> + * @return
> + * - (RTE_ETH_RX_DESC_AVAIL): Descriptor is available for the hardware to
> + * receive a packet.
> + * - (RTE_ETH_RX_DESC_DONE): Descriptor is done, it is filled by hw, but
> + * not yet processed by the driver (i.e. in the receive queue).
> + * - (RTE_ETH_RX_DESC_UNAVAIL): Descriptor is unavailable, either hold by
> + * the driver and not yet returned to hw, or reserved by the hw.
> + * - (-EINVAL) bad descriptor offset.
> + * - (-ENOTSUP) if the device does not support this function.
> + * - (-ENODEV) bad port or queue (only if compiled with debug).
> + */
> +static inline int
> +rte_eth_rx_descriptor_status(uint8_t port_id, uint16_t queue_id,
> + uint16_t offset)
> +{
> + struct rte_eth_dev *dev;
> + void *rxq;
> +
> +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); #endif
> + dev = &rte_eth_devices[port_id];
> +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> + if (queue_id >= dev->data->nb_rx_queues)
> + return -ENODEV;
> +#endif
> + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> >rx_descriptor_status, -ENOTSUP);
> + rxq = dev->data->rx_queues[queue_id];
> +
> + return (*dev->dev_ops->rx_descriptor_status)(rxq, offset); }
> +
> +#define RTE_ETH_TX_DESC_FULL 0 /**< Desc filled for hw, waiting xmit.
> */
> +#define RTE_ETH_TX_DESC_DONE 1 /**< Desc done, packet is
> transmitted. */
> +#define RTE_ETH_TX_DESC_UNAVAIL 2 /**< Desc used by driver or hw. */
> +
> +/**
> + * Check the status of a Tx descriptor in the queue.
> + *
> + * It should be called in a similar context than the Tx function:
> + * - on a dataplane core
> + * - not concurrently on the same queue
> + *
> + * Since it's a dataplane function, no check is performed on port_id
> +and
> + * queue_id. The caller must therefore ensure that the port is enabled
> + * and the queue is configured and running.
> + *
> + * Note: accessing to a random descriptor in the ring may trigger cache
> + * misses and have a performance impact.
> + *
> + * @param port_id
> + * A valid port identifier of the Ethernet device which.
> + * @param queue_id
> + * A valid Tx queue identifier on this port.
> + * @param offset
> + * The offset of the descriptor starting from tail (0 is the place
> +where
> + * the next packet will be send).
> + *
> + * @return
> + * - (RTE_ETH_TX_DESC_FULL) Descriptor is being processed by the hw, i.e.
> + * in the transmit queue.
> + * - (RTE_ETH_TX_DESC_DONE) Hardware is done with this descriptor, it
> can
> + * be reused by the driver.
> + * - (RTE_ETH_TX_DESC_UNAVAIL): Descriptor is unavailable, reserved by
> the
> + * driver or the hardware.
> + * - (-EINVAL) bad descriptor offset.
> + * - (-ENOTSUP) if the device does not support this function.
> + * - (-ENODEV) bad port or queue (only if compiled with debug).
> + */
> +static inline int rte_eth_tx_descriptor_status(uint8_t port_id,
> + uint16_t queue_id, uint16_t offset)
> +{
> + struct rte_eth_dev *dev;
> + void *txq;
> +
> +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); #endif
> + dev = &rte_eth_devices[port_id];
> +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> + if (queue_id >= dev->data->nb_tx_queues)
> + return -ENODEV;
> +#endif
> + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> >tx_descriptor_status, -ENOTSUP);
> + txq = dev->data->tx_queues[queue_id];
> +
> + return (*dev->dev_ops->tx_descriptor_status)(txq, offset); }
> +
> /**
> * Send a burst of output packets on a transmit queue of an Ethernet device.
> *
> --
> 2.8.1
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH v2 1/6] ethdev: add descriptor status API
2017-03-21 8:32 ` Yang, Qiming
@ 2017-03-24 12:49 ` Olivier Matz
2017-03-27 1:28 ` Yang, Qiming
0 siblings, 1 reply; 72+ messages in thread
From: Olivier Matz @ 2017-03-24 12:49 UTC (permalink / raw)
To: Yang, Qiming
Cc: dev, thomas.monjalon, Ananyev, Konstantin, Lu, Wenzhuo, Zhang,
Helin, Wu, Jingjing, adrien.mazarguil, nelio.laranjeiro, Yigit,
Ferruh, Richardson, Bruce, Venkatesan, Venky, arybchenko
Hi Qiming,
On Tue, 21 Mar 2017 08:32:17 +0000, "Yang, Qiming" <qiming.yang@intel.com> wrote:
> Hi, Olivier
> You need to add your new API in lib/librte_ether/rte_ether_version.map and doc/guides/rel_notes/release_17_05.rst
About rte_ether_version.map, I don't think it's needed since
the functions are static inline. Did you noticed any issue?
About release_17_05.rst, you are right, I can add some words about
this new feature.
Thanks,
Olivier
>
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Olivier Matz
> > Sent: Wednesday, March 8, 2017 12:00 AM
> > To: dev@dpdk.org; thomas.monjalon@6wind.com; Ananyev, Konstantin
> > <konstantin.ananyev@intel.com>; Lu, Wenzhuo <wenzhuo.lu@intel.com>;
> > Zhang, Helin <helin.zhang@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>;
> > adrien.mazarguil@6wind.com; nelio.laranjeiro@6wind.com
> > Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; Richardson, Bruce
> > <bruce.richardson@intel.com>; Venkatesan, Venky
> > <venky.venkatesan@intel.com>; arybchenko@solarflare.com
> > Subject: [dpdk-dev] [PATCH v2 1/6] ethdev: add descriptor status API
> >
> > Introduce a new API to get the status of a descriptor.
> >
> > For Rx, it is almost similar to rx_descriptor_done API, except it differentiates
> > "used" descriptors (which are hold by the driver and not returned to the
> > hardware).
> >
> > For Tx, it is a new API.
> >
> > The descriptor_done() API, and probably the rx_queue_count() API could be
> > replaced by this new API as soon as it is implemented on all PMDs.
> >
> > Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> > ---
> > doc/guides/nics/features/default.ini | 2 +
> > lib/librte_ether/rte_ethdev.h | 125
> > +++++++++++++++++++++++++++++++++++
> > 2 files changed, 127 insertions(+)
> >
> > diff --git a/doc/guides/nics/features/default.ini
> > b/doc/guides/nics/features/default.ini
> > index 9e363ff..0e6a78d 100644
> > --- a/doc/guides/nics/features/default.ini
> > +++ b/doc/guides/nics/features/default.ini
> > @@ -49,6 +49,8 @@ Inner L3 checksum =
> > Inner L4 checksum =
> > Packet type parsing =
> > Timesync =
> > +Rx Descriptor Status =
> > +Tx Descriptor Status =
> > Basic stats =
> > Extended stats =
> > Stats per queue =
> > diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> > index 97f3e2d..904ecbe 100644
> > --- a/lib/librte_ether/rte_ethdev.h
> > +++ b/lib/librte_ether/rte_ethdev.h
> > @@ -1179,6 +1179,12 @@ typedef uint32_t
> > (*eth_rx_queue_count_t)(struct rte_eth_dev *dev, typedef int
> > (*eth_rx_descriptor_done_t)(void *rxq, uint16_t offset); /**< @internal
> > Check DD bit of specific RX descriptor */
> >
> > +typedef int (*eth_rx_descriptor_status_t)(void *rxq, uint16_t offset);
> > +/**< @internal Check the status of a Rx descriptor */
> > +
> > +typedef int (*eth_tx_descriptor_status_t)(void *txq, uint16_t offset);
> > +/**< @internal Check the status of a Tx descriptor */
> > +
> > typedef int (*eth_fw_version_get_t)(struct rte_eth_dev *dev,
> > char *fw_version, size_t fw_size); /**<
> > @internal Get firmware information of an Ethernet device. */ @@ -1483,6
> > +1489,10 @@ struct eth_dev_ops {
> > eth_queue_release_t rx_queue_release; /**< Release RX queue.
> > */
> > eth_rx_queue_count_t rx_queue_count;/**< Get Rx queue
> > count. */
> > eth_rx_descriptor_done_t rx_descriptor_done; /**< Check rxd DD
> > bit. */
> > + eth_rx_descriptor_status_t rx_descriptor_status;
> > + /**< Check the status of a Rx descriptor. */
> > + eth_tx_descriptor_status_t tx_descriptor_status;
> > + /**< Check the status of a Tx descriptor. */
> > eth_rx_enable_intr_t rx_queue_intr_enable; /**< Enable Rx
> > queue interrupt. */
> > eth_rx_disable_intr_t rx_queue_intr_disable; /**< Disable Rx
> > queue interrupt. */
> > eth_tx_queue_setup_t tx_queue_setup;/**< Set up device TX
> > queue. */
> > @@ -2768,6 +2778,121 @@ rte_eth_rx_descriptor_done(uint8_t port_id,
> > uint16_t queue_id, uint16_t offset)
> > dev->data->rx_queues[queue_id], offset); }
> >
> > +#define RTE_ETH_RX_DESC_AVAIL 0 /**< Desc available for hw. */
> > +#define RTE_ETH_RX_DESC_DONE 1 /**< Desc done, filled by hw. */
> > +#define RTE_ETH_RX_DESC_UNAVAIL 2 /**< Desc used by driver or hw. */
> > +
> > +/**
> > + * Check the status of a Rx descriptor in the queue
> > + *
> > + * It should be called in a similar context than the Rx function:
> > + * - on a dataplane core
> > + * - not concurrently on the same queue
> > + *
> > + * Since it's a dataplane function, no check is performed on port_id
> > +and
> > + * queue_id. The caller must therefore ensure that the port is enabled
> > + * and the queue is configured and running.
> > + *
> > + * Note: accessing to a random descriptor in the ring may trigger cache
> > + * misses and have a performance impact.
> > + *
> > + * @param port_id
> > + * A valid port identifier of the Ethernet device which.
> > + * @param queue_id
> > + * A valid Rx queue identifier on this port.
> > + * @param offset
> > + * The offset of the descriptor starting from tail (0 is the next
> > + * packet to be received by the driver).
> > + *
> > + * @return
> > + * - (RTE_ETH_RX_DESC_AVAIL): Descriptor is available for the hardware to
> > + * receive a packet.
> > + * - (RTE_ETH_RX_DESC_DONE): Descriptor is done, it is filled by hw, but
> > + * not yet processed by the driver (i.e. in the receive queue).
> > + * - (RTE_ETH_RX_DESC_UNAVAIL): Descriptor is unavailable, either hold by
> > + * the driver and not yet returned to hw, or reserved by the hw.
> > + * - (-EINVAL) bad descriptor offset.
> > + * - (-ENOTSUP) if the device does not support this function.
> > + * - (-ENODEV) bad port or queue (only if compiled with debug).
> > + */
> > +static inline int
> > +rte_eth_rx_descriptor_status(uint8_t port_id, uint16_t queue_id,
> > + uint16_t offset)
> > +{
> > + struct rte_eth_dev *dev;
> > + void *rxq;
> > +
> > +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> > + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); #endif
> > + dev = &rte_eth_devices[port_id];
> > +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> > + if (queue_id >= dev->data->nb_rx_queues)
> > + return -ENODEV;
> > +#endif
> > + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> > >rx_descriptor_status, -ENOTSUP);
> > + rxq = dev->data->rx_queues[queue_id];
> > +
> > + return (*dev->dev_ops->rx_descriptor_status)(rxq, offset); }
> > +
> > +#define RTE_ETH_TX_DESC_FULL 0 /**< Desc filled for hw, waiting xmit.
> > */
> > +#define RTE_ETH_TX_DESC_DONE 1 /**< Desc done, packet is
> > transmitted. */
> > +#define RTE_ETH_TX_DESC_UNAVAIL 2 /**< Desc used by driver or hw. */
> > +
> > +/**
> > + * Check the status of a Tx descriptor in the queue.
> > + *
> > + * It should be called in a similar context than the Tx function:
> > + * - on a dataplane core
> > + * - not concurrently on the same queue
> > + *
> > + * Since it's a dataplane function, no check is performed on port_id
> > +and
> > + * queue_id. The caller must therefore ensure that the port is enabled
> > + * and the queue is configured and running.
> > + *
> > + * Note: accessing to a random descriptor in the ring may trigger cache
> > + * misses and have a performance impact.
> > + *
> > + * @param port_id
> > + * A valid port identifier of the Ethernet device which.
> > + * @param queue_id
> > + * A valid Tx queue identifier on this port.
> > + * @param offset
> > + * The offset of the descriptor starting from tail (0 is the place
> > +where
> > + * the next packet will be send).
> > + *
> > + * @return
> > + * - (RTE_ETH_TX_DESC_FULL) Descriptor is being processed by the hw, i.e.
> > + * in the transmit queue.
> > + * - (RTE_ETH_TX_DESC_DONE) Hardware is done with this descriptor, it
> > can
> > + * be reused by the driver.
> > + * - (RTE_ETH_TX_DESC_UNAVAIL): Descriptor is unavailable, reserved by
> > the
> > + * driver or the hardware.
> > + * - (-EINVAL) bad descriptor offset.
> > + * - (-ENOTSUP) if the device does not support this function.
> > + * - (-ENODEV) bad port or queue (only if compiled with debug).
> > + */
> > +static inline int rte_eth_tx_descriptor_status(uint8_t port_id,
> > + uint16_t queue_id, uint16_t offset)
> > +{
> > + struct rte_eth_dev *dev;
> > + void *txq;
> > +
> > +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> > + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); #endif
> > + dev = &rte_eth_devices[port_id];
> > +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> > + if (queue_id >= dev->data->nb_tx_queues)
> > + return -ENODEV;
> > +#endif
> > + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> > >tx_descriptor_status, -ENOTSUP);
> > + txq = dev->data->tx_queues[queue_id];
> > +
> > + return (*dev->dev_ops->tx_descriptor_status)(txq, offset); }
> > +
> > /**
> > * Send a burst of output packets on a transmit queue of an Ethernet device.
> > *
> > --
> > 2.8.1
>
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH v2 1/6] ethdev: add descriptor status API
2017-03-24 12:49 ` Olivier Matz
@ 2017-03-27 1:28 ` Yang, Qiming
0 siblings, 0 replies; 72+ messages in thread
From: Yang, Qiming @ 2017-03-27 1:28 UTC (permalink / raw)
To: Olivier Matz
Cc: dev, thomas.monjalon, Ananyev, Konstantin, Lu, Wenzhuo, Zhang,
Helin, Wu, Jingjing, adrien.mazarguil, nelio.laranjeiro, Yigit,
Ferruh, Richardson, Bruce, Venkatesan, Venky, arybchenko
Hi, Olivier
> -----Original Message-----
> From: Olivier Matz [mailto:olivier.matz@6wind.com]
> Sent: Friday, March 24, 2017 8:49 PM
> To: Yang, Qiming <qiming.yang@intel.com>
> Cc: dev@dpdk.org; thomas.monjalon@6wind.com; Ananyev, Konstantin
> <konstantin.ananyev@intel.com>; Lu, Wenzhuo <wenzhuo.lu@intel.com>;
> Zhang, Helin <helin.zhang@intel.com>; Wu, Jingjing <jingjing.wu@intel.com>;
> adrien.mazarguil@6wind.com; nelio.laranjeiro@6wind.com; Yigit, Ferruh
> <ferruh.yigit@intel.com>; Richardson, Bruce <bruce.richardson@intel.com>;
> Venkatesan, Venky <venky.venkatesan@intel.com>;
> arybchenko@solarflare.com
> Subject: Re: [dpdk-dev] [PATCH v2 1/6] ethdev: add descriptor status API
>
> Hi Qiming,
>
> On Tue, 21 Mar 2017 08:32:17 +0000, "Yang, Qiming" <qiming.yang@intel.com>
> wrote:
> > Hi, Olivier
> > You need to add your new API in lib/librte_ether/rte_ether_version.map
> > and doc/guides/rel_notes/release_17_05.rst
>
> About rte_ether_version.map, I don't think it's needed since the functions
> are static inline. Did you noticed any issue?
>
That's OK, I didn't notice that the functions are static inline, sorry.
> About release_17_05.rst, you are right, I can add some words about this new
> feature.
>
>
> Thanks,
> Olivier
>
>
> >
> > > -----Original Message-----
> > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Olivier Matz
> > > Sent: Wednesday, March 8, 2017 12:00 AM
> > > To: dev@dpdk.org; thomas.monjalon@6wind.com; Ananyev, Konstantin
> > > <konstantin.ananyev@intel.com>; Lu, Wenzhuo
> <wenzhuo.lu@intel.com>;
> > > Zhang, Helin <helin.zhang@intel.com>; Wu, Jingjing
> > > <jingjing.wu@intel.com>; adrien.mazarguil@6wind.com;
> > > nelio.laranjeiro@6wind.com
> > > Cc: Yigit, Ferruh <ferruh.yigit@intel.com>; Richardson, Bruce
> > > <bruce.richardson@intel.com>; Venkatesan, Venky
> > > <venky.venkatesan@intel.com>; arybchenko@solarflare.com
> > > Subject: [dpdk-dev] [PATCH v2 1/6] ethdev: add descriptor status API
> > >
> > > Introduce a new API to get the status of a descriptor.
> > >
> > > For Rx, it is almost similar to rx_descriptor_done API, except it
> > > differentiates "used" descriptors (which are hold by the driver and
> > > not returned to the hardware).
> > >
> > > For Tx, it is a new API.
> > >
> > > The descriptor_done() API, and probably the rx_queue_count() API
> > > could be replaced by this new API as soon as it is implemented on all
> PMDs.
> > >
> > > Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
> > > ---
> > > doc/guides/nics/features/default.ini | 2 +
> > > lib/librte_ether/rte_ethdev.h | 125
> > > +++++++++++++++++++++++++++++++++++
> > > 2 files changed, 127 insertions(+)
> > >
> > > diff --git a/doc/guides/nics/features/default.ini
> > > b/doc/guides/nics/features/default.ini
> > > index 9e363ff..0e6a78d 100644
> > > --- a/doc/guides/nics/features/default.ini
> > > +++ b/doc/guides/nics/features/default.ini
> > > @@ -49,6 +49,8 @@ Inner L3 checksum =
> > > Inner L4 checksum =
> > > Packet type parsing =
> > > Timesync =
> > > +Rx Descriptor Status =
> > > +Tx Descriptor Status =
> > > Basic stats =
> > > Extended stats =
> > > Stats per queue =
> > > diff --git a/lib/librte_ether/rte_ethdev.h
> > > b/lib/librte_ether/rte_ethdev.h index 97f3e2d..904ecbe 100644
> > > --- a/lib/librte_ether/rte_ethdev.h
> > > +++ b/lib/librte_ether/rte_ethdev.h
> > > @@ -1179,6 +1179,12 @@ typedef uint32_t
> > > (*eth_rx_queue_count_t)(struct rte_eth_dev *dev, typedef int
> > > (*eth_rx_descriptor_done_t)(void *rxq, uint16_t offset); /**<
> > > @internal Check DD bit of specific RX descriptor */
> > >
> > > +typedef int (*eth_rx_descriptor_status_t)(void *rxq, uint16_t
> > > +offset); /**< @internal Check the status of a Rx descriptor */
> > > +
> > > +typedef int (*eth_tx_descriptor_status_t)(void *txq, uint16_t
> > > +offset); /**< @internal Check the status of a Tx descriptor */
> > > +
> > > typedef int (*eth_fw_version_get_t)(struct rte_eth_dev *dev,
> > > char *fw_version, size_t fw_size); /**<
> @internal Get
> > > firmware information of an Ethernet device. */ @@ -1483,6
> > > +1489,10 @@ struct eth_dev_ops {
> > > eth_queue_release_t rx_queue_release; /**< Release RX queue.
> > > */
> > > eth_rx_queue_count_t rx_queue_count;/**< Get Rx queue
> > > count. */
> > > eth_rx_descriptor_done_t rx_descriptor_done; /**< Check rxd DD
> > > bit. */
> > > + eth_rx_descriptor_status_t rx_descriptor_status;
> > > + /**< Check the status of a Rx descriptor. */
> > > + eth_tx_descriptor_status_t tx_descriptor_status;
> > > + /**< Check the status of a Tx descriptor. */
> > > eth_rx_enable_intr_t rx_queue_intr_enable; /**< Enable Rx
> > > queue interrupt. */
> > > eth_rx_disable_intr_t rx_queue_intr_disable; /**< Disable Rx
> > > queue interrupt. */
> > > eth_tx_queue_setup_t tx_queue_setup;/**< Set up device TX
> > > queue. */
> > > @@ -2768,6 +2778,121 @@ rte_eth_rx_descriptor_done(uint8_t port_id,
> > > uint16_t queue_id, uint16_t offset)
> > > dev->data->rx_queues[queue_id], offset); }
> > >
> > > +#define RTE_ETH_RX_DESC_AVAIL 0 /**< Desc available for hw. */
> > > +#define RTE_ETH_RX_DESC_DONE 1 /**< Desc done, filled by hw. */
> > > +#define RTE_ETH_RX_DESC_UNAVAIL 2 /**< Desc used by driver or hw.
> > > +*/
> > > +
> > > +/**
> > > + * Check the status of a Rx descriptor in the queue
> > > + *
> > > + * It should be called in a similar context than the Rx function:
> > > + * - on a dataplane core
> > > + * - not concurrently on the same queue
> > > + *
> > > + * Since it's a dataplane function, no check is performed on
> > > +port_id and
> > > + * queue_id. The caller must therefore ensure that the port is
> > > +enabled
> > > + * and the queue is configured and running.
> > > + *
> > > + * Note: accessing to a random descriptor in the ring may trigger
> > > +cache
> > > + * misses and have a performance impact.
> > > + *
> > > + * @param port_id
> > > + * A valid port identifier of the Ethernet device which.
> > > + * @param queue_id
> > > + * A valid Rx queue identifier on this port.
> > > + * @param offset
> > > + * The offset of the descriptor starting from tail (0 is the next
> > > + * packet to be received by the driver).
> > > + *
> > > + * @return
> > > + * - (RTE_ETH_RX_DESC_AVAIL): Descriptor is available for the
> hardware to
> > > + * receive a packet.
> > > + * - (RTE_ETH_RX_DESC_DONE): Descriptor is done, it is filled by hw, but
> > > + * not yet processed by the driver (i.e. in the receive queue).
> > > + * - (RTE_ETH_RX_DESC_UNAVAIL): Descriptor is unavailable, either
> hold by
> > > + * the driver and not yet returned to hw, or reserved by the hw.
> > > + * - (-EINVAL) bad descriptor offset.
> > > + * - (-ENOTSUP) if the device does not support this function.
> > > + * - (-ENODEV) bad port or queue (only if compiled with debug).
> > > + */
> > > +static inline int
> > > +rte_eth_rx_descriptor_status(uint8_t port_id, uint16_t queue_id,
> > > + uint16_t offset)
> > > +{
> > > + struct rte_eth_dev *dev;
> > > + void *rxq;
> > > +
> > > +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> > > + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); #endif
> > > + dev = &rte_eth_devices[port_id];
> > > +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> > > + if (queue_id >= dev->data->nb_rx_queues)
> > > + return -ENODEV;
> > > +#endif
> > > + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> > > >rx_descriptor_status, -ENOTSUP);
> > > + rxq = dev->data->rx_queues[queue_id];
> > > +
> > > + return (*dev->dev_ops->rx_descriptor_status)(rxq, offset); }
> > > +
> > > +#define RTE_ETH_TX_DESC_FULL 0 /**< Desc filled for hw, waiting
> xmit.
> > > */
> > > +#define RTE_ETH_TX_DESC_DONE 1 /**< Desc done, packet is
> > > transmitted. */
> > > +#define RTE_ETH_TX_DESC_UNAVAIL 2 /**< Desc used by driver or hw.
> > > +*/
> > > +
> > > +/**
> > > + * Check the status of a Tx descriptor in the queue.
> > > + *
> > > + * It should be called in a similar context than the Tx function:
> > > + * - on a dataplane core
> > > + * - not concurrently on the same queue
> > > + *
> > > + * Since it's a dataplane function, no check is performed on
> > > +port_id and
> > > + * queue_id. The caller must therefore ensure that the port is
> > > +enabled
> > > + * and the queue is configured and running.
> > > + *
> > > + * Note: accessing to a random descriptor in the ring may trigger
> > > +cache
> > > + * misses and have a performance impact.
> > > + *
> > > + * @param port_id
> > > + * A valid port identifier of the Ethernet device which.
> > > + * @param queue_id
> > > + * A valid Tx queue identifier on this port.
> > > + * @param offset
> > > + * The offset of the descriptor starting from tail (0 is the place
> > > +where
> > > + * the next packet will be send).
> > > + *
> > > + * @return
> > > + * - (RTE_ETH_TX_DESC_FULL) Descriptor is being processed by the hw,
> i.e.
> > > + * in the transmit queue.
> > > + * - (RTE_ETH_TX_DESC_DONE) Hardware is done with this descriptor,
> > > +it
> > > can
> > > + * be reused by the driver.
> > > + * - (RTE_ETH_TX_DESC_UNAVAIL): Descriptor is unavailable,
> > > + reserved by
> > > the
> > > + * driver or the hardware.
> > > + * - (-EINVAL) bad descriptor offset.
> > > + * - (-ENOTSUP) if the device does not support this function.
> > > + * - (-ENODEV) bad port or queue (only if compiled with debug).
> > > + */
> > > +static inline int rte_eth_tx_descriptor_status(uint8_t port_id,
> > > + uint16_t queue_id, uint16_t offset) {
> > > + struct rte_eth_dev *dev;
> > > + void *txq;
> > > +
> > > +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> > > + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); #endif
> > > + dev = &rte_eth_devices[port_id];
> > > +#ifdef RTE_LIBRTE_ETHDEV_DEBUG
> > > + if (queue_id >= dev->data->nb_tx_queues)
> > > + return -ENODEV;
> > > +#endif
> > > + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops-
> > > >tx_descriptor_status, -ENOTSUP);
> > > + txq = dev->data->tx_queues[queue_id];
> > > +
> > > + return (*dev->dev_ops->tx_descriptor_status)(txq, offset); }
> > > +
> > > /**
> > > * Send a burst of output packets on a transmit queue of an Ethernet
> device.
> > > *
> > > --
> > > 2.8.1
> >
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH v2 2/6] net/ixgbe: implement descriptor status API
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 " Olivier Matz
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 1/6] ethdev: add descriptor status API Olivier Matz
@ 2017-03-07 15:59 ` Olivier Matz
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 3/6] net/e1000: implement descriptor status API (igb) Olivier Matz
` (4 subsequent siblings)
6 siblings, 0 replies; 72+ messages in thread
From: Olivier Matz @ 2017-03-07 15:59 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson, venky.venkatesan, arybchenko
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
doc/guides/nics/features/ixgbe.ini | 2 ++
doc/guides/nics/features/ixgbe_vec.ini | 2 ++
doc/guides/nics/features/ixgbe_vf.ini | 2 ++
doc/guides/nics/features/ixgbe_vf_vec.ini | 2 ++
drivers/net/ixgbe/ixgbe_ethdev.c | 4 +++
drivers/net/ixgbe/ixgbe_ethdev.h | 3 ++
drivers/net/ixgbe/ixgbe_rxtx.c | 57 +++++++++++++++++++++++++++++++
7 files changed, 72 insertions(+)
diff --git a/doc/guides/nics/features/ixgbe.ini b/doc/guides/nics/features/ixgbe.ini
index e65bbb8..d59ed43 100644
--- a/doc/guides/nics/features/ixgbe.ini
+++ b/doc/guides/nics/features/ixgbe.ini
@@ -42,6 +42,8 @@ Inner L3 checksum = Y
Inner L4 checksum = Y
Packet type parsing = Y
Timesync = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
Stats per queue = Y
diff --git a/doc/guides/nics/features/ixgbe_vec.ini b/doc/guides/nics/features/ixgbe_vec.ini
index e1773dd..1a9326e 100644
--- a/doc/guides/nics/features/ixgbe_vec.ini
+++ b/doc/guides/nics/features/ixgbe_vec.ini
@@ -32,6 +32,8 @@ Flow control = Y
Rate limitation = Y
Traffic mirroring = Y
Timesync = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
Stats per queue = Y
diff --git a/doc/guides/nics/features/ixgbe_vf.ini b/doc/guides/nics/features/ixgbe_vf.ini
index bf28215..8be1db8 100644
--- a/doc/guides/nics/features/ixgbe_vf.ini
+++ b/doc/guides/nics/features/ixgbe_vf.ini
@@ -25,6 +25,8 @@ L4 checksum offload = Y
Inner L3 checksum = Y
Inner L4 checksum = Y
Packet type parsing = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
Registers dump = Y
diff --git a/doc/guides/nics/features/ixgbe_vf_vec.ini b/doc/guides/nics/features/ixgbe_vf_vec.ini
index 8b8c90b..f02251f 100644
--- a/doc/guides/nics/features/ixgbe_vf_vec.ini
+++ b/doc/guides/nics/features/ixgbe_vf_vec.ini
@@ -17,6 +17,8 @@ RSS hash = Y
RSS key update = Y
RSS reta update = Y
VLAN filter = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
Registers dump = Y
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 7169007..34bd681 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -554,6 +554,8 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
.rx_queue_release = ixgbe_dev_rx_queue_release,
.rx_queue_count = ixgbe_dev_rx_queue_count,
.rx_descriptor_done = ixgbe_dev_rx_descriptor_done,
+ .rx_descriptor_status = ixgbe_dev_rx_descriptor_status,
+ .tx_descriptor_status = ixgbe_dev_tx_descriptor_status,
.tx_queue_setup = ixgbe_dev_tx_queue_setup,
.tx_queue_release = ixgbe_dev_tx_queue_release,
.dev_led_on = ixgbe_dev_led_on,
@@ -632,6 +634,8 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops = {
.rx_queue_setup = ixgbe_dev_rx_queue_setup,
.rx_queue_release = ixgbe_dev_rx_queue_release,
.rx_descriptor_done = ixgbe_dev_rx_descriptor_done,
+ .rx_descriptor_status = ixgbe_dev_rx_descriptor_status,
+ .tx_descriptor_status = ixgbe_dev_tx_descriptor_status,
.tx_queue_setup = ixgbe_dev_tx_queue_setup,
.tx_queue_release = ixgbe_dev_tx_queue_release,
.rx_queue_intr_enable = ixgbevf_dev_rx_queue_intr_enable,
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index 680d5d9..fc11d20 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -516,6 +516,9 @@ uint32_t ixgbe_dev_rx_queue_count(struct rte_eth_dev *dev,
int ixgbe_dev_rx_descriptor_done(void *rx_queue, uint16_t offset);
int ixgbevf_dev_rx_descriptor_done(void *rx_queue, uint16_t offset);
+int ixgbe_dev_rx_descriptor_status(void *rx_queue, uint16_t offset);
+int ixgbe_dev_tx_descriptor_status(void *tx_queue, uint16_t offset);
+
int ixgbe_dev_rx_init(struct rte_eth_dev *dev);
void ixgbe_dev_tx_init(struct rte_eth_dev *dev);
diff --git a/drivers/net/ixgbe/ixgbe_rxtx.c b/drivers/net/ixgbe/ixgbe_rxtx.c
index 9502432..216079a 100644
--- a/drivers/net/ixgbe/ixgbe_rxtx.c
+++ b/drivers/net/ixgbe/ixgbe_rxtx.c
@@ -2950,6 +2950,63 @@ ixgbe_dev_rx_descriptor_done(void *rx_queue, uint16_t offset)
rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD));
}
+int
+ixgbe_dev_rx_descriptor_status(void *rx_queue, uint16_t offset)
+{
+ struct ixgbe_rx_queue *rxq = rx_queue;
+ volatile uint32_t *status;
+ uint32_t nb_hold, desc;
+
+ if (unlikely(offset >= rxq->nb_rx_desc))
+ return -EINVAL;
+
+#ifdef RTE_IXGBE_INC_VECTOR
+ if (rxq->rx_using_sse)
+ nb_hold = rxq->rxrearm_nb;
+ else
+#endif
+ nb_hold = rxq->nb_rx_hold;
+ if (offset >= rxq->nb_rx_desc - nb_hold)
+ return RTE_ETH_RX_DESC_UNAVAIL;
+
+ desc = rxq->rx_tail + offset;
+ if (desc >= rxq->nb_rx_desc)
+ desc -= rxq->nb_rx_desc;
+
+ status = &rxq->rx_ring[desc].wb.upper.status_error;
+ if (*status & rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD))
+ return RTE_ETH_RX_DESC_DONE;
+
+ return RTE_ETH_RX_DESC_AVAIL;
+}
+
+int
+ixgbe_dev_tx_descriptor_status(void *tx_queue, uint16_t offset)
+{
+ struct ixgbe_tx_queue *txq = tx_queue;
+ volatile uint32_t *status;
+ uint32_t desc;
+
+ if (unlikely(offset >= txq->nb_tx_desc))
+ return -EINVAL;
+
+ desc = txq->tx_tail + offset;
+ /* go to next desc that has the RS bit */
+ desc = ((desc + txq->tx_rs_thresh - 1) / txq->tx_rs_thresh) *
+ txq->tx_rs_thresh;
+ if (desc >= txq->nb_tx_desc) {
+ desc -= txq->nb_tx_desc;
+ if (desc >= txq->nb_tx_desc)
+ desc -= txq->nb_tx_desc;
+ }
+
+ status = &txq->tx_ring[desc].wb.status;
+ if (*status & rte_cpu_to_le_32(IXGBE_ADVTXD_STAT_DD))
+ return RTE_ETH_TX_DESC_DONE;
+
+ return RTE_ETH_TX_DESC_FULL;
+}
+
void __attribute__((cold))
ixgbe_dev_clear_queues(struct rte_eth_dev *dev)
{
--
2.8.1
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH v2 3/6] net/e1000: implement descriptor status API (igb)
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 " Olivier Matz
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 1/6] ethdev: add descriptor status API Olivier Matz
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 2/6] net/ixgbe: implement " Olivier Matz
@ 2017-03-07 15:59 ` Olivier Matz
2017-03-08 1:17 ` Lu, Wenzhuo
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 4/6] net/e1000: implement descriptor status API (em) Olivier Matz
` (3 subsequent siblings)
6 siblings, 1 reply; 72+ messages in thread
From: Olivier Matz @ 2017-03-07 15:59 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson, venky.venkatesan, arybchenko
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
doc/guides/nics/features/igb.ini | 2 ++
doc/guides/nics/features/igb_vf.ini | 2 ++
drivers/net/e1000/e1000_ethdev.h | 3 +++
drivers/net/e1000/igb_ethdev.c | 2 ++
drivers/net/e1000/igb_rxtx.c | 45 +++++++++++++++++++++++++++++++++++++
5 files changed, 54 insertions(+)
diff --git a/doc/guides/nics/features/igb.ini b/doc/guides/nics/features/igb.ini
index 26ae008..6a7df60 100644
--- a/doc/guides/nics/features/igb.ini
+++ b/doc/guides/nics/features/igb.ini
@@ -33,6 +33,8 @@ L3 checksum offload = Y
L4 checksum offload = Y
Packet type parsing = Y
Timesync = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
FW version = Y
diff --git a/doc/guides/nics/features/igb_vf.ini b/doc/guides/nics/features/igb_vf.ini
index b617820..653b5da 100644
--- a/doc/guides/nics/features/igb_vf.ini
+++ b/doc/guides/nics/features/igb_vf.ini
@@ -17,6 +17,8 @@ QinQ offload = Y
L3 checksum offload = Y
L4 checksum offload = Y
Packet type parsing = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
Registers dump = Y
diff --git a/drivers/net/e1000/e1000_ethdev.h b/drivers/net/e1000/e1000_ethdev.h
index 81a6dbb..564438d 100644
--- a/drivers/net/e1000/e1000_ethdev.h
+++ b/drivers/net/e1000/e1000_ethdev.h
@@ -311,6 +311,9 @@ uint32_t eth_igb_rx_queue_count(struct rte_eth_dev *dev,
int eth_igb_rx_descriptor_done(void *rx_queue, uint16_t offset);
+int eth_igb_rx_descriptor_status(void *rx_queue, uint16_t offset);
+int eth_igb_tx_descriptor_status(void *tx_queue, uint16_t offset);
+
int eth_igb_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
uint16_t nb_tx_desc, unsigned int socket_id,
const struct rte_eth_txconf *tx_conf);
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index a112b38..f6ed824 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -406,6 +406,8 @@ static const struct eth_dev_ops eth_igb_ops = {
.rx_queue_release = eth_igb_rx_queue_release,
.rx_queue_count = eth_igb_rx_queue_count,
.rx_descriptor_done = eth_igb_rx_descriptor_done,
+ .rx_descriptor_status = eth_igb_rx_descriptor_status,
+ .tx_descriptor_status = eth_igb_tx_descriptor_status,
.tx_queue_setup = eth_igb_tx_queue_setup,
.tx_queue_release = eth_igb_tx_queue_release,
.dev_led_on = eth_igb_led_on,
diff --git a/drivers/net/e1000/igb_rxtx.c b/drivers/net/e1000/igb_rxtx.c
index c9cf392..7190738 100644
--- a/drivers/net/e1000/igb_rxtx.c
+++ b/drivers/net/e1000/igb_rxtx.c
@@ -1606,6 +1606,51 @@ eth_igb_rx_descriptor_done(void *rx_queue, uint16_t offset)
return !!(rxdp->wb.upper.status_error & E1000_RXD_STAT_DD);
}
+int
+eth_igb_rx_descriptor_status(void *rx_queue, uint16_t offset)
+{
+ struct igb_rx_queue *rxq = rx_queue;
+ volatile uint32_t *status;
+ uint32_t desc;
+
+ if (unlikely(offset >= rxq->nb_rx_desc))
+ return -EINVAL;
+
+ if (offset >= rxq->nb_rx_desc - rxq->nb_rx_hold)
+ return RTE_ETH_RX_DESC_UNAVAIL;
+
+ desc = rxq->rx_tail + offset;
+ if (desc >= rxq->nb_rx_desc)
+ desc -= rxq->nb_rx_desc;
+
+ status = &rxq->rx_ring[desc].wb.upper.status_error;
+ if (*status & rte_cpu_to_le_32(E1000_RXD_STAT_DD))
+ return RTE_ETH_RX_DESC_DONE;
+
+ return RTE_ETH_RX_DESC_AVAIL;
+}
+
+int
+eth_igb_tx_descriptor_status(void *tx_queue, uint16_t offset)
+{
+ struct igb_tx_queue *txq = tx_queue;
+ volatile uint32_t *status;
+ uint32_t desc;
+
+ if (unlikely(offset >= txq->nb_tx_desc))
+ return -EINVAL;
+
+ desc = txq->tx_tail + offset;
+ if (desc >= txq->nb_tx_desc)
+ desc -= txq->nb_tx_desc;
+
+ status = &txq->tx_ring[desc].wb.status;
+ if (*status & rte_cpu_to_le_32(E1000_TXD_STAT_DD))
+ return RTE_ETH_TX_DESC_DONE;
+
+ return RTE_ETH_TX_DESC_FULL;
+}
+
void
igb_dev_clear_queues(struct rte_eth_dev *dev)
{
--
2.8.1
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH v2 3/6] net/e1000: implement descriptor status API (igb)
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 3/6] net/e1000: implement descriptor status API (igb) Olivier Matz
@ 2017-03-08 1:17 ` Lu, Wenzhuo
0 siblings, 0 replies; 72+ messages in thread
From: Lu, Wenzhuo @ 2017-03-08 1:17 UTC (permalink / raw)
To: Olivier Matz, dev, thomas.monjalon, Ananyev, Konstantin, Zhang,
Helin, Wu, Jingjing, adrien.mazarguil, nelio.laranjeiro
Cc: Yigit, Ferruh, Richardson, Bruce, Venkatesan, Venky, arybchenko
Hi,
> -----Original Message-----
> From: Olivier Matz [mailto:olivier.matz@6wind.com]
> Sent: Wednesday, March 8, 2017 12:00 AM
> To: dev@dpdk.org; thomas.monjalon@6wind.com; Ananyev, Konstantin; Lu,
> Wenzhuo; Zhang, Helin; Wu, Jingjing; adrien.mazarguil@6wind.com;
> nelio.laranjeiro@6wind.com
> Cc: Yigit, Ferruh; Richardson, Bruce; Venkatesan, Venky;
> arybchenko@solarflare.com
> Subject: [PATCH v2 3/6] net/e1000: implement descriptor status API (igb)
>
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH v2 4/6] net/e1000: implement descriptor status API (em)
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 " Olivier Matz
` (2 preceding siblings ...)
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 3/6] net/e1000: implement descriptor status API (igb) Olivier Matz
@ 2017-03-07 15:59 ` Olivier Matz
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 5/6] net/mlx5: implement descriptor status API Olivier Matz
` (2 subsequent siblings)
6 siblings, 0 replies; 72+ messages in thread
From: Olivier Matz @ 2017-03-07 15:59 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson, venky.venkatesan, arybchenko
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
doc/guides/nics/features/e1000.ini | 2 ++
drivers/net/e1000/e1000_ethdev.h | 3 +++
drivers/net/e1000/em_ethdev.c | 2 ++
drivers/net/e1000/em_rxtx.c | 51 ++++++++++++++++++++++++++++++++++++++
4 files changed, 58 insertions(+)
diff --git a/doc/guides/nics/features/e1000.ini b/doc/guides/nics/features/e1000.ini
index 7f6d55c..4b95730 100644
--- a/doc/guides/nics/features/e1000.ini
+++ b/doc/guides/nics/features/e1000.ini
@@ -20,6 +20,8 @@ VLAN offload = Y
QinQ offload = Y
L3 checksum offload = Y
L4 checksum offload = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
BSD nic_uio = Y
Linux UIO = Y
diff --git a/drivers/net/e1000/e1000_ethdev.h b/drivers/net/e1000/e1000_ethdev.h
index 564438d..cb8d273 100644
--- a/drivers/net/e1000/e1000_ethdev.h
+++ b/drivers/net/e1000/e1000_ethdev.h
@@ -378,6 +378,9 @@ uint32_t eth_em_rx_queue_count(struct rte_eth_dev *dev,
int eth_em_rx_descriptor_done(void *rx_queue, uint16_t offset);
+int eth_em_rx_descriptor_status(void *rx_queue, uint16_t offset);
+int eth_em_tx_descriptor_status(void *tx_queue, uint16_t offset);
+
int eth_em_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
uint16_t nb_tx_desc, unsigned int socket_id,
const struct rte_eth_txconf *tx_conf);
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 4066ef9..4f34c14 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -205,6 +205,8 @@ static const struct eth_dev_ops eth_em_ops = {
.rx_queue_release = eth_em_rx_queue_release,
.rx_queue_count = eth_em_rx_queue_count,
.rx_descriptor_done = eth_em_rx_descriptor_done,
+ .rx_descriptor_status = eth_em_rx_descriptor_status,
+ .tx_descriptor_status = eth_em_tx_descriptor_status,
.tx_queue_setup = eth_em_tx_queue_setup,
.tx_queue_release = eth_em_tx_queue_release,
.rx_queue_intr_enable = eth_em_rx_queue_intr_enable,
diff --git a/drivers/net/e1000/em_rxtx.c b/drivers/net/e1000/em_rxtx.c
index d099d6a..2c9c7f8 100644
--- a/drivers/net/e1000/em_rxtx.c
+++ b/drivers/net/e1000/em_rxtx.c
@@ -1473,6 +1473,57 @@ eth_em_rx_descriptor_done(void *rx_queue, uint16_t offset)
return !!(rxdp->status & E1000_RXD_STAT_DD);
}
+int
+eth_em_rx_descriptor_status(void *rx_queue, uint16_t offset)
+{
+ struct em_rx_queue *rxq = rx_queue;
+ volatile uint8_t *status;
+ uint32_t desc;
+
+ if (unlikely(offset >= rxq->nb_rx_desc))
+ return -EINVAL;
+
+ if (offset >= rxq->nb_rx_desc - rxq->nb_rx_hold)
+ return RTE_ETH_RX_DESC_UNAVAIL;
+
+ desc = rxq->rx_tail + offset;
+ if (desc >= rxq->nb_rx_desc)
+ desc -= rxq->nb_rx_desc;
+
+ status = &rxq->rx_ring[desc].status;
+ if (*status & E1000_RXD_STAT_DD)
+ return RTE_ETH_RX_DESC_DONE;
+
+ return RTE_ETH_RX_DESC_AVAIL;
+}
+
+int
+eth_em_tx_descriptor_status(void *tx_queue, uint16_t offset)
+{
+ struct em_tx_queue *txq = tx_queue;
+ volatile uint8_t *status;
+ uint32_t desc;
+
+ if (unlikely(offset >= txq->nb_tx_desc))
+ return -EINVAL;
+
+ desc = txq->tx_tail + offset;
+ /* go to next desc that has the RS bit */
+ desc = ((desc + txq->tx_rs_thresh - 1) / txq->tx_rs_thresh) *
+ txq->tx_rs_thresh;
+ if (desc >= txq->nb_tx_desc) {
+ desc -= txq->nb_tx_desc;
+ if (desc >= txq->nb_tx_desc)
+ desc -= txq->nb_tx_desc;
+ }
+
+ status = &txq->tx_ring[desc].upper.fields.status;
+ if (*status & E1000_TXD_STAT_DD)
+ return RTE_ETH_TX_DESC_DONE;
+
+ return RTE_ETH_TX_DESC_FULL;
+}
+
void
em_dev_clear_queues(struct rte_eth_dev *dev)
{
--
2.8.1
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH v2 5/6] net/mlx5: implement descriptor status API
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 " Olivier Matz
` (3 preceding siblings ...)
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 4/6] net/e1000: implement descriptor status API (em) Olivier Matz
@ 2017-03-07 15:59 ` Olivier Matz
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 6/6] net/i40e: " Olivier Matz
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 0/6] get status of Rx and Tx descriptors Olivier Matz
6 siblings, 0 replies; 72+ messages in thread
From: Olivier Matz @ 2017-03-07 15:59 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson, venky.venkatesan, arybchenko
Since there is no "descriptor done" flag like on Intel drivers, the
approach is different on mlx5 driver.
- for Tx, we call txq_complete() to free descriptors processed by
the hw, then we check if the descriptor is between tail and head
- for Rx, we need to browse the cqes, managing compressed ones,
to get the number of used descriptors.
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
doc/guides/nics/features/mlx5.ini | 2 ++
drivers/net/mlx5/mlx5.c | 2 ++
drivers/net/mlx5/mlx5_rxtx.c | 76 +++++++++++++++++++++++++++++++++++++++
drivers/net/mlx5/mlx5_rxtx.h | 2 ++
4 files changed, 82 insertions(+)
diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini
index f20d214..1c92e37 100644
--- a/doc/guides/nics/features/mlx5.ini
+++ b/doc/guides/nics/features/mlx5.ini
@@ -27,6 +27,8 @@ VLAN offload = Y
L3 checksum offload = Y
L4 checksum offload = Y
Packet type parsing = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Stats per queue = Y
Multiprocess aware = Y
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index d4bd469..4a6450c 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -222,6 +222,8 @@ static const struct eth_dev_ops mlx5_dev_ops = {
.rss_hash_update = mlx5_rss_hash_update,
.rss_hash_conf_get = mlx5_rss_hash_conf_get,
.filter_ctrl = mlx5_dev_filter_ctrl,
+ .rx_descriptor_status = mlx5_rx_descriptor_status,
+ .tx_descriptor_status = mlx5_tx_descriptor_status,
};
static struct {
diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index 88b0354..b8d2bf6 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -345,6 +345,82 @@ mlx5_tx_dbrec(struct txq *txq, volatile struct mlx5_wqe *wqe)
}
/**
+ * DPDK callback to check the status of a tx descriptor.
+ *
+ * @param tx_queue
+ * The tx queue.
+ * @param[in] offset
+ * The index of the descriptor in the ring.
+ *
+ * @return
+ * The status of the tx descriptor.
+ */
+int
+mlx5_tx_descriptor_status(void *tx_queue, uint16_t offset)
+{
+ struct txq *txq = tx_queue;
+ const unsigned int elts_n = 1 << txq->elts_n;
+ const unsigned int elts_cnt = elts_n - 1;
+ unsigned int used;
+
+ txq_complete(txq);
+ used = (txq->elts_head - txq->elts_tail) & elts_cnt;
+ if (offset < used)
+ return RTE_ETH_TX_DESC_FULL;
+ return RTE_ETH_TX_DESC_DONE;
+}
+
+/**
+ * DPDK callback to check the status of a rx descriptor.
+ *
+ * @param rx_queue
+ * The rx queue.
+ * @param[in] offset
+ * The index of the descriptor in the ring.
+ *
+ * @return
+ * The status of the tx descriptor.
+ */
+int
+mlx5_rx_descriptor_status(void *rx_queue, uint16_t offset)
+{
+ struct rxq *rxq = rx_queue;
+ struct rxq_zip *zip = &rxq->zip;
+ volatile struct mlx5_cqe *cqe;
+ const unsigned int cqe_n = (1 << rxq->cqe_n);
+ const unsigned int cqe_cnt = cqe_n - 1;
+ unsigned int cq_ci;
+ unsigned int used;
+
+ /* if we are processing a compressed cqe */
+ if (zip->ai) {
+ used = zip->cqe_cnt - zip->ca;
+ cq_ci = zip->cq_ci;
+ } else {
+ used = 0;
+ cq_ci = rxq->cq_ci;
+ }
+ cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
+ while (check_cqe(cqe, cqe_n, cq_ci) == 0) {
+ int8_t op_own;
+ unsigned int n;
+
+ op_own = cqe->op_own;
+ if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED)
+ n = ntohl(cqe->byte_cnt);
+ else
+ n = 1;
+ cq_ci += n;
+ used += n;
+ cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
+ }
+ used = RTE_MIN(used, (1U << rxq->elts_n) - 1);
+ if (offset < used)
+ return RTE_ETH_RX_DESC_DONE;
+ return RTE_ETH_RX_DESC_AVAIL;
+}
+
+/**
* DPDK callback for TX.
*
* @param dpdk_txq
diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h
index 41a34d7..012207e 100644
--- a/drivers/net/mlx5/mlx5_rxtx.h
+++ b/drivers/net/mlx5/mlx5_rxtx.h
@@ -323,6 +323,8 @@ uint16_t mlx5_tx_burst_mpw_inline(void *, struct rte_mbuf **, uint16_t);
uint16_t mlx5_rx_burst(void *, struct rte_mbuf **, uint16_t);
uint16_t removed_tx_burst(void *, struct rte_mbuf **, uint16_t);
uint16_t removed_rx_burst(void *, struct rte_mbuf **, uint16_t);
+int mlx5_rx_descriptor_status(void *, uint16_t);
+int mlx5_tx_descriptor_status(void *, uint16_t);
/* mlx5_mr.c */
--
2.8.1
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH v2 6/6] net/i40e: implement descriptor status API
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 " Olivier Matz
` (4 preceding siblings ...)
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 5/6] net/mlx5: implement descriptor status API Olivier Matz
@ 2017-03-07 15:59 ` Olivier Matz
2017-03-08 1:17 ` Lu, Wenzhuo
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 0/6] get status of Rx and Tx descriptors Olivier Matz
6 siblings, 1 reply; 72+ messages in thread
From: Olivier Matz @ 2017-03-07 15:59 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson, venky.venkatesan, arybchenko
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
doc/guides/nics/features/i40e.ini | 2 ++
doc/guides/nics/features/i40e_vec.ini | 2 ++
doc/guides/nics/features/i40e_vf.ini | 2 ++
doc/guides/nics/features/i40e_vf_vec.ini | 2 ++
drivers/net/i40e/i40e_ethdev.c | 2 ++
drivers/net/i40e/i40e_ethdev_vf.c | 2 ++
drivers/net/i40e/i40e_rxtx.c | 58 ++++++++++++++++++++++++++++++++
drivers/net/i40e/i40e_rxtx.h | 2 ++
8 files changed, 72 insertions(+)
diff --git a/doc/guides/nics/features/i40e.ini b/doc/guides/nics/features/i40e.ini
index 6d11cce..4725f02 100644
--- a/doc/guides/nics/features/i40e.ini
+++ b/doc/guides/nics/features/i40e.ini
@@ -38,6 +38,8 @@ Inner L3 checksum = Y
Inner L4 checksum = Y
Packet type parsing = Y
Timesync = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
FW version = Y
diff --git a/doc/guides/nics/features/i40e_vec.ini b/doc/guides/nics/features/i40e_vec.ini
index edd6b71..2f95eb6 100644
--- a/doc/guides/nics/features/i40e_vec.ini
+++ b/doc/guides/nics/features/i40e_vec.ini
@@ -29,6 +29,8 @@ Flow director = Y
Flow control = Y
Traffic mirroring = Y
Timesync = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
Multiprocess aware = Y
diff --git a/doc/guides/nics/features/i40e_vf.ini b/doc/guides/nics/features/i40e_vf.ini
index 2f82c6b..60bdf7a 100644
--- a/doc/guides/nics/features/i40e_vf.ini
+++ b/doc/guides/nics/features/i40e_vf.ini
@@ -26,6 +26,8 @@ L4 checksum offload = Y
Inner L3 checksum = Y
Inner L4 checksum = Y
Packet type parsing = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
Multiprocess aware = Y
diff --git a/doc/guides/nics/features/i40e_vf_vec.ini b/doc/guides/nics/features/i40e_vf_vec.ini
index d6674f7..5766aaf 100644
--- a/doc/guides/nics/features/i40e_vf_vec.ini
+++ b/doc/guides/nics/features/i40e_vf_vec.ini
@@ -18,6 +18,8 @@ RSS key update = Y
RSS reta update = Y
VLAN filter = Y
Hash filter = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
Multiprocess aware = Y
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 303027b..8b5fd54 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -479,6 +479,8 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
.rx_queue_release = i40e_dev_rx_queue_release,
.rx_queue_count = i40e_dev_rx_queue_count,
.rx_descriptor_done = i40e_dev_rx_descriptor_done,
+ .rx_descriptor_status = i40e_dev_rx_descriptor_status,
+ .tx_descriptor_status = i40e_dev_tx_descriptor_status,
.tx_queue_setup = i40e_dev_tx_queue_setup,
.tx_queue_release = i40e_dev_tx_queue_release,
.dev_led_on = i40e_dev_led_on,
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 55fd344..d3659c9 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -217,6 +217,8 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = {
.rx_queue_intr_enable = i40evf_dev_rx_queue_intr_enable,
.rx_queue_intr_disable = i40evf_dev_rx_queue_intr_disable,
.rx_descriptor_done = i40e_dev_rx_descriptor_done,
+ .rx_descriptor_status = i40e_dev_rx_descriptor_status,
+ .tx_descriptor_status = i40e_dev_tx_descriptor_status,
.tx_queue_setup = i40e_dev_tx_queue_setup,
.tx_queue_release = i40e_dev_tx_queue_release,
.rx_queue_count = i40e_dev_rx_queue_count,
diff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c
index 48429cc..524be62 100644
--- a/drivers/net/i40e/i40e_rxtx.c
+++ b/drivers/net/i40e/i40e_rxtx.c
@@ -1929,6 +1929,64 @@ i40e_dev_rx_descriptor_done(void *rx_queue, uint16_t offset)
}
int
+i40e_dev_rx_descriptor_status(void *rx_queue, uint16_t offset)
+{
+ struct i40e_rx_queue *rxq = rx_queue;
+ volatile uint64_t *status;
+ uint64_t mask;
+ uint32_t desc;
+
+ if (unlikely(offset >= rxq->nb_rx_desc))
+ return -EINVAL;
+
+ if (offset >= rxq->nb_rx_desc - rxq->nb_rx_hold)
+ return RTE_ETH_RX_DESC_UNAVAIL;
+
+ desc = rxq->rx_tail + offset;
+ if (desc >= rxq->nb_rx_desc)
+ desc -= rxq->nb_rx_desc;
+
+ status = &rxq->rx_ring[desc].wb.qword1.status_error_len;
+ mask = rte_le_to_cpu_64((1ULL << I40E_RX_DESC_STATUS_DD_SHIFT)
+ << I40E_RXD_QW1_STATUS_SHIFT);
+ if (*status & mask)
+ return RTE_ETH_RX_DESC_DONE;
+
+ return RTE_ETH_RX_DESC_AVAIL;
+}
+
+int
+i40e_dev_tx_descriptor_status(void *tx_queue, uint16_t offset)
+{
+ struct i40e_tx_queue *txq = tx_queue;
+ volatile uint64_t *status;
+ uint64_t mask, expect;
+ uint32_t desc;
+
+ if (unlikely(offset >= txq->nb_tx_desc))
+ return -EINVAL;
+
+ desc = txq->tx_tail + offset;
+ /* go to next desc that has the RS bit */
+ desc = ((desc + txq->tx_rs_thresh - 1) / txq->tx_rs_thresh) *
+ txq->tx_rs_thresh;
+ if (desc >= txq->nb_tx_desc) {
+ desc -= txq->nb_tx_desc;
+ if (desc >= txq->nb_tx_desc)
+ desc -= txq->nb_tx_desc;
+ }
+
+ status = &txq->tx_ring[desc].cmd_type_offset_bsz;
+ mask = rte_le_to_cpu_64(I40E_TXD_QW1_DTYPE_MASK);
+ expect = rte_cpu_to_le_64(
+ I40E_TX_DESC_DTYPE_DESC_DONE << I40E_TXD_QW1_DTYPE_SHIFT);
+ if ((*status & mask) == expect)
+ return RTE_ETH_TX_DESC_DONE;
+
+ return RTE_ETH_TX_DESC_FULL;
+}
+
+int
i40e_dev_tx_queue_setup(struct rte_eth_dev *dev,
uint16_t queue_idx,
uint16_t nb_desc,
diff --git a/drivers/net/i40e/i40e_rxtx.h b/drivers/net/i40e/i40e_rxtx.h
index 9df8a56..7f63328 100644
--- a/drivers/net/i40e/i40e_rxtx.h
+++ b/drivers/net/i40e/i40e_rxtx.h
@@ -246,6 +246,8 @@ void i40e_rx_queue_release_mbufs(struct i40e_rx_queue *rxq);
uint32_t i40e_dev_rx_queue_count(struct rte_eth_dev *dev,
uint16_t rx_queue_id);
int i40e_dev_rx_descriptor_done(void *rx_queue, uint16_t offset);
+int i40e_dev_rx_descriptor_status(void *rx_queue, uint16_t offset);
+int i40e_dev_tx_descriptor_status(void *tx_queue, uint16_t offset);
uint16_t i40e_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
uint16_t nb_pkts);
--
2.8.1
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH v2 6/6] net/i40e: implement descriptor status API
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 6/6] net/i40e: " Olivier Matz
@ 2017-03-08 1:17 ` Lu, Wenzhuo
0 siblings, 0 replies; 72+ messages in thread
From: Lu, Wenzhuo @ 2017-03-08 1:17 UTC (permalink / raw)
To: Olivier Matz, dev, thomas.monjalon, Ananyev, Konstantin, Zhang,
Helin, Wu, Jingjing, adrien.mazarguil, nelio.laranjeiro
Cc: Yigit, Ferruh, Richardson, Bruce, Venkatesan, Venky, arybchenko
Hi,
> -----Original Message-----
> From: Olivier Matz [mailto:olivier.matz@6wind.com]
> Sent: Wednesday, March 8, 2017 12:00 AM
> To: dev@dpdk.org; thomas.monjalon@6wind.com; Ananyev, Konstantin; Lu,
> Wenzhuo; Zhang, Helin; Wu, Jingjing; adrien.mazarguil@6wind.com;
> nelio.laranjeiro@6wind.com
> Cc: Yigit, Ferruh; Richardson, Bruce; Venkatesan, Venky;
> arybchenko@solarflare.com
> Subject: [PATCH v2 6/6] net/i40e: implement descriptor status API
>
> Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH v3 0/6] get status of Rx and Tx descriptors
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 " Olivier Matz
` (5 preceding siblings ...)
2017-03-07 15:59 ` [dpdk-dev] [PATCH v2 6/6] net/i40e: " Olivier Matz
@ 2017-03-29 8:36 ` Olivier Matz
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 1/6] ethdev: add descriptor status API Olivier Matz
` (6 more replies)
6 siblings, 7 replies; 72+ messages in thread
From: Olivier Matz @ 2017-03-29 8:36 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson, venky.venkatesan, arybchenko,
qiming.yang
This patchset introduces a new ethdev API:
- rte_eth_rx_descriptor_status()
- rte_eth_tx_descriptor_status()
The Rx API is aims to replace rte_eth_rx_descriptor_done() which
does almost the same, but does not differentiate the case of a
descriptor used by the driver (not returned to the hw).
The usage of these functions can be:
- on Rx, anticipate that the cpu is not fast enough to process
all incoming packets, and take dispositions to solve the
problem (add more cpus, drop specific packets, ...)
- on Tx, detect that the link is overloaded, and take dispositions
to solve the problem (notify flow control, drop specific
packets)
The patchset updates ixgbe, i40e, e1000, mlx5.
The other drivers that implement the descriptor_done() API are
fm10k, sfc, virtio. They are not updated.
If the new API is accepted, the descriptor_done() can be deprecated,
and examples/l3fwd-power will be updated to.
v2->v3:
- add an entry in the release note
- rebase on top of net-next/master
v1->v2:
- replace RTE_ETH_RX_DESC_USED by RTE_ETH_RX_DESC_UNAVAIL: it can be used when
the descriptor is hold by driver or reserved by the hardware.
- add RTE_ETH_TX_DESC_UNAVAIL (same for Tx)
- change the ethdev callback api to use a queue pointer instead of port_id
and queue_id
- like rx_burst/tx_burst, do not check the validity of port_id and queue_id
except in debug mode
- better document the calling context, error status, possible performance
impact
- add the feature in NIC documentation
- fix overflow of descriptor value in tx functions (ixgbe, igb, em)
- fix tx function to only check descs that have the rs bit (i40e)
- mlx: remove empty line
RFC->v1:
- instead of optimizing an API that returns the number of used
descriptors like rx_queue_count(), use a more simple API that
returns the status of a descriptor, like rx_descriptor_done().
- remove ethdev api rework (first 2 patches), they have been
sent separately
Olivier Matz (6):
ethdev: add descriptor status API
net/ixgbe: implement descriptor status API
net/e1000: implement descriptor status API (igb)
net/e1000: implement descriptor status API (em)
net/mlx5: implement descriptor status API
net/i40e: implement descriptor status API
doc/guides/nics/features/default.ini | 2 +
doc/guides/nics/features/e1000.ini | 2 +
doc/guides/nics/features/i40e.ini | 2 +
doc/guides/nics/features/i40e_vec.ini | 2 +
doc/guides/nics/features/i40e_vf.ini | 2 +
doc/guides/nics/features/i40e_vf_vec.ini | 2 +
doc/guides/nics/features/igb.ini | 2 +
doc/guides/nics/features/igb_vf.ini | 2 +
doc/guides/nics/features/ixgbe.ini | 2 +
doc/guides/nics/features/ixgbe_vec.ini | 2 +
doc/guides/nics/features/ixgbe_vf.ini | 2 +
doc/guides/nics/features/ixgbe_vf_vec.ini | 2 +
doc/guides/nics/features/mlx5.ini | 2 +
doc/guides/rel_notes/release_17_02.rst | 8 ++
drivers/net/e1000/e1000_ethdev.h | 6 ++
drivers/net/e1000/em_ethdev.c | 2 +
drivers/net/e1000/em_rxtx.c | 51 ++++++++++++
drivers/net/e1000/igb_ethdev.c | 2 +
drivers/net/e1000/igb_rxtx.c | 45 +++++++++++
drivers/net/i40e/i40e_ethdev.c | 2 +
drivers/net/i40e/i40e_ethdev_vf.c | 2 +
drivers/net/i40e/i40e_rxtx.c | 58 ++++++++++++++
drivers/net/i40e/i40e_rxtx.h | 2 +
drivers/net/ixgbe/ixgbe_ethdev.c | 4 +
drivers/net/ixgbe/ixgbe_ethdev.h | 3 +
drivers/net/ixgbe/ixgbe_rxtx.c | 57 ++++++++++++++
drivers/net/mlx5/mlx5.c | 2 +
drivers/net/mlx5/mlx5_rxtx.c | 76 ++++++++++++++++++
drivers/net/mlx5/mlx5_rxtx.h | 2 +
lib/librte_ether/rte_ethdev.h | 125 ++++++++++++++++++++++++++++++
30 files changed, 473 insertions(+)
--
2.11.0
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH v3 1/6] ethdev: add descriptor status API
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 0/6] get status of Rx and Tx descriptors Olivier Matz
@ 2017-03-29 8:36 ` Olivier Matz
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 2/6] net/ixgbe: implement " Olivier Matz
` (5 subsequent siblings)
6 siblings, 0 replies; 72+ messages in thread
From: Olivier Matz @ 2017-03-29 8:36 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson, venky.venkatesan, arybchenko,
qiming.yang
Introduce a new API to get the status of a descriptor.
For Rx, it is almost similar to rx_descriptor_done API, except it
differentiates "used" descriptors (which are hold by the driver and not
returned to the hardware).
For Tx, it is a new API.
The descriptor_done() API, and probably the rx_queue_count() API could
be replaced by this new API as soon as it is implemented on all PMDs.
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
Reviewed-by: Andrew Rybchenko <arybchenko@solarflare.com>
---
doc/guides/nics/features/default.ini | 2 +
doc/guides/rel_notes/release_17_02.rst | 8 +++
lib/librte_ether/rte_ethdev.h | 125 +++++++++++++++++++++++++++++++++
3 files changed, 135 insertions(+)
diff --git a/doc/guides/nics/features/default.ini b/doc/guides/nics/features/default.ini
index 0135c0c4e..effdbe642 100644
--- a/doc/guides/nics/features/default.ini
+++ b/doc/guides/nics/features/default.ini
@@ -51,6 +51,8 @@ Inner L3 checksum =
Inner L4 checksum =
Packet type parsing =
Timesync =
+Rx Descriptor Status =
+Tx Descriptor Status =
Basic stats =
Extended stats =
Stats per queue =
diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst
index 357965ac9..524d2ac2b 100644
--- a/doc/guides/rel_notes/release_17_02.rst
+++ b/doc/guides/rel_notes/release_17_02.rst
@@ -250,6 +250,14 @@ New Features
See the :ref:`Elastic Flow Distributor Library <Efd_Library>` documentation in
the Programmers Guide document, for more information.
+* **Added descriptor status ethdev API.**
+
+ Added a new API to get the status of a descriptor.
+
+ For Rx, it is almost similar to the *rx_descriptor_done* API, except
+ it differentiates descriptors which are hold by the driver and not
+ returned to the hardware. For Tx, it is a new API.
+
Resolved Issues
---------------
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index b3ee8728b..71a35f242 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -1179,6 +1179,12 @@ typedef uint32_t (*eth_rx_queue_count_t)(struct rte_eth_dev *dev,
typedef int (*eth_rx_descriptor_done_t)(void *rxq, uint16_t offset);
/**< @internal Check DD bit of specific RX descriptor */
+typedef int (*eth_rx_descriptor_status_t)(void *rxq, uint16_t offset);
+/**< @internal Check the status of a Rx descriptor */
+
+typedef int (*eth_tx_descriptor_status_t)(void *txq, uint16_t offset);
+/**< @internal Check the status of a Tx descriptor */
+
typedef int (*eth_fw_version_get_t)(struct rte_eth_dev *dev,
char *fw_version, size_t fw_size);
/**< @internal Get firmware information of an Ethernet device. */
@@ -1487,6 +1493,10 @@ struct eth_dev_ops {
eth_rx_queue_count_t rx_queue_count;
/**< Get the number of used RX descriptors. */
eth_rx_descriptor_done_t rx_descriptor_done; /**< Check rxd DD bit. */
+ eth_rx_descriptor_status_t rx_descriptor_status;
+ /**< Check the status of a Rx descriptor. */
+ eth_tx_descriptor_status_t tx_descriptor_status;
+ /**< Check the status of a Tx descriptor. */
eth_rx_enable_intr_t rx_queue_intr_enable; /**< Enable Rx queue interrupt. */
eth_rx_disable_intr_t rx_queue_intr_disable; /**< Disable Rx queue interrupt. */
eth_tx_queue_setup_t tx_queue_setup;/**< Set up device TX queue. */
@@ -2778,6 +2788,121 @@ rte_eth_rx_descriptor_done(uint8_t port_id, uint16_t queue_id, uint16_t offset)
dev->data->rx_queues[queue_id], offset);
}
+#define RTE_ETH_RX_DESC_AVAIL 0 /**< Desc available for hw. */
+#define RTE_ETH_RX_DESC_DONE 1 /**< Desc done, filled by hw. */
+#define RTE_ETH_RX_DESC_UNAVAIL 2 /**< Desc used by driver or hw. */
+
+/**
+ * Check the status of a Rx descriptor in the queue
+ *
+ * It should be called in a similar context than the Rx function:
+ * - on a dataplane core
+ * - not concurrently on the same queue
+ *
+ * Since it's a dataplane function, no check is performed on port_id and
+ * queue_id. The caller must therefore ensure that the port is enabled
+ * and the queue is configured and running.
+ *
+ * Note: accessing to a random descriptor in the ring may trigger cache
+ * misses and have a performance impact.
+ *
+ * @param port_id
+ * A valid port identifier of the Ethernet device which.
+ * @param queue_id
+ * A valid Rx queue identifier on this port.
+ * @param offset
+ * The offset of the descriptor starting from tail (0 is the next
+ * packet to be received by the driver).
+ *
+ * @return
+ * - (RTE_ETH_RX_DESC_AVAIL): Descriptor is available for the hardware to
+ * receive a packet.
+ * - (RTE_ETH_RX_DESC_DONE): Descriptor is done, it is filled by hw, but
+ * not yet processed by the driver (i.e. in the receive queue).
+ * - (RTE_ETH_RX_DESC_UNAVAIL): Descriptor is unavailable, either hold by
+ * the driver and not yet returned to hw, or reserved by the hw.
+ * - (-EINVAL) bad descriptor offset.
+ * - (-ENOTSUP) if the device does not support this function.
+ * - (-ENODEV) bad port or queue (only if compiled with debug).
+ */
+static inline int
+rte_eth_rx_descriptor_status(uint8_t port_id, uint16_t queue_id,
+ uint16_t offset)
+{
+ struct rte_eth_dev *dev;
+ void *rxq;
+
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+#endif
+ dev = &rte_eth_devices[port_id];
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ if (queue_id >= dev->data->nb_rx_queues)
+ return -ENODEV;
+#endif
+ RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->rx_descriptor_status, -ENOTSUP);
+ rxq = dev->data->rx_queues[queue_id];
+
+ return (*dev->dev_ops->rx_descriptor_status)(rxq, offset);
+}
+
+#define RTE_ETH_TX_DESC_FULL 0 /**< Desc filled for hw, waiting xmit. */
+#define RTE_ETH_TX_DESC_DONE 1 /**< Desc done, packet is transmitted. */
+#define RTE_ETH_TX_DESC_UNAVAIL 2 /**< Desc used by driver or hw. */
+
+/**
+ * Check the status of a Tx descriptor in the queue.
+ *
+ * It should be called in a similar context than the Tx function:
+ * - on a dataplane core
+ * - not concurrently on the same queue
+ *
+ * Since it's a dataplane function, no check is performed on port_id and
+ * queue_id. The caller must therefore ensure that the port is enabled
+ * and the queue is configured and running.
+ *
+ * Note: accessing to a random descriptor in the ring may trigger cache
+ * misses and have a performance impact.
+ *
+ * @param port_id
+ * A valid port identifier of the Ethernet device which.
+ * @param queue_id
+ * A valid Tx queue identifier on this port.
+ * @param offset
+ * The offset of the descriptor starting from tail (0 is the place where
+ * the next packet will be send).
+ *
+ * @return
+ * - (RTE_ETH_TX_DESC_FULL) Descriptor is being processed by the hw, i.e.
+ * in the transmit queue.
+ * - (RTE_ETH_TX_DESC_DONE) Hardware is done with this descriptor, it can
+ * be reused by the driver.
+ * - (RTE_ETH_TX_DESC_UNAVAIL): Descriptor is unavailable, reserved by the
+ * driver or the hardware.
+ * - (-EINVAL) bad descriptor offset.
+ * - (-ENOTSUP) if the device does not support this function.
+ * - (-ENODEV) bad port or queue (only if compiled with debug).
+ */
+static inline int rte_eth_tx_descriptor_status(uint8_t port_id,
+ uint16_t queue_id, uint16_t offset)
+{
+ struct rte_eth_dev *dev;
+ void *txq;
+
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+#endif
+ dev = &rte_eth_devices[port_id];
+#ifdef RTE_LIBRTE_ETHDEV_DEBUG
+ if (queue_id >= dev->data->nb_tx_queues)
+ return -ENODEV;
+#endif
+ RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->tx_descriptor_status, -ENOTSUP);
+ txq = dev->data->tx_queues[queue_id];
+
+ return (*dev->dev_ops->tx_descriptor_status)(txq, offset);
+}
+
/**
* Send a burst of output packets on a transmit queue of an Ethernet device.
*
--
2.11.0
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH v3 2/6] net/ixgbe: implement descriptor status API
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 0/6] get status of Rx and Tx descriptors Olivier Matz
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 1/6] ethdev: add descriptor status API Olivier Matz
@ 2017-03-29 8:36 ` Olivier Matz
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 3/6] net/e1000: implement descriptor status API (igb) Olivier Matz
` (4 subsequent siblings)
6 siblings, 0 replies; 72+ messages in thread
From: Olivier Matz @ 2017-03-29 8:36 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson, venky.venkatesan, arybchenko,
qiming.yang
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
doc/guides/nics/features/ixgbe.ini | 2 ++
doc/guides/nics/features/ixgbe_vec.ini | 2 ++
doc/guides/nics/features/ixgbe_vf.ini | 2 ++
doc/guides/nics/features/ixgbe_vf_vec.ini | 2 ++
drivers/net/ixgbe/ixgbe_ethdev.c | 4 +++
drivers/net/ixgbe/ixgbe_ethdev.h | 3 ++
drivers/net/ixgbe/ixgbe_rxtx.c | 57 +++++++++++++++++++++++++++++++
7 files changed, 72 insertions(+)
diff --git a/doc/guides/nics/features/ixgbe.ini b/doc/guides/nics/features/ixgbe.ini
index e65bbb883..d59ed43fc 100644
--- a/doc/guides/nics/features/ixgbe.ini
+++ b/doc/guides/nics/features/ixgbe.ini
@@ -42,6 +42,8 @@ Inner L3 checksum = Y
Inner L4 checksum = Y
Packet type parsing = Y
Timesync = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
Stats per queue = Y
diff --git a/doc/guides/nics/features/ixgbe_vec.ini b/doc/guides/nics/features/ixgbe_vec.ini
index e1773dd6a..1a9326e5d 100644
--- a/doc/guides/nics/features/ixgbe_vec.ini
+++ b/doc/guides/nics/features/ixgbe_vec.ini
@@ -32,6 +32,8 @@ Flow control = Y
Rate limitation = Y
Traffic mirroring = Y
Timesync = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
Stats per queue = Y
diff --git a/doc/guides/nics/features/ixgbe_vf.ini b/doc/guides/nics/features/ixgbe_vf.ini
index bf28215da..8be1db8ac 100644
--- a/doc/guides/nics/features/ixgbe_vf.ini
+++ b/doc/guides/nics/features/ixgbe_vf.ini
@@ -25,6 +25,8 @@ L4 checksum offload = Y
Inner L3 checksum = Y
Inner L4 checksum = Y
Packet type parsing = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
Registers dump = Y
diff --git a/doc/guides/nics/features/ixgbe_vf_vec.ini b/doc/guides/nics/features/ixgbe_vf_vec.ini
index 8b8c90ba8..f02251f8b 100644
--- a/doc/guides/nics/features/ixgbe_vf_vec.ini
+++ b/doc/guides/nics/features/ixgbe_vf_vec.ini
@@ -17,6 +17,8 @@ RSS hash = Y
RSS key update = Y
RSS reta update = Y
VLAN filter = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
Registers dump = Y
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 8a249db91..4fd22c5ee 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -548,6 +548,8 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
.rx_queue_release = ixgbe_dev_rx_queue_release,
.rx_queue_count = ixgbe_dev_rx_queue_count,
.rx_descriptor_done = ixgbe_dev_rx_descriptor_done,
+ .rx_descriptor_status = ixgbe_dev_rx_descriptor_status,
+ .tx_descriptor_status = ixgbe_dev_tx_descriptor_status,
.tx_queue_setup = ixgbe_dev_tx_queue_setup,
.tx_queue_release = ixgbe_dev_tx_queue_release,
.dev_led_on = ixgbe_dev_led_on,
@@ -626,6 +628,8 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops = {
.rx_queue_setup = ixgbe_dev_rx_queue_setup,
.rx_queue_release = ixgbe_dev_rx_queue_release,
.rx_descriptor_done = ixgbe_dev_rx_descriptor_done,
+ .rx_descriptor_status = ixgbe_dev_rx_descriptor_status,
+ .tx_descriptor_status = ixgbe_dev_tx_descriptor_status,
.tx_queue_setup = ixgbe_dev_tx_queue_setup,
.tx_queue_release = ixgbe_dev_tx_queue_release,
.rx_queue_intr_enable = ixgbevf_dev_rx_queue_intr_enable,
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.h b/drivers/net/ixgbe/ixgbe_ethdev.h
index 058ad8700..f4ff6ad04 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.h
+++ b/drivers/net/ixgbe/ixgbe_ethdev.h
@@ -527,6 +527,9 @@ uint32_t ixgbe_dev_rx_queue_count(struct rte_eth_dev *dev,
int ixgbe_dev_rx_descriptor_done(void *rx_queue, uint16_t offset);
+int ixgbe_dev_rx_descriptor_status(void *rx_queue, uint16_t offset);
+int ixgbe_dev_tx_descriptor_status(void *tx_queue, uint16_t offset);
+
int ixgbe_dev_rx_init(struct rte_eth_dev *dev);
void ixgbe_dev_tx_init(struct rte_eth_dev *dev);
diff --git a/drivers/net/ixgbe/ixgbe_rxtx.c b/drivers/net/ixgbe/ixgbe_rxtx.c
index c0805666b..c9993abc6 100644
--- a/drivers/net/ixgbe/ixgbe_rxtx.c
+++ b/drivers/net/ixgbe/ixgbe_rxtx.c
@@ -2945,6 +2945,63 @@ ixgbe_dev_rx_descriptor_done(void *rx_queue, uint16_t offset)
rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD));
}
+int
+ixgbe_dev_rx_descriptor_status(void *rx_queue, uint16_t offset)
+{
+ struct ixgbe_rx_queue *rxq = rx_queue;
+ volatile uint32_t *status;
+ uint32_t nb_hold, desc;
+
+ if (unlikely(offset >= rxq->nb_rx_desc))
+ return -EINVAL;
+
+#ifdef RTE_IXGBE_INC_VECTOR
+ if (rxq->rx_using_sse)
+ nb_hold = rxq->rxrearm_nb;
+ else
+#endif
+ nb_hold = rxq->nb_rx_hold;
+ if (offset >= rxq->nb_rx_desc - nb_hold)
+ return RTE_ETH_RX_DESC_UNAVAIL;
+
+ desc = rxq->rx_tail + offset;
+ if (desc >= rxq->nb_rx_desc)
+ desc -= rxq->nb_rx_desc;
+
+ status = &rxq->rx_ring[desc].wb.upper.status_error;
+ if (*status & rte_cpu_to_le_32(IXGBE_RXDADV_STAT_DD))
+ return RTE_ETH_RX_DESC_DONE;
+
+ return RTE_ETH_RX_DESC_AVAIL;
+}
+
+int
+ixgbe_dev_tx_descriptor_status(void *tx_queue, uint16_t offset)
+{
+ struct ixgbe_tx_queue *txq = tx_queue;
+ volatile uint32_t *status;
+ uint32_t desc;
+
+ if (unlikely(offset >= txq->nb_tx_desc))
+ return -EINVAL;
+
+ desc = txq->tx_tail + offset;
+ /* go to next desc that has the RS bit */
+ desc = ((desc + txq->tx_rs_thresh - 1) / txq->tx_rs_thresh) *
+ txq->tx_rs_thresh;
+ if (desc >= txq->nb_tx_desc) {
+ desc -= txq->nb_tx_desc;
+ if (desc >= txq->nb_tx_desc)
+ desc -= txq->nb_tx_desc;
+ }
+
+ status = &txq->tx_ring[desc].wb.status;
+ if (*status & rte_cpu_to_le_32(IXGBE_ADVTXD_STAT_DD))
+ return RTE_ETH_TX_DESC_DONE;
+
+ return RTE_ETH_TX_DESC_FULL;
+}
+
void __attribute__((cold))
ixgbe_dev_clear_queues(struct rte_eth_dev *dev)
{
--
2.11.0
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH v3 3/6] net/e1000: implement descriptor status API (igb)
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 0/6] get status of Rx and Tx descriptors Olivier Matz
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 1/6] ethdev: add descriptor status API Olivier Matz
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 2/6] net/ixgbe: implement " Olivier Matz
@ 2017-03-29 8:36 ` Olivier Matz
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 4/6] net/e1000: implement descriptor status API (em) Olivier Matz
` (3 subsequent siblings)
6 siblings, 0 replies; 72+ messages in thread
From: Olivier Matz @ 2017-03-29 8:36 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson, venky.venkatesan, arybchenko,
qiming.yang
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
doc/guides/nics/features/igb.ini | 2 ++
doc/guides/nics/features/igb_vf.ini | 2 ++
drivers/net/e1000/e1000_ethdev.h | 3 +++
drivers/net/e1000/igb_ethdev.c | 2 ++
drivers/net/e1000/igb_rxtx.c | 45 +++++++++++++++++++++++++++++++++++++
5 files changed, 54 insertions(+)
diff --git a/doc/guides/nics/features/igb.ini b/doc/guides/nics/features/igb.ini
index 26ae008b3..6a7df6071 100644
--- a/doc/guides/nics/features/igb.ini
+++ b/doc/guides/nics/features/igb.ini
@@ -33,6 +33,8 @@ L3 checksum offload = Y
L4 checksum offload = Y
Packet type parsing = Y
Timesync = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
FW version = Y
diff --git a/doc/guides/nics/features/igb_vf.ini b/doc/guides/nics/features/igb_vf.ini
index b61782028..653b5da87 100644
--- a/doc/guides/nics/features/igb_vf.ini
+++ b/doc/guides/nics/features/igb_vf.ini
@@ -17,6 +17,8 @@ QinQ offload = Y
L3 checksum offload = Y
L4 checksum offload = Y
Packet type parsing = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
Registers dump = Y
diff --git a/drivers/net/e1000/e1000_ethdev.h b/drivers/net/e1000/e1000_ethdev.h
index 39b2f435b..cb760e986 100644
--- a/drivers/net/e1000/e1000_ethdev.h
+++ b/drivers/net/e1000/e1000_ethdev.h
@@ -311,6 +311,9 @@ uint32_t eth_igb_rx_queue_count(struct rte_eth_dev *dev,
int eth_igb_rx_descriptor_done(void *rx_queue, uint16_t offset);
+int eth_igb_rx_descriptor_status(void *rx_queue, uint16_t offset);
+int eth_igb_tx_descriptor_status(void *tx_queue, uint16_t offset);
+
int eth_igb_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
uint16_t nb_tx_desc, unsigned int socket_id,
const struct rte_eth_txconf *tx_conf);
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 71d05a938..a73cd7a02 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -406,6 +406,8 @@ static const struct eth_dev_ops eth_igb_ops = {
.rx_queue_release = eth_igb_rx_queue_release,
.rx_queue_count = eth_igb_rx_queue_count,
.rx_descriptor_done = eth_igb_rx_descriptor_done,
+ .rx_descriptor_status = eth_igb_rx_descriptor_status,
+ .tx_descriptor_status = eth_igb_tx_descriptor_status,
.tx_queue_setup = eth_igb_tx_queue_setup,
.tx_queue_release = eth_igb_tx_queue_release,
.tx_done_cleanup = eth_igb_tx_done_cleanup,
diff --git a/drivers/net/e1000/igb_rxtx.c b/drivers/net/e1000/igb_rxtx.c
index cba3704ba..b3b601b79 100644
--- a/drivers/net/e1000/igb_rxtx.c
+++ b/drivers/net/e1000/igb_rxtx.c
@@ -1727,6 +1727,51 @@ eth_igb_rx_descriptor_done(void *rx_queue, uint16_t offset)
return !!(rxdp->wb.upper.status_error & E1000_RXD_STAT_DD);
}
+int
+eth_igb_rx_descriptor_status(void *rx_queue, uint16_t offset)
+{
+ struct igb_rx_queue *rxq = rx_queue;
+ volatile uint32_t *status;
+ uint32_t desc;
+
+ if (unlikely(offset >= rxq->nb_rx_desc))
+ return -EINVAL;
+
+ if (offset >= rxq->nb_rx_desc - rxq->nb_rx_hold)
+ return RTE_ETH_RX_DESC_UNAVAIL;
+
+ desc = rxq->rx_tail + offset;
+ if (desc >= rxq->nb_rx_desc)
+ desc -= rxq->nb_rx_desc;
+
+ status = &rxq->rx_ring[desc].wb.upper.status_error;
+ if (*status & rte_cpu_to_le_32(E1000_RXD_STAT_DD))
+ return RTE_ETH_RX_DESC_DONE;
+
+ return RTE_ETH_RX_DESC_AVAIL;
+}
+
+int
+eth_igb_tx_descriptor_status(void *tx_queue, uint16_t offset)
+{
+ struct igb_tx_queue *txq = tx_queue;
+ volatile uint32_t *status;
+ uint32_t desc;
+
+ if (unlikely(offset >= txq->nb_tx_desc))
+ return -EINVAL;
+
+ desc = txq->tx_tail + offset;
+ if (desc >= txq->nb_tx_desc)
+ desc -= txq->nb_tx_desc;
+
+ status = &txq->tx_ring[desc].wb.status;
+ if (*status & rte_cpu_to_le_32(E1000_TXD_STAT_DD))
+ return RTE_ETH_TX_DESC_DONE;
+
+ return RTE_ETH_TX_DESC_FULL;
+}
+
void
igb_dev_clear_queues(struct rte_eth_dev *dev)
{
--
2.11.0
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH v3 4/6] net/e1000: implement descriptor status API (em)
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 0/6] get status of Rx and Tx descriptors Olivier Matz
` (2 preceding siblings ...)
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 3/6] net/e1000: implement descriptor status API (igb) Olivier Matz
@ 2017-03-29 8:36 ` Olivier Matz
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 5/6] net/mlx5: implement descriptor status API Olivier Matz
` (2 subsequent siblings)
6 siblings, 0 replies; 72+ messages in thread
From: Olivier Matz @ 2017-03-29 8:36 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson, venky.venkatesan, arybchenko,
qiming.yang
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
doc/guides/nics/features/e1000.ini | 2 ++
drivers/net/e1000/e1000_ethdev.h | 3 +++
drivers/net/e1000/em_ethdev.c | 2 ++
drivers/net/e1000/em_rxtx.c | 51 ++++++++++++++++++++++++++++++++++++++
4 files changed, 58 insertions(+)
diff --git a/doc/guides/nics/features/e1000.ini b/doc/guides/nics/features/e1000.ini
index 3aed7d709..6a7c6c7d7 100644
--- a/doc/guides/nics/features/e1000.ini
+++ b/doc/guides/nics/features/e1000.ini
@@ -21,6 +21,8 @@ VLAN offload = Y
QinQ offload = Y
L3 checksum offload = Y
L4 checksum offload = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
BSD nic_uio = Y
Linux UIO = Y
diff --git a/drivers/net/e1000/e1000_ethdev.h b/drivers/net/e1000/e1000_ethdev.h
index cb760e986..8352d0a79 100644
--- a/drivers/net/e1000/e1000_ethdev.h
+++ b/drivers/net/e1000/e1000_ethdev.h
@@ -380,6 +380,9 @@ uint32_t eth_em_rx_queue_count(struct rte_eth_dev *dev,
int eth_em_rx_descriptor_done(void *rx_queue, uint16_t offset);
+int eth_em_rx_descriptor_status(void *rx_queue, uint16_t offset);
+int eth_em_tx_descriptor_status(void *tx_queue, uint16_t offset);
+
int eth_em_tx_queue_setup(struct rte_eth_dev *dev, uint16_t tx_queue_id,
uint16_t nb_tx_desc, unsigned int socket_id,
const struct rte_eth_txconf *tx_conf);
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index e76e34bbe..7110af344 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -205,6 +205,8 @@ static const struct eth_dev_ops eth_em_ops = {
.rx_queue_release = eth_em_rx_queue_release,
.rx_queue_count = eth_em_rx_queue_count,
.rx_descriptor_done = eth_em_rx_descriptor_done,
+ .rx_descriptor_status = eth_em_rx_descriptor_status,
+ .tx_descriptor_status = eth_em_tx_descriptor_status,
.tx_queue_setup = eth_em_tx_queue_setup,
.tx_queue_release = eth_em_tx_queue_release,
.rx_queue_intr_enable = eth_em_rx_queue_intr_enable,
diff --git a/drivers/net/e1000/em_rxtx.c b/drivers/net/e1000/em_rxtx.c
index a265cb41c..31819c5bd 100644
--- a/drivers/net/e1000/em_rxtx.c
+++ b/drivers/net/e1000/em_rxtx.c
@@ -1468,6 +1468,57 @@ eth_em_rx_descriptor_done(void *rx_queue, uint16_t offset)
return !!(rxdp->status & E1000_RXD_STAT_DD);
}
+int
+eth_em_rx_descriptor_status(void *rx_queue, uint16_t offset)
+{
+ struct em_rx_queue *rxq = rx_queue;
+ volatile uint8_t *status;
+ uint32_t desc;
+
+ if (unlikely(offset >= rxq->nb_rx_desc))
+ return -EINVAL;
+
+ if (offset >= rxq->nb_rx_desc - rxq->nb_rx_hold)
+ return RTE_ETH_RX_DESC_UNAVAIL;
+
+ desc = rxq->rx_tail + offset;
+ if (desc >= rxq->nb_rx_desc)
+ desc -= rxq->nb_rx_desc;
+
+ status = &rxq->rx_ring[desc].status;
+ if (*status & E1000_RXD_STAT_DD)
+ return RTE_ETH_RX_DESC_DONE;
+
+ return RTE_ETH_RX_DESC_AVAIL;
+}
+
+int
+eth_em_tx_descriptor_status(void *tx_queue, uint16_t offset)
+{
+ struct em_tx_queue *txq = tx_queue;
+ volatile uint8_t *status;
+ uint32_t desc;
+
+ if (unlikely(offset >= txq->nb_tx_desc))
+ return -EINVAL;
+
+ desc = txq->tx_tail + offset;
+ /* go to next desc that has the RS bit */
+ desc = ((desc + txq->tx_rs_thresh - 1) / txq->tx_rs_thresh) *
+ txq->tx_rs_thresh;
+ if (desc >= txq->nb_tx_desc) {
+ desc -= txq->nb_tx_desc;
+ if (desc >= txq->nb_tx_desc)
+ desc -= txq->nb_tx_desc;
+ }
+
+ status = &txq->tx_ring[desc].upper.fields.status;
+ if (*status & E1000_TXD_STAT_DD)
+ return RTE_ETH_TX_DESC_DONE;
+
+ return RTE_ETH_TX_DESC_FULL;
+}
+
void
em_dev_clear_queues(struct rte_eth_dev *dev)
{
--
2.11.0
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH v3 5/6] net/mlx5: implement descriptor status API
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 0/6] get status of Rx and Tx descriptors Olivier Matz
` (3 preceding siblings ...)
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 4/6] net/e1000: implement descriptor status API (em) Olivier Matz
@ 2017-03-29 8:36 ` Olivier Matz
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 6/6] net/i40e: " Olivier Matz
2017-03-30 13:30 ` [dpdk-dev] [PATCH v3 0/6] get status of Rx and Tx descriptors Thomas Monjalon
6 siblings, 0 replies; 72+ messages in thread
From: Olivier Matz @ 2017-03-29 8:36 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson, venky.venkatesan, arybchenko,
qiming.yang
Since there is no "descriptor done" flag like on Intel drivers, the
approach is different on mlx5 driver.
- for Tx, we call txq_complete() to free descriptors processed by
the hw, then we check if the descriptor is between tail and head
- for Rx, we need to browse the cqes, managing compressed ones,
to get the number of used descriptors.
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
---
doc/guides/nics/features/mlx5.ini | 2 ++
drivers/net/mlx5/mlx5.c | 2 ++
drivers/net/mlx5/mlx5_rxtx.c | 76 +++++++++++++++++++++++++++++++++++++++
drivers/net/mlx5/mlx5_rxtx.h | 2 ++
4 files changed, 82 insertions(+)
diff --git a/doc/guides/nics/features/mlx5.ini b/doc/guides/nics/features/mlx5.ini
index 532c0ef3e..5b728ef06 100644
--- a/doc/guides/nics/features/mlx5.ini
+++ b/doc/guides/nics/features/mlx5.ini
@@ -31,6 +31,8 @@ L4 checksum offload = Y
Inner L3 checksum = Y
Inner L4 checksum = Y
Packet type parsing = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Stats per queue = Y
Multiprocess aware = Y
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index f034e889b..33a7f58b4 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -233,6 +233,8 @@ static const struct eth_dev_ops mlx5_dev_ops = {
.filter_ctrl = mlx5_dev_filter_ctrl,
.rx_queue_intr_enable = mlx5_rx_intr_enable,
.rx_queue_intr_disable = mlx5_rx_intr_disable,
+ .rx_descriptor_status = mlx5_rx_descriptor_status,
+ .tx_descriptor_status = mlx5_tx_descriptor_status,
};
static struct {
diff --git a/drivers/net/mlx5/mlx5_rxtx.c b/drivers/net/mlx5/mlx5_rxtx.c
index a1dd84a14..c336081d1 100644
--- a/drivers/net/mlx5/mlx5_rxtx.c
+++ b/drivers/net/mlx5/mlx5_rxtx.c
@@ -401,6 +401,82 @@ mlx5_tx_dbrec(struct txq *txq, volatile struct mlx5_wqe *wqe)
}
/**
+ * DPDK callback to check the status of a tx descriptor.
+ *
+ * @param tx_queue
+ * The tx queue.
+ * @param[in] offset
+ * The index of the descriptor in the ring.
+ *
+ * @return
+ * The status of the tx descriptor.
+ */
+int
+mlx5_tx_descriptor_status(void *tx_queue, uint16_t offset)
+{
+ struct txq *txq = tx_queue;
+ const unsigned int elts_n = 1 << txq->elts_n;
+ const unsigned int elts_cnt = elts_n - 1;
+ unsigned int used;
+
+ txq_complete(txq);
+ used = (txq->elts_head - txq->elts_tail) & elts_cnt;
+ if (offset < used)
+ return RTE_ETH_TX_DESC_FULL;
+ return RTE_ETH_TX_DESC_DONE;
+}
+
+/**
+ * DPDK callback to check the status of a rx descriptor.
+ *
+ * @param rx_queue
+ * The rx queue.
+ * @param[in] offset
+ * The index of the descriptor in the ring.
+ *
+ * @return
+ * The status of the tx descriptor.
+ */
+int
+mlx5_rx_descriptor_status(void *rx_queue, uint16_t offset)
+{
+ struct rxq *rxq = rx_queue;
+ struct rxq_zip *zip = &rxq->zip;
+ volatile struct mlx5_cqe *cqe;
+ const unsigned int cqe_n = (1 << rxq->cqe_n);
+ const unsigned int cqe_cnt = cqe_n - 1;
+ unsigned int cq_ci;
+ unsigned int used;
+
+ /* if we are processing a compressed cqe */
+ if (zip->ai) {
+ used = zip->cqe_cnt - zip->ca;
+ cq_ci = zip->cq_ci;
+ } else {
+ used = 0;
+ cq_ci = rxq->cq_ci;
+ }
+ cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
+ while (check_cqe(cqe, cqe_n, cq_ci) == 0) {
+ int8_t op_own;
+ unsigned int n;
+
+ op_own = cqe->op_own;
+ if (MLX5_CQE_FORMAT(op_own) == MLX5_COMPRESSED)
+ n = ntohl(cqe->byte_cnt);
+ else
+ n = 1;
+ cq_ci += n;
+ used += n;
+ cqe = &(*rxq->cqes)[cq_ci & cqe_cnt];
+ }
+ used = RTE_MIN(used, (1U << rxq->elts_n) - 1);
+ if (offset < used)
+ return RTE_ETH_RX_DESC_DONE;
+ return RTE_ETH_RX_DESC_AVAIL;
+}
+
+/**
* DPDK callback for TX.
*
* @param dpdk_txq
diff --git a/drivers/net/mlx5/mlx5_rxtx.h b/drivers/net/mlx5/mlx5_rxtx.h
index 4a4bd8402..b777efa12 100644
--- a/drivers/net/mlx5/mlx5_rxtx.h
+++ b/drivers/net/mlx5/mlx5_rxtx.h
@@ -339,6 +339,8 @@ uint16_t removed_tx_burst(void *, struct rte_mbuf **, uint16_t);
uint16_t removed_rx_burst(void *, struct rte_mbuf **, uint16_t);
int mlx5_rx_intr_enable(struct rte_eth_dev *dev, uint16_t rx_queue_id);
int mlx5_rx_intr_disable(struct rte_eth_dev *dev, uint16_t rx_queue_id);
+int mlx5_rx_descriptor_status(void *, uint16_t);
+int mlx5_tx_descriptor_status(void *, uint16_t);
/* mlx5_mr.c */
--
2.11.0
^ permalink raw reply [flat|nested] 72+ messages in thread
* [dpdk-dev] [PATCH v3 6/6] net/i40e: implement descriptor status API
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 0/6] get status of Rx and Tx descriptors Olivier Matz
` (4 preceding siblings ...)
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 5/6] net/mlx5: implement descriptor status API Olivier Matz
@ 2017-03-29 8:36 ` Olivier Matz
2017-03-30 13:30 ` [dpdk-dev] [PATCH v3 0/6] get status of Rx and Tx descriptors Thomas Monjalon
6 siblings, 0 replies; 72+ messages in thread
From: Olivier Matz @ 2017-03-29 8:36 UTC (permalink / raw)
To: dev, thomas.monjalon, konstantin.ananyev, wenzhuo.lu,
helin.zhang, jingjing.wu, adrien.mazarguil, nelio.laranjeiro
Cc: ferruh.yigit, bruce.richardson, venky.venkatesan, arybchenko,
qiming.yang
Signed-off-by: Olivier Matz <olivier.matz@6wind.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
---
doc/guides/nics/features/i40e.ini | 2 ++
doc/guides/nics/features/i40e_vec.ini | 2 ++
doc/guides/nics/features/i40e_vf.ini | 2 ++
doc/guides/nics/features/i40e_vf_vec.ini | 2 ++
drivers/net/i40e/i40e_ethdev.c | 2 ++
drivers/net/i40e/i40e_ethdev_vf.c | 2 ++
drivers/net/i40e/i40e_rxtx.c | 58 ++++++++++++++++++++++++++++++++
drivers/net/i40e/i40e_rxtx.h | 2 ++
8 files changed, 72 insertions(+)
diff --git a/doc/guides/nics/features/i40e.ini b/doc/guides/nics/features/i40e.ini
index 703001510..7c6c97cd0 100644
--- a/doc/guides/nics/features/i40e.ini
+++ b/doc/guides/nics/features/i40e.ini
@@ -38,6 +38,8 @@ Inner L3 checksum = Y
Inner L4 checksum = Y
Packet type parsing = Y
Timesync = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
FW version = Y
diff --git a/doc/guides/nics/features/i40e_vec.ini b/doc/guides/nics/features/i40e_vec.ini
index 5ec4088cb..372aa0154 100644
--- a/doc/guides/nics/features/i40e_vec.ini
+++ b/doc/guides/nics/features/i40e_vec.ini
@@ -29,6 +29,8 @@ Flow director = Y
Flow control = Y
Traffic mirroring = Y
Timesync = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
Multiprocess aware = Y
diff --git a/doc/guides/nics/features/i40e_vf.ini b/doc/guides/nics/features/i40e_vf.ini
index 2f82c6b98..60bdf7aa5 100644
--- a/doc/guides/nics/features/i40e_vf.ini
+++ b/doc/guides/nics/features/i40e_vf.ini
@@ -26,6 +26,8 @@ L4 checksum offload = Y
Inner L3 checksum = Y
Inner L4 checksum = Y
Packet type parsing = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
Multiprocess aware = Y
diff --git a/doc/guides/nics/features/i40e_vf_vec.ini b/doc/guides/nics/features/i40e_vf_vec.ini
index d6674f76e..5766aaf6f 100644
--- a/doc/guides/nics/features/i40e_vf_vec.ini
+++ b/doc/guides/nics/features/i40e_vf_vec.ini
@@ -18,6 +18,8 @@ RSS key update = Y
RSS reta update = Y
VLAN filter = Y
Hash filter = Y
+Rx Descriptor Status = Y
+Tx Descriptor Status = Y
Basic stats = Y
Extended stats = Y
Multiprocess aware = Y
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 20636039b..af69c9cfc 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -488,6 +488,8 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
.rx_queue_release = i40e_dev_rx_queue_release,
.rx_queue_count = i40e_dev_rx_queue_count,
.rx_descriptor_done = i40e_dev_rx_descriptor_done,
+ .rx_descriptor_status = i40e_dev_rx_descriptor_status,
+ .tx_descriptor_status = i40e_dev_tx_descriptor_status,
.tx_queue_setup = i40e_dev_tx_queue_setup,
.tx_queue_release = i40e_dev_tx_queue_release,
.dev_led_on = i40e_dev_led_on,
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 55fd34425..d3659c94b 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -217,6 +217,8 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = {
.rx_queue_intr_enable = i40evf_dev_rx_queue_intr_enable,
.rx_queue_intr_disable = i40evf_dev_rx_queue_intr_disable,
.rx_descriptor_done = i40e_dev_rx_descriptor_done,
+ .rx_descriptor_status = i40e_dev_rx_descriptor_status,
+ .tx_descriptor_status = i40e_dev_tx_descriptor_status,
.tx_queue_setup = i40e_dev_tx_queue_setup,
.tx_queue_release = i40e_dev_tx_queue_release,
.rx_queue_count = i40e_dev_rx_queue_count,
diff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c
index 02367b7f4..9b3b39ede 100644
--- a/drivers/net/i40e/i40e_rxtx.c
+++ b/drivers/net/i40e/i40e_rxtx.c
@@ -1918,6 +1918,64 @@ i40e_dev_rx_descriptor_done(void *rx_queue, uint16_t offset)
}
int
+i40e_dev_rx_descriptor_status(void *rx_queue, uint16_t offset)
+{
+ struct i40e_rx_queue *rxq = rx_queue;
+ volatile uint64_t *status;
+ uint64_t mask;
+ uint32_t desc;
+
+ if (unlikely(offset >= rxq->nb_rx_desc))
+ return -EINVAL;
+
+ if (offset >= rxq->nb_rx_desc - rxq->nb_rx_hold)
+ return RTE_ETH_RX_DESC_UNAVAIL;
+
+ desc = rxq->rx_tail + offset;
+ if (desc >= rxq->nb_rx_desc)
+ desc -= rxq->nb_rx_desc;
+
+ status = &rxq->rx_ring[desc].wb.qword1.status_error_len;
+ mask = rte_le_to_cpu_64((1ULL << I40E_RX_DESC_STATUS_DD_SHIFT)
+ << I40E_RXD_QW1_STATUS_SHIFT);
+ if (*status & mask)
+ return RTE_ETH_RX_DESC_DONE;
+
+ return RTE_ETH_RX_DESC_AVAIL;
+}
+
+int
+i40e_dev_tx_descriptor_status(void *tx_queue, uint16_t offset)
+{
+ struct i40e_tx_queue *txq = tx_queue;
+ volatile uint64_t *status;
+ uint64_t mask, expect;
+ uint32_t desc;
+
+ if (unlikely(offset >= txq->nb_tx_desc))
+ return -EINVAL;
+
+ desc = txq->tx_tail + offset;
+ /* go to next desc that has the RS bit */
+ desc = ((desc + txq->tx_rs_thresh - 1) / txq->tx_rs_thresh) *
+ txq->tx_rs_thresh;
+ if (desc >= txq->nb_tx_desc) {
+ desc -= txq->nb_tx_desc;
+ if (desc >= txq->nb_tx_desc)
+ desc -= txq->nb_tx_desc;
+ }
+
+ status = &txq->tx_ring[desc].cmd_type_offset_bsz;
+ mask = rte_le_to_cpu_64(I40E_TXD_QW1_DTYPE_MASK);
+ expect = rte_cpu_to_le_64(
+ I40E_TX_DESC_DTYPE_DESC_DONE << I40E_TXD_QW1_DTYPE_SHIFT);
+ if ((*status & mask) == expect)
+ return RTE_ETH_TX_DESC_DONE;
+
+ return RTE_ETH_TX_DESC_FULL;
+}
+
+int
i40e_dev_tx_queue_setup(struct rte_eth_dev *dev,
uint16_t queue_idx,
uint16_t nb_desc,
diff --git a/drivers/net/i40e/i40e_rxtx.h b/drivers/net/i40e/i40e_rxtx.h
index a87bdb08e..1f8e6817d 100644
--- a/drivers/net/i40e/i40e_rxtx.h
+++ b/drivers/net/i40e/i40e_rxtx.h
@@ -236,6 +236,8 @@ void i40e_rx_queue_release_mbufs(struct i40e_rx_queue *rxq);
uint32_t i40e_dev_rx_queue_count(struct rte_eth_dev *dev,
uint16_t rx_queue_id);
int i40e_dev_rx_descriptor_done(void *rx_queue, uint16_t offset);
+int i40e_dev_rx_descriptor_status(void *rx_queue, uint16_t offset);
+int i40e_dev_tx_descriptor_status(void *tx_queue, uint16_t offset);
uint16_t i40e_recv_pkts_vec(void *rx_queue, struct rte_mbuf **rx_pkts,
uint16_t nb_pkts);
--
2.11.0
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH v3 0/6] get status of Rx and Tx descriptors
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 0/6] get status of Rx and Tx descriptors Olivier Matz
` (5 preceding siblings ...)
2017-03-29 8:36 ` [dpdk-dev] [PATCH v3 6/6] net/i40e: " Olivier Matz
@ 2017-03-30 13:30 ` Thomas Monjalon
2017-04-19 15:50 ` Ferruh Yigit
6 siblings, 1 reply; 72+ messages in thread
From: Thomas Monjalon @ 2017-03-30 13:30 UTC (permalink / raw)
To: Olivier Matz, ferruh.yigit
Cc: dev, konstantin.ananyev, wenzhuo.lu, helin.zhang, jingjing.wu,
adrien.mazarguil, nelio.laranjeiro, bruce.richardson,
venky.venkatesan, arybchenko, qiming.yang
2017-03-29 10:36, Olivier Matz:
> This patchset introduces a new ethdev API:
> - rte_eth_rx_descriptor_status()
> - rte_eth_tx_descriptor_status()
>
> The Rx API is aims to replace rte_eth_rx_descriptor_done() which
> does almost the same, but does not differentiate the case of a
> descriptor used by the driver (not returned to the hw).
>
> The usage of these functions can be:
> - on Rx, anticipate that the cpu is not fast enough to process
> all incoming packets, and take dispositions to solve the
> problem (add more cpus, drop specific packets, ...)
> - on Tx, detect that the link is overloaded, and take dispositions
> to solve the problem (notify flow control, drop specific
> packets)
>
> The patchset updates ixgbe, i40e, e1000, mlx5.
> The other drivers that implement the descriptor_done() API are
> fm10k, sfc, virtio. They are not updated.
> If the new API is accepted, the descriptor_done() can be deprecated,
> and examples/l3fwd-power will be updated to.
Applied, thanks
Next steps:
- implement it in other drivers
- deprecate descriptor_done API
Ferruh, please, could you check with drivers maintainers?
Thanks
^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [dpdk-dev] [PATCH v3 0/6] get status of Rx and Tx descriptors
2017-03-30 13:30 ` [dpdk-dev] [PATCH v3 0/6] get status of Rx and Tx descriptors Thomas Monjalon
@ 2017-04-19 15:50 ` Ferruh Yigit
0 siblings, 0 replies; 72+ messages in thread
From: Ferruh Yigit @ 2017-04-19 15:50 UTC (permalink / raw)
To: Jing Chen, Andrew Rybchenko, Yuanhan Liu, Maxime Coquelin
Cc: Thomas Monjalon, Olivier Matz, dev, konstantin.ananyev,
wenzhuo.lu, helin.zhang, jingjing.wu, adrien.mazarguil,
nelio.laranjeiro, bruce.richardson, venky.venkatesan, arybchenko,
qiming.yang
On 3/30/2017 2:30 PM, Thomas Monjalon wrote:
> 2017-03-29 10:36, Olivier Matz:
>> This patchset introduces a new ethdev API:
>> - rte_eth_rx_descriptor_status()
>> - rte_eth_tx_descriptor_status()
>>
>> The Rx API is aims to replace rte_eth_rx_descriptor_done() which
>> does almost the same, but does not differentiate the case of a
>> descriptor used by the driver (not returned to the hw).
>>
>> The usage of these functions can be:
>> - on Rx, anticipate that the cpu is not fast enough to process
>> all incoming packets, and take dispositions to solve the
>> problem (add more cpus, drop specific packets, ...)
>> - on Tx, detect that the link is overloaded, and take dispositions
>> to solve the problem (notify flow control, drop specific
>> packets)
>>
>> The patchset updates ixgbe, i40e, e1000, mlx5.
>> The other drivers that implement the descriptor_done() API are
>> fm10k, sfc, virtio. They are not updated.
Reminder for following PMDs:
- fm10k
- sfc
- virtio
There are two new eth_dev_ops:
rx_descriptor_status
tx_descriptor_status
"rx_descriptor_status" replaces "rx_descriptor_done"
It is suggested to switch to new one, and implement tx_descriptor_status
Thanks,
ferruh
>> If the new API is accepted, the descriptor_done() can be deprecated,
>> and examples/l3fwd-power will be updated to.
>
> Applied, thanks
>
> Next steps:
> - implement it in other drivers
> - deprecate descriptor_done API
>
> Ferruh, please, could you check with drivers maintainers?
> Thanks
>
^ permalink raw reply [flat|nested] 72+ messages in thread