[PATCH v5 16/19] net/tap: replace use of VLA in transmit burst

Stephen Hemminger
2026-02-22T17:34:23Z

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 <stephen@networkplumber.org>
---
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