All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Morten Brørup" <mb@smartsharesystems.com>
To: "Feifei Wang" <Feifei.Wang2@arm.com>, <thomas@monjalon.net>,
	"Ferruh Yigit" <ferruh.yigit@amd.com>,
	"Andrew Rybchenko" <andrew.rybchenko@oktetlabs.ru>
Cc: <dev@dpdk.org>, <konstantin.v.ananyev@yandex.ru>,
	"nd" <nd@arm.com>,
	"Honnappa Nagarahalli" <Honnappa.Nagarahalli@arm.com>,
	"Ruifeng Wang" <Ruifeng.Wang@arm.com>, "nd" <nd@arm.com>
Subject: RE: [PATCH v5 1/3] ethdev: add API for buffer recycle mode
Date: Thu, 30 Mar 2023 17:15:22 +0200	[thread overview]
Message-ID: <98CBD80474FA8B44BF855DF32C47DC35D8782B@smartserver.smartshare.dk> (raw)
In-Reply-To: <AS8PR08MB77180DA8C28C829A8152A413C88E9@AS8PR08MB7718.eurprd08.prod.outlook.com>

> From: Feifei Wang [mailto:Feifei.Wang2@arm.com]
> Sent: Thursday, 30 March 2023 11.31
> 
> > From: Morten Brørup <mb@smartsharesystems.com>
> > Sent: Thursday, March 30, 2023 3:19 PM
> >
> > > From: Feifei Wang [mailto:feifei.wang2@arm.com]
> > > Sent: Thursday, 30 March 2023 08.30
> > >
> >
> > [...]
> >
> > > +/**
> > > + * @internal
> > > + * Rx routine for rte_eth_dev_buf_recycle().
> > > + * Refill Rx descriptors in buffer recycle mode.
> > > + *
> > > + * @note
> > > + * This API can only be called by rte_eth_dev_buf_recycle().
> > > + * Before calling this API, rte_eth_tx_buf_stash() should be
> > > + * called to stash Tx used buffers into Rx buffer ring.
> > > + *
> > > + * When this functionality is not implemented in the driver, the
> > > +return
> > > + * buffer number is 0.
> > > + *
> > > + * @param port_id
> > > + *   The port identifier of the Ethernet device.
> > > + * @param queue_id
> > > + *   The index of the receive queue.
> > > + *   The value must be in the range [0, nb_rx_queue - 1] previously
> > supplied
> > > + *   to rte_eth_dev_configure().
> > > + *@param nb
> > > + *   The number of Rx descriptors to be refilled.
> > > + * @return
> > > + *   The number Rx descriptors correct to be refilled.
> > > + *   - ENODEV: bad port or queue (only if compiled with debug).
> >
> > If you want errors reported by the return value, the function return type
> > cannot be uint16_t.
> Agree. Actually, in the code path, if errors happen, the function will return
> 0.
> For this description line, I refer to 'rte_eth_tx_prepare' notes. Maybe we
> should delete
> this line.
> 
> >
> > > + */
> > > +static inline uint16_t rte_eth_rx_descriptors_refill(uint16_t port_id,
> > > +		uint16_t queue_id, uint16_t nb)
> > > +{
> > > +	struct rte_eth_fp_ops *p;
> > > +	void *qd;
> > > +
> > > +#ifdef RTE_ETHDEV_DEBUG_RX
> > > +	if (port_id >= RTE_MAX_ETHPORTS ||
> > > +			queue_id >= RTE_MAX_QUEUES_PER_PORT) {
> > > +		RTE_ETHDEV_LOG(ERR,
> > > +			"Invalid port_id=%u or queue_id=%u\n",
> > > +			port_id, queue_id);
> > > +		rte_errno = ENODEV;
> > > +		return 0;
> >
> > If p->rx_descriptors_refill() is likely to return 0, this function should
> not use 0
> > as return value to indicate errors.
> However, refer to dpdk code style in ethdev, most of API write like this.
> For example, 'rte_eth_rx/tx_burst', 'rte_eth_tx_prep'.
> 
> I'm also confused what's return type for this due to I want
> to indicate errors and show the processed buffer number.

OK. Thanks for the references.

Looking at rte_eth_rx/tx_burst(), you could follow the same conventions here, i.e.:
- Use uint16_t as return type.
- Return 0 on error.
- Do not set rte_errno.
- Remove the "ENODEV" line from the @return description.
- Use RTE_ETHDEV_LOG(ERR,...) as the only method to indicate errors.

I now see that you follow the convention of rte_eth_tx_prepare(). This is also perfectly fine; then you just need to update the description of @return to mention that the error value is set in rte_errno if a value less than 'nb' is returned.

> 
> >
> > > +	}
> > > +#endif
> > > +
> > > +	p = &rte_eth_fp_ops[port_id];
> > > +	qd = p->rxq.data[queue_id];
> > > +
> > > +#ifdef RTE_ETHDEV_DEBUG_RX
> > > +	if (!rte_eth_dev_is_valid_port(port_id)) {
> > > +		RTE_ETHDEV_LOG(ERR, "Invalid Rx port_id=%u\n", port_id);
> > > +		rte_errno = ENODEV;
> > > +		return 0;
> > > +
> > > +	if (qd == NULL) {
> > > +		RTE_ETHDEV_LOG(ERR, "Invalid Rx queue_id=%u for
> > port_id=%u\n",
> > > +			queue_id, port_id);
> > > +		rte_errno = ENODEV;
> > > +		return 0;
> > > +	}
> > > +#endif
> > > +
> > > +	if (p->rx_descriptors_refill == NULL)
> > > +		return 0;
> > > +
> > > +	return p->rx_descriptors_refill(qd, nb); }

When does p->rx_descriptors_refill() return anything else than 'nb'?

If p->rx_descriptors_refill() always succeeds (and thus always returns 'nb'), you could make its return type void. And thus, you could also make the return type of rte_eth_rx_descriptors_refill() void.

> > > +
> > >  /**@{@name Rx hardware descriptor states
> > >   * @see rte_eth_rx_descriptor_status
> > >   */
> > > @@ -6483,6 +6597,122 @@ rte_eth_tx_buffer(uint16_t port_id, uint16_t
> > queue_id,
> > >  	return rte_eth_tx_buffer_flush(port_id, queue_id, buffer);  }
> > >
> > > +/**
> > > + * @internal
> > > + * Tx routine for rte_eth_dev_buf_recycle().
> > > + * Stash Tx used buffers into Rx buffer ring in buffer recycle mode.
> > > + *
> > > + * @note
> > > + * This API can only be called by rte_eth_dev_buf_recycle().
> > > + * After calling this API, rte_eth_rx_descriptors_refill() should be
> > > + * called to refill Rx ring descriptors.
> > > + *
> > > + * When this functionality is not implemented in the driver, the
> > > +return
> > > + * buffer number is 0.
> > > + *
> > > + * @param port_id
> > > + *   The port identifier of the Ethernet device.
> > > + * @param queue_id
> > > + *   The index of the transmit queue.
> > > + *   The value must be in the range [0, nb_tx_queue - 1] previously
> > supplied
> > > + *   to rte_eth_dev_configure().
> > > + * @param rxq_buf_recycle_info
> > > + *   A pointer to a structure of Rx queue buffer ring information in
> buffer
> > > + *   recycle mode.
> > > + *
> > > + * @return
> > > + *   The number buffers correct to be filled in the Rx buffer ring.
> > > + *   - ENODEV: bad port or queue (only if compiled with debug).
> >
> > If you want errors reported by the return value, the function return type
> > cannot be uint16_t.

I now see that you follow the convention of rte_eth_tx_prepare() here too.

This is perfectly fine; then you just need to update the description of @return to mention that the error value is set in rte_errno if a value less than 'nb' is returned.

> >
> > > + */
> > > +static inline uint16_t rte_eth_tx_buf_stash(uint16_t port_id,
> > > +uint16_t
> > > queue_id,
> > > +		struct rte_eth_rxq_buf_recycle_info *rxq_buf_recycle_info)
> > {
> > > +	struct rte_eth_fp_ops *p;
> > > +	void *qd;
> > > +
> > > +#ifdef RTE_ETHDEV_DEBUG_TX
> > > +	if (port_id >= RTE_MAX_ETHPORTS ||
> > > +			queue_id >= RTE_MAX_QUEUES_PER_PORT) {
> > > +		RTE_ETHDEV_LOG(ERR,
> > > +			"Invalid port_id=%u or queue_id=%u\n",
> > > +			port_id, queue_id);
> > > +		rte_errno = ENODEV;
> > > +		return 0;
> >
> > If p->tx_buf_stash() is likely to return 0, this function should not use 0
> as
> > return value to indicate errors.

I now see that you follow the convention of rte_eth_tx_prepare() here too. Then please ignore my comment about using 0 as return value on errors for this function.

> >
> > > +	}
> > > +#endif
> > > +
> > > +	p = &rte_eth_fp_ops[port_id];
> > > +	qd = p->txq.data[queue_id];
> > > +
> > > +#ifdef RTE_ETHDEV_DEBUG_TX
> > > +	if (!rte_eth_dev_is_valid_port(port_id)) {
> > > +		RTE_ETHDEV_LOG(ERR, "Invalid Tx port_id=%u\n", port_id);
> > > +		rte_errno = ENODEV;
> > > +		return 0;
> > > +
> > > +	if (qd == NULL) {
> > > +		RTE_ETHDEV_LOG(ERR, "Invalid Tx queue_id=%u for
> > port_id=%u\n",
> > > +			queue_id, port_id);
> > > +		rte_erno = ENODEV;
> > > +		return 0;
> > > +	}
> > > +#endif
> > > +
> > > +	if (p->tx_buf_stash == NULL)
> > > +		return 0;
> > > +
> > > +	return p->tx_buf_stash(qd, rxq_buf_recycle_info); }
> > > +
> > > +/**
> > > + * @warning
> > > + * @b EXPERIMENTAL: this API may change, or be removed, without prior
> > > +notice
> > > + *
> > > + * Buffer recycle mode can let Tx queue directly put used buffers
> > > +into Rx
> > > buffer
> > > + * ring. This avoids freeing buffers into mempool and allocating
> > > + buffers from
> > > + * mempool.
> >
> > This function description generally describes the buffer recycle mode.
> >
> > Please update it to describe what this specific function does.
> Ack.
> >
> > > + *
> > > + * @param rx_port_id
> > > + *   Port identifying the receive side.
> > > + * @param rx_queue_id
> > > + *   The index of the receive queue identifying the receive side.
> > > + *   The value must be in the range [0, nb_rx_queue - 1] previously
> > supplied
> > > + *   to rte_eth_dev_configure().
> > > + * @param tx_port_id
> > > + *   Port identifying the transmit side.
> > > + * @param tx_queue_id
> > > + *   The index of the transmit queue identifying the transmit side.
> > > + *   The value must be in the range [0, nb_tx_queue - 1] previously
> > supplied
> > > + *   to rte_eth_dev_configure().
> > > + * @param rxq_recycle_info
> > > + *   A pointer to a structure of type *rte_eth_txq_rearm_data* to be
> filled.
> > > + * @return
> > > + *   - (0) on success or no recycling buffer.
> >
> > Why not return the return value of rte_eth_rx_descriptors_refill() instead
> of
> > 0 on success? (This is a question, not a suggestion.)
> >
> > Or, if rxq_buf_recycle_info must be valid, the function return type could be
> > void instead of int.
> >
> In some time, users may forget to allocate the room for ' rxq_buf_recycle_info
> '
> and call 'rte_rxq_buf_recycle_info_get' API. Thus, I think we need to check
> with this.

If the user forgets to allocate the rxq_buf_recycle_info, it is a serious bug in the user's application.

We don't need to handle such bugs at runtime.

> 
> Furthermore, the return value of this API should return success or not.

If rxq_buf_recycle_info is not NULL, this function will always succeed. So there is no need for a return value.

If you want this function to return something, it could return nb_buf, so the application can it use for telemetry purposes or similar.

> 
> > > + *   - (-EINVAL) rxq_recycle_info is NULL.
> > > + */
> > > +__rte_experimental
> > > +static inline int
> > > +rte_eth_dev_buf_recycle(uint16_t rx_port_id, uint16_t rx_queue_id,
> > > +		uint16_t tx_port_id, uint16_t tx_queue_id,
> > > +		struct rte_eth_rxq_buf_recycle_info *rxq_buf_recycle_info)
> > {
> > > +	/* The number of recycling buffers. */
> > > +	uint16_t nb_buf;
> > > +
> > > +	if (!rxq_buf_recycle_info)
> > > +		return -EINVAL;
> >
> > This is a fast path function. In which situation is this function called
> with
> > rxq_buf_recycle_info == NULL?
> >
> > If this function can genuinely be called with rxq_buf_recycle_info == NULL,
> > you should test for (rxq_buf_recycle_info == NULL), not (!
> > rxq_buf_recycle_info). Otherwise, I think
> > RTE_ASSERT(rxq_buf_recycle_info != NULL) is more appropriate.
> Agree. We should use ' RTE_ASSERT(rxq_buf_recycle_info != NULL)'.
> >
> > > +
> > > +	/* Stash Tx used buffers into Rx buffer ring */
> > > +	nb_buf = rte_eth_tx_buf_stash(tx_port_id, tx_queue_id,
> > > +				rxq_buf_recycle_info);
> > > +	/* If there are recycling buffers, refill Rx queue descriptors. */
> > > +	if (nb_buf)
> > > +		rte_eth_rx_descriptors_refill(rx_port_id, rx_queue_id,
> > > +					nb_buf);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > >  /**
> > >   * @warning
> > >   * @b EXPERIMENTAL: this API may change without prior notice diff
> > > --git a/lib/ethdev/rte_ethdev_core.h b/lib/ethdev/rte_ethdev_core.h
> > > index dcf8adab92..a138fd4dbc 100644
> > > --- a/lib/ethdev/rte_ethdev_core.h
> > > +++ b/lib/ethdev/rte_ethdev_core.h
> > > @@ -56,6 +56,13 @@ typedef int (*eth_rx_descriptor_status_t)(void
> > > *rxq, uint16_t offset);
> > >  /** @internal Check the status of a Tx descriptor */  typedef int
> > > (*eth_tx_descriptor_status_t)(void *txq, uint16_t offset);
> > >
> > > +/** @internal Stash Tx used buffers into RX ring in buffer recycle
> > > +mode */ typedef uint16_t (*eth_tx_buf_stash_t)(void *txq,
> > > +		struct rte_eth_rxq_buf_recycle_info *rxq_buf_recycle_info);
> > > +
> > > +/** @internal Refill Rx descriptors in buffer recycle mode */ typedef
> > > +uint16_t (*eth_rx_descriptors_refill_t)(void *rxq, uint16_t nb);
> >
> > Please add proper function descriptions for the two callbacks above.
> Ack.
> >
> > > +
> > >  /**
> > >   * @internal
> > >   * Structure used to hold opaque pointers to internal ethdev Rx/Tx @@
> > > -90,9 +97,11 @@ struct rte_eth_fp_ops {
> > >  	eth_rx_queue_count_t rx_queue_count;
> > >  	/** Check the status of a Rx descriptor. */
> > >  	eth_rx_descriptor_status_t rx_descriptor_status;
> > > +	/** Refill Rx descriptors in buffer recycle mode */
> > > +	eth_rx_descriptors_refill_t rx_descriptors_refill;
> > >  	/** Rx queues data. */
> > >  	struct rte_ethdev_qdata rxq;
> > > -	uintptr_t reserved1[3];
> > > +	uintptr_t reserved1[4];
> >
> > You added a function pointer above, so to keep the structure alignment, you
> > must remove one here, not add one:
> >
> > -	uintptr_t reserved1[3];
> > +	uintptr_t reserved1[2];
> >
> Ack.
> > >  	/**@}*/
> > >
> > >  	/**@{*/
> > > @@ -106,9 +115,11 @@ struct rte_eth_fp_ops {
> > >  	eth_tx_prep_t tx_pkt_prepare;
> > >  	/** Check the status of a Tx descriptor. */
> > >  	eth_tx_descriptor_status_t tx_descriptor_status;
> > > +	/** Stash Tx used buffers into RX ring in buffer recycle mode */
> > > +	eth_tx_buf_stash_t tx_buf_stash;
> > >  	/** Tx queues data. */
> > >  	struct rte_ethdev_qdata txq;
> > > -	uintptr_t reserved2[3];
> > > +	uintptr_t reserved2[4];
> >
> > You added a function pointer above, so to keep the structure alignment, you
> > must remove one here, not add one:
> >
> > -	uintptr_t reserved1[3];
> > +	uintptr_t reserved1[2];
> >
> Ack.
> > >  	/**@}*/
> > >
> > >  } __rte_cache_aligned;


  reply	other threads:[~2023-03-30 15:15 UTC|newest]

Thread overview: 67+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-24 16:46 [RFC PATCH v1 0/4] Direct re-arming of buffers on receive side Feifei Wang
2021-12-24 16:46 ` [RFC PATCH v1 1/4] net/i40e: enable direct re-arm mode Feifei Wang
2021-12-24 16:46 ` [RFC PATCH v1 2/4] ethdev: add API for " Feifei Wang
2021-12-24 19:38   ` Stephen Hemminger
2021-12-26  9:49     ` 回复: " Feifei Wang
2021-12-26 10:31       ` Morten Brørup
2021-12-24 16:46 ` [RFC PATCH v1 3/4] net/i40e: add direct re-arm mode internal API Feifei Wang
2021-12-24 16:46 ` [RFC PATCH v1 4/4] examples/l3fwd: give an example for direct rearm mode Feifei Wang
2021-12-26 10:25 ` [RFC PATCH v1 0/4] Direct re-arming of buffers on receive side Morten Brørup
2021-12-28  6:55   ` 回复: " Feifei Wang
2022-01-18 15:51     ` Ferruh Yigit
2022-01-18 16:53       ` Thomas Monjalon
2022-01-18 17:27         ` Morten Brørup
2022-01-27  5:24           ` Honnappa Nagarahalli
2022-01-27 16:45             ` Ananyev, Konstantin
2022-02-02 19:46               ` Honnappa Nagarahalli
2022-01-27  5:16         ` Honnappa Nagarahalli
2023-02-28  6:43       ` 回复: " Feifei Wang
2023-02-28  6:52         ` Feifei Wang
2022-01-27  4:06   ` Honnappa Nagarahalli
2022-01-27 17:13     ` Morten Brørup
2022-01-28 11:29     ` Morten Brørup
2023-03-23 10:43 ` [PATCH v4 0/3] Recycle buffers from Tx to Rx Feifei Wang
2023-03-23 10:43   ` [PATCH v4 1/3] ethdev: add API for buffer recycle mode Feifei Wang
2023-03-23 11:41     ` Morten Brørup
2023-03-29  2:16       ` Feifei Wang
2023-03-23 10:43   ` [PATCH v4 2/3] net/i40e: implement recycle buffer mode Feifei Wang
2023-03-23 10:43   ` [PATCH v4 3/3] net/ixgbe: " Feifei Wang
2023-03-30  6:29 ` [PATCH v5 0/3] Recycle buffers from Tx to Rx Feifei Wang
2023-03-30  6:29   ` [PATCH v5 1/3] ethdev: add API for buffer recycle mode Feifei Wang
2023-03-30  7:19     ` Morten Brørup
2023-03-30  9:31       ` Feifei Wang
2023-03-30 15:15         ` Morten Brørup [this message]
2023-03-30 15:58         ` Morten Brørup
2023-04-26  6:59           ` Feifei Wang
2023-04-19 14:46     ` Ferruh Yigit
2023-04-26  7:29       ` Feifei Wang
2023-03-30  6:29   ` [PATCH v5 2/3] net/i40e: implement recycle buffer mode Feifei Wang
2023-03-30  6:29   ` [PATCH v5 3/3] net/ixgbe: " Feifei Wang
2023-04-19 14:46     ` Ferruh Yigit
2023-04-26  7:36       ` Feifei Wang
2023-03-30 15:04   ` [PATCH v5 0/3] Recycle buffers from Tx to Rx Stephen Hemminger
2023-04-03  2:48     ` Feifei Wang
2023-04-19 14:56   ` Ferruh Yigit
2023-04-25  7:57     ` Feifei Wang
2023-05-25  9:45 ` [PATCH v6 0/4] Recycle mbufs from Tx queue to Rx queue Feifei Wang
2023-05-25  9:45   ` [PATCH v6 1/4] ethdev: add API for mbufs recycle mode Feifei Wang
2023-05-25 15:08     ` Morten Brørup
2023-05-31  6:10       ` Feifei Wang
2023-06-05 12:53     ` Константин Ананьев
2023-06-06  2:55       ` Feifei Wang
2023-06-06  7:10         ` Konstantin Ananyev
2023-06-06  7:31           ` Feifei Wang
2023-06-06  8:34             ` Konstantin Ananyev
2023-06-07  0:00               ` Ferruh Yigit
2023-06-12  3:25                 ` Feifei Wang
2023-05-25  9:45   ` [PATCH v6 2/4] net/i40e: implement " Feifei Wang
2023-06-05 13:02     ` Константин Ананьев
2023-06-06  3:16       ` Feifei Wang
2023-06-06  7:18         ` Konstantin Ananyev
2023-06-06  7:58           ` Feifei Wang
2023-06-06  8:27             ` Konstantin Ananyev
2023-06-12  3:05               ` Feifei Wang
2023-05-25  9:45   ` [PATCH v6 3/4] net/ixgbe: " Feifei Wang
2023-05-25  9:45   ` [PATCH v6 4/4] app/testpmd: add recycle mbufs engine Feifei Wang
2023-06-05 13:08     ` Константин Ананьев
2023-06-06  6:32       ` Feifei Wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=98CBD80474FA8B44BF855DF32C47DC35D8782B@smartserver.smartshare.dk \
    --to=mb@smartsharesystems.com \
    --cc=Feifei.Wang2@arm.com \
    --cc=Honnappa.Nagarahalli@arm.com \
    --cc=Ruifeng.Wang@arm.com \
    --cc=andrew.rybchenko@oktetlabs.ru \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@amd.com \
    --cc=konstantin.v.ananyev@yandex.ru \
    --cc=nd@arm.com \
    --cc=thomas@monjalon.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.