Replace the per-packet variable-length iovec array on the stack
with a fixed-size array of TAP_MAX_TX_SEGS + 1 (129) entries,
hoisted to function scope in tap_write_mbufs(). Packets with
more than 128 segments are dropped.

This eliminates the last VLA in the driver.

Signed-off-by: Stephen Hemminger <[email protected]>
---
 drivers/net/tap/rte_eth_tap.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
index f2cf7da736..9efdbc7012 100644
--- a/drivers/net/tap/rte_eth_tap.c
+++ b/drivers/net/tap/rte_eth_tap.c
@@ -79,9 +79,15 @@ static_assert(RTE_PMD_TAP_MAX_QUEUES <= RTE_MP_MAX_FD_NUM, 
"TAP max queues excee
  */
 #define TAP_MAX_RX_SEGS 128
 
+/* Limit on the number of segments per mbuf on Tx */
+#define TAP_MAX_TX_SEGS  128
+
 static_assert(TAP_MAX_RX_SEGS + 1 <= IOV_MAX,
              "TAP_MAX_RX_SEGS + 1 (for tun_pi) must not exceed IOV_MAX");
 
+static_assert(TAP_MAX_TX_SEGS + 1 <= IOV_MAX,
+             "TAP_MAX_TX_SEGS + 1 (for tun_pi) must not exceed IOV_MAX");
+
 #define TAP_RX_OFFLOAD (RTE_ETH_RX_OFFLOAD_SCATTER |   \
                        RTE_ETH_RX_OFFLOAD_IPV4_CKSUM | \
                        RTE_ETH_RX_OFFLOAD_UDP_CKSUM |  \
@@ -533,13 +539,13 @@ tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
                        uint16_t *num_packets, unsigned long *num_tx_bytes)
 {
        struct pmd_process_private *process_private;
+       struct iovec iovecs[TAP_MAX_TX_SEGS + 1];
        int i;
 
        process_private = rte_eth_devices[txq->out_port].process_private;
 
        for (i = 0; i < num_mbufs; i++) {
                struct rte_mbuf *mbuf = pmbufs[i];
-               struct iovec iovecs[mbuf->nb_segs + 2];
                struct tun_pi pi = { .flags = 0, .proto = 0x00 };
                struct rte_mbuf *seg = mbuf;
                uint64_t l4_ol_flags;
@@ -641,6 +647,10 @@ tap_write_mbufs(struct tx_queue *txq, uint16_t num_mbufs,
                }
 
 skip_l4_cksum:
+               /* tun_pi header + packet segments must fit in iovecs */
+               if (unlikely(mbuf->nb_segs > TAP_MAX_TX_SEGS))
+                       return -1;
+
                for (j = 0; j < mbuf->nb_segs; j++) {
                        iovecs[k].iov_len = rte_pktmbuf_data_len(seg);
                        iovecs[k].iov_base = rte_pktmbuf_mtod(seg, void *);
@@ -669,7 +679,7 @@ pmd_tx_burst(void *queue, struct rte_mbuf **bufs, uint16_t 
nb_pkts)
        uint16_t num_packets = 0;
        unsigned long num_tx_bytes = 0;
        uint32_t max_size;
-       int i;
+       unsigned int i;
 
        if (unlikely(nb_pkts == 0))
                return 0;
-- 
2.51.0

Reply via email to