The linearization of the mbuf isn't common practice for the PMD, as it
can expose it's capabilities to the upper layer using
rte_eth_dev_info_get().
Moreover, the rte_eth_tx_prepare() function should also verify if the
number of segments inside the mbuf isn't too high.
Because of those 2 circumstances, it may be safer to avoid modifying
mbuf on PMD's Tx side and remove linearization at all. Instead, add
verification of the number of segments to the eth_ena_prep_pkts().
Signed-off-by: Michal Krawczyk <mk@semihalf.com>
Reviewed-by: Artur Rojek <ar@semihalf.com>
Reviewed-by: Dawid Gorecki <dgr@semihalf.com>
Reviewed-by: Igor Chauskin <igorch@amazon.com>
Reviewed-by: Shai Brandes <shaibran@amazon.com>
---
drivers/net/ena/ena_ethdev.c | 74 +++++++++---------------------------
drivers/net/ena/ena_ethdev.h | 2 -
2 files changed, 19 insertions(+), 57 deletions(-)
@@ -93,8 +93,6 @@ static const struct ena_stats ena_stats_tx_strings[] = {
ENA_STAT_TX_ENTRY(cnt),
ENA_STAT_TX_ENTRY(bytes),
ENA_STAT_TX_ENTRY(prepare_ctx_err),
- ENA_STAT_TX_ENTRY(linearize),
- ENA_STAT_TX_ENTRY(linearize_failed),
ENA_STAT_TX_ENTRY(tx_poll),
ENA_STAT_TX_ENTRY(doorbells),
ENA_STAT_TX_ENTRY(bad_req_id),
@@ -2408,6 +2406,17 @@ eth_ena_prep_pkts(void *tx_queue, struct rte_mbuf **tx_pkts,
return i;
}
+ if (unlikely(m->nb_segs >= tx_ring->sgl_size &&
+ !(tx_ring->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV &&
+ m->nb_segs == tx_ring->sgl_size &&
+ m->data_len < tx_ring->tx_max_header_size))) {
+ PMD_TX_LOG(DEBUG,
+ "mbuf[%" PRIu32 "] has too many segments: %" PRIu16 "\n",
+ i, m->nb_segs);
+ rte_errno = EINVAL;
+ return i;
+ }
+
#ifdef RTE_LIBRTE_ETHDEV_DEBUG
/* Check if requested offload is also enabled for the queue */
if ((ol_flags & RTE_MBUF_F_TX_IP_CKSUM &&
@@ -2554,56 +2563,6 @@ static void ena_update_hints(struct ena_adapter *adapter,
}
}
-static int ena_check_space_and_linearize_mbuf(struct ena_ring *tx_ring,
- struct rte_mbuf *mbuf)
-{
- struct ena_com_dev *ena_dev;
- int num_segments, header_len, rc;
-
- ena_dev = &tx_ring->adapter->ena_dev;
- num_segments = mbuf->nb_segs;
- header_len = mbuf->data_len;
-
- if (likely(num_segments < tx_ring->sgl_size))
- goto checkspace;
-
- if (ena_dev->tx_mem_queue_type == ENA_ADMIN_PLACEMENT_POLICY_DEV &&
- (num_segments == tx_ring->sgl_size) &&
- (header_len < tx_ring->tx_max_header_size))
- goto checkspace;
-
- /* Checking for space for 2 additional metadata descriptors due to
- * possible header split and metadata descriptor. Linearization will
- * be needed so we reduce the segments number from num_segments to 1
- */
- if (!ena_com_sq_have_enough_space(tx_ring->ena_com_io_sq, 3)) {
- PMD_TX_LOG(DEBUG, "Not enough space in the Tx queue\n");
- return ENA_COM_NO_MEM;
- }
- ++tx_ring->tx_stats.linearize;
- rc = rte_pktmbuf_linearize(mbuf);
- if (unlikely(rc)) {
- PMD_TX_LOG(WARNING, "Mbuf linearize failed\n");
- rte_atomic64_inc(&tx_ring->adapter->drv_stats->ierrors);
- ++tx_ring->tx_stats.linearize_failed;
- return rc;
- }
-
- return 0;
-
-checkspace:
- /* Checking for space for 2 additional metadata descriptors due to
- * possible header split and metadata descriptor
- */
- if (!ena_com_sq_have_enough_space(tx_ring->ena_com_io_sq,
- num_segments + 2)) {
- PMD_TX_LOG(DEBUG, "Not enough space in the Tx queue\n");
- return ENA_COM_NO_MEM;
- }
-
- return 0;
-}
-
static void ena_tx_map_mbuf(struct ena_ring *tx_ring,
struct ena_tx_buffer *tx_info,
struct rte_mbuf *mbuf,
@@ -2688,9 +2647,14 @@ static int ena_xmit_mbuf(struct ena_ring *tx_ring, struct rte_mbuf *mbuf)
int nb_hw_desc;
int rc;
- rc = ena_check_space_and_linearize_mbuf(tx_ring, mbuf);
- if (unlikely(rc))
- return rc;
+ /* Checking for space for 2 additional metadata descriptors due to
+ * possible header split and metadata descriptor
+ */
+ if (!ena_com_sq_have_enough_space(tx_ring->ena_com_io_sq,
+ mbuf->nb_segs + 2)) {
+ PMD_DRV_LOG(DEBUG, "Not enough space in the tx queue\n");
+ return ENA_COM_NO_MEM;
+ }
next_to_use = tx_ring->next_to_use;
@@ -103,8 +103,6 @@ struct ena_stats_tx {
u64 cnt;
u64 bytes;
u64 prepare_ctx_err;
- u64 linearize;
- u64 linearize_failed;
u64 tx_poll;
u64 doorbells;
u64 bad_req_id;