From: Konstantin Ananyev <konstantin.ananyev@huawei.com>
To: "Feifei Wang" <Feifei.Wang2@arm.com>,
"Константин Ананьев" <konstantin.v.ananyev@yandex.ru>,
"Yuying Zhang" <yuying.zhang@intel.com>,
"Beilei Xing" <beilei.xing@intel.com>
Cc: "dev@dpdk.org" <dev@dpdk.org>, nd <nd@arm.com>,
Honnappa Nagarahalli <Honnappa.Nagarahalli@arm.com>,
Ruifeng Wang <Ruifeng.Wang@arm.com>, nd <nd@arm.com>,
nd <nd@arm.com>
Subject: RE: [PATCH v6 2/4] net/i40e: implement mbufs recycle mode
Date: Tue, 6 Jun 2023 08:27:02 +0000 [thread overview]
Message-ID: <83b9487385e04212847f7deea32efd82@huawei.com> (raw)
In-Reply-To: <AS8PR08MB7718A351559025BA7B9008A4C852A@AS8PR08MB7718.eurprd08.prod.outlook.com>
> > > Define specific function implementation for i40e driver.
> > > Currently, mbufs recycle mode can support 128bit vector path and avx2
> > > path. And can be enabled both in fast free and no fast free mode.
> > >
> > > Suggested-by: Honnappa Nagarahalli
> > > <mailto:honnappa.nagarahalli@arm.com>
> > > Signed-off-by: Feifei Wang <mailto:feifei.wang2@arm.com>
> > > Reviewed-by: Ruifeng Wang <mailto:ruifeng.wang@arm.com>
> > > Reviewed-by: Honnappa Nagarahalli
> > > <mailto:honnappa.nagarahalli@arm.com>
> > > ---
> > > drivers/net/i40e/i40e_ethdev.c | 1 +
> > > drivers/net/i40e/i40e_ethdev.h | 2 +
> > > .../net/i40e/i40e_recycle_mbufs_vec_common.c | 140
> > ++++++++++++++++++
> > > drivers/net/i40e/i40e_rxtx.c | 32 ++++ drivers/net/i40e/i40e_rxtx.h |
> > > 4 + drivers/net/i40e/meson.build | 2 +
> > > 6 files changed, 181 insertions(+)
> > > create mode 100644 drivers/net/i40e/i40e_recycle_mbufs_vec_common.c
> > >
> > > diff --git a/drivers/net/i40e/i40e_ethdev.c
> > > b/drivers/net/i40e/i40e_ethdev.c index f9d8f9791f..d4eecd16cf 100644
> > > --- a/drivers/net/i40e/i40e_ethdev.c
> > > +++ b/drivers/net/i40e/i40e_ethdev.c
> > > @@ -496,6 +496,7 @@ static const struct eth_dev_ops i40e_eth_dev_ops =
> > {
> > > .flow_ops_get = i40e_dev_flow_ops_get,
> > > .rxq_info_get = i40e_rxq_info_get,
> > > .txq_info_get = i40e_txq_info_get,
> > > + .recycle_rxq_info_get = i40e_recycle_rxq_info_get,
> > > .rx_burst_mode_get = i40e_rx_burst_mode_get,
> > > .tx_burst_mode_get = i40e_tx_burst_mode_get,
> > > .timesync_enable = i40e_timesync_enable, diff --git
> > > a/drivers/net/i40e/i40e_ethdev.h b/drivers/net/i40e/i40e_ethdev.h
> > > index 9b806d130e..b5b2d6cf2b 100644
> > > --- a/drivers/net/i40e/i40e_ethdev.h
> > > +++ b/drivers/net/i40e/i40e_ethdev.h
> > > @@ -1355,6 +1355,8 @@ void i40e_rxq_info_get(struct rte_eth_dev *dev,
> > uint16_t queue_id,
> > > struct rte_eth_rxq_info *qinfo); void
> > > i40e_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
> > > struct rte_eth_txq_info *qinfo);
> > > +void i40e_recycle_rxq_info_get(struct rte_eth_dev *dev, uint16_t
> > > +queue_id, struct rte_eth_recycle_rxq_info *recycle_rxq_info);
> > > int i40e_rx_burst_mode_get(struct rte_eth_dev *dev, uint16_t queue_id,
> > > struct rte_eth_burst_mode *mode); int
> > > i40e_tx_burst_mode_get(struct rte_eth_dev *dev, uint16_t queue_id,
> > > diff --git a/drivers/net/i40e/i40e_recycle_mbufs_vec_common.c
> > > b/drivers/net/i40e/i40e_recycle_mbufs_vec_common.c
> > > new file mode 100644
> > > index 0000000000..08d708fd7d
> > > --- /dev/null
> > > +++ b/drivers/net/i40e/i40e_recycle_mbufs_vec_common.c
> > > @@ -0,0 +1,140 @@
> > > +/* SPDX-License-Identifier: BSD-3-Clause
> > > + * Copyright (c) 2023 Arm Limited.
> > > + */
> > > +
> > > +#include <stdint.h>
> > > +#include <ethdev_driver.h>
> > > +
> > > +#include "base/i40e_prototype.h"
> > > +#include "base/i40e_type.h"
> > > +#include "i40e_ethdev.h"
> > > +#include "i40e_rxtx.h"
> > > +
> > > +#pragma GCC diagnostic ignored "-Wcast-qual"
> > > +
> > > +void
> > > +i40e_recycle_rx_descriptors_refill_vec(void *rx_queue, uint16_t
> > > +nb_mbufs) { struct i40e_rx_queue *rxq = rx_queue; struct
> > > +i40e_rx_entry *rxep; volatile union i40e_rx_desc *rxdp; uint16_t
> > > +rx_id; uint64_t paddr; uint64_t dma_addr; uint16_t i;
> > > +
> > > + rxdp = rxq->rx_ring + rxq->rxrearm_start; rxep =
> > > + &rxq->sw_ring[rxq->rxrearm_start];
> > > +
> > > + for (i = 0; i < nb_mbufs; i++) {
> > > + /* Initialize rxdp descs. */
> > > + paddr = (rxep[i].mbuf)->buf_iova + RTE_PKTMBUF_HEADROOM;
> > dma_addr =
> > > + rte_cpu_to_le_64(paddr);
> > > + /* flush desc with pa dma_addr */
> > > + rxdp[i].read.hdr_addr = 0;
> > > + rxdp[i].read.pkt_addr = dma_addr;
> > > + }
> > > +
> > > + /* Update the descriptor initializer index */
> > > + rxq->rxrearm_start += nb_mbufs;
> > > + rx_id = rxq->rxrearm_start - 1;
> > > +
> > > + if (unlikely(rxq->rxrearm_start >= rxq->nb_rx_desc)) {
> > > + rxq->rxrearm_start = 0;
> > > + rx_id = rxq->nb_rx_desc - 1;
> > > + }
> > > +
> > > + rxq->rxrearm_nb -= nb_mbufs;
> > > +
> > > + rte_io_wmb();
> > > + /* Update the tail pointer on the NIC */
> > > +I40E_PCI_REG_WRITE_RELAXED(rxq->qrx_tail, rx_id); }
> > > +
> > > +uint16_t
> > > +i40e_recycle_tx_mbufs_reuse_vec(void *tx_queue, struct
> > > +rte_eth_recycle_rxq_info *recycle_rxq_info) { struct i40e_tx_queue
> > > +*txq = tx_queue; struct i40e_tx_entry *txep; struct rte_mbuf
> > > +**rxep; struct rte_mbuf *m[RTE_I40E_TX_MAX_FREE_BUF_SZ]; int i, j,
> > > +n; uint16_t avail = 0; uint16_t mbuf_ring_size =
> > > +recycle_rxq_info->mbuf_ring_size;
> > > + uint16_t mask = recycle_rxq_info->mbuf_ring_size - 1; uint16_t
> > > +refill_requirement = recycle_rxq_info->refill_requirement;
> > > + uint16_t refill_head = *recycle_rxq_info->refill_head; uint16_t
> > > +receive_tail = *recycle_rxq_info->receive_tail;
> > > +
> > > + /* Get available recycling Rx buffers. */ avail = (mbuf_ring_size -
> > > + (refill_head - receive_tail)) & mask;
> > > +
> > > + /* Check Tx free thresh and Rx available space. */ if
> > > + (txq->nb_tx_free > txq->tx_free_thresh || avail <=
> > > + txq->tx_rs_thresh) return 0;
> > > +
> > > + /* check DD bits on threshold descriptor */ if
> > > + ((txq->tx_ring[txq->tx_next_dd].cmd_type_offset_bsz &
> > > + rte_cpu_to_le_64(I40E_TXD_QW1_DTYPE_MASK)) !=
> > > + rte_cpu_to_le_64(I40E_TX_DESC_DTYPE_DESC_DONE))
> > > + return 0;
> > > +
> > > + n = txq->tx_rs_thresh;
> > > +
> > > + /* Mbufs recycle mode can only support no ring buffer wrapping around.
> > > + * Two case for this:
> > > + *
> > > + * case 1: The refill head of Rx buffer ring needs to be aligned with
> > > + * mbuf ring size. In this case, the number of Tx freeing buffers
> > > + * should be equal to refill_requirement.
> > > + *
> > > + * case 2: The refill head of Rx ring buffer does not need to be
> > > + aligned
> > > + * with mbuf ring size. In this case, the update of refill head can
> > > + not
> > > + * exceed the Rx mbuf ring size.
> > > + */
> > > + if (refill_requirement != n ||
> > > + (!refill_requirement && (refill_head + n > mbuf_ring_size))) return
> > > + 0;
> > > +
> > > + /* First buffer to free from S/W ring is at index
> > > + * tx_next_dd - (tx_rs_thresh-1).
> > > + */
> > > + txep = &txq->sw_ring[txq->tx_next_dd - (n - 1)]; rxep =
> > > + recycle_rxq_info->mbuf_ring; rxep += refill_head;
> > > +
> > > + if (txq->offloads & RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE) {
> > > + /* Directly put mbufs from Tx to Rx. */ for (i = 0; i < n; i++,
> > > + rxep++, txep++) *rxep = txep[0].mbuf; } else { for (i = 0, j = 0; i
> > > + < n; i++) {
> > > + /* Avoid txq contains buffers from expected mempool. */ if
> > > + (unlikely(recycle_rxq_info->mp != txep[i].mbuf->pool)) return 0;
> > > I don't think that it is possible to simply return 0 here:
> > > we might already have some mbufs inside rxep[], so we probably need to
> > > return that number (j).
> > >
> > > No, here is just pre-free, not actually put mbufs into rxeq.
> >
> > I understand that.
> > What I am saying: after you call pktmbuf_prefree_seg(mbuf), you can’t keep it
> > in the txq anymore.
> > You have either to put it into rxep[], or back into mempool.
> > Also txq state (nb_tx_free, etc.) need to be updated.
> >
> > > After run out of the loop, we call rte_memcpy to actually copy mbufs
> > > into rxep.
> > > +
> > > + m[j] = rte_pktmbuf_prefree_seg(txep[i].mbuf);
> > > +
> > > + /* In case 1, each of Tx buffers should be the
> > > + * last reference.
> > > + */
> > > + if (unlikely(m[j] == NULL && refill_requirement)) return 0;
> > >
> > > same here, we can't simply return 0, it will introduce mbuf leakage.
> > > + /* In case 2, the number of valid Tx free
> > > + * buffers should be recorded.
> > > + */
> > > + j++;
> > > + }
> > > + rte_memcpy(rxep, m, sizeof(void *) * j);
> > > Wonder why do you need intermediate buffer for released mbufs?
> > > Why can't just:
> > > ...
> > > m = rte_pktmbuf_prefree_seg(txep[i].mbuf);
> > > ...
> > > rxep[j++] = m;
> > > ?
> > > Might save you few extra cycles.
> > > Sometimes ‘rte_pktmbuf_prefree_seg’ can return NULL due to
> > > mbuf->refcnt > 1. So we should firstly ensure all ‘m’ are valid and
> > > then copy them into rxep.
> >
> > I understand that, but you can check is it NULL or not.
> For i40e rxq, it must rearm ' RTE_I40E_RXQ_REARM_THRESH ' pkts once a time
> based on its ring wrapping mechanism.
>
> For i40e txq, it must free ' txq->tx_rs_thresh' pkts once a time.
>
> So we need firstly ensure all tx free mbufs are valid, and then copy these into rxq.
> If not enough valid mbufs, it will break rxq's ring wrapping mechanism.
I think you can still copy mbufs into rxep[], if there are not enough mbufs,
you can still return 0 (or whatever is a proper value here), and that would mean
all these new rxep[] entries will be considered as invalid.
Anyway that's just a suggestion to avoid extra copy.
>
> >
> > > + }
> > > +
> > > + /* Update counters for Tx. */
> > > + txq->nb_tx_free = (uint16_t)(txq->nb_tx_free + txq->tx_rs_thresh);
> > > + txq->tx_next_dd = (uint16_t)(txq->tx_next_dd + txq->tx_rs_thresh);
> > > + if (txq->tx_next_dd >= txq->nb_tx_desc)
> > > + txq->tx_next_dd = (uint16_t)(txq->tx_rs_thresh - 1);
> > > +
> > > + return n;
> > > +}
next prev parent reply other threads:[~2023-06-06 8:27 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
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 [this message]
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=83b9487385e04212847f7deea32efd82@huawei.com \
--to=konstantin.ananyev@huawei.com \
--cc=Feifei.Wang2@arm.com \
--cc=Honnappa.Nagarahalli@arm.com \
--cc=Ruifeng.Wang@arm.com \
--cc=beilei.xing@intel.com \
--cc=dev@dpdk.org \
--cc=konstantin.v.ananyev@yandex.ru \
--cc=nd@arm.com \
--cc=yuying.zhang@intel.com \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).