Don't use int as a boolean. Use bool. Ideally find unused pad hole for it
On Fri, Jul 17, 2026, 11:59 AM Maxime Leroy <[email protected]> wrote:
> The tap Rx path is driven by a SIGIO trigger: pmd_rx_burst() returns
> without reading the queue fd unless tap_trigger, bumped by the O_ASYNC
> signal handler, has advanced. That avoids a readv() on every empty poll.
>
> In Rx interrupt mode the application blocks on the queue fd through epoll
> and polls only after a wakeup. The epoll wakeup and the trigger are
> distinct signals, so the burst can return 0 right after a wakeup because
> the trigger has not advanced, leaving the fd readable with no further
> edge: traffic stalls.
>
> When the port is configured for Rx interrupts, drain the fd
> unconditionally in the burst and do not arm the SIGIO trigger on the data
> queue fd. A data queue fd can be closed and recreated on a later setup,
> so the mode must stay constant to keep every fd on the same SIGIO policy:
> it is fixed at configure time and a later change is rejected. Close and
> reopen the port to switch modes.
>
> Fixes: 4870a8cdd968 ("net/tap: support Rx interrupt")
> Cc: [email protected]
>
> Signed-off-by: Maxime Leroy <[email protected]>
> ---
> drivers/net/tap/rte_eth_tap.c | 18 +++++++++++++++++-
> drivers/net/tap/rte_eth_tap.h | 2 ++
> 2 files changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/tap/rte_eth_tap.c b/drivers/net/tap/rte_eth_tap.c
> index 99ede19e49..ea9ef76335 100644
> --- a/drivers/net/tap/rte_eth_tap.c
> +++ b/drivers/net/tap/rte_eth_tap.c
> @@ -254,6 +254,10 @@ tun_alloc(struct pmd_internals *pmd, int
> is_keepalive, int persistent)
> goto error;
> }
>
> + /* interrupt mode wakes through epoll on the data queue fd, not
> the SIGIO trigger */
> + if (pmd->intr_mode)
> + return fd;
> +
> /* Find a free realtime signal */
> for (signo = SIGRTMIN + 1; signo < SIGRTMAX; signo++) {
> struct sigaction sa;
> @@ -477,7 +481,7 @@ pmd_rx_burst(void *queue, struct rte_mbuf **bufs,
> uint16_t nb_pkts)
> unsigned long num_rx_bytes = 0;
> uint32_t trigger = tap_trigger;
>
> - if (trigger == rxq->trigger_seen)
> + if (!rxq->intr_mode && trigger == rxq->trigger_seen)
> return 0;
>
> process_private = rte_eth_devices[rxq->in_port].process_private;
> @@ -937,6 +941,16 @@ tap_dev_configure(struct rte_eth_dev *dev)
> struct pmd_internals *pmd = dev->data->dev_private;
> int intr_mode = !!dev->data->dev_conf.intr_conf.rxq;
>
> + /* The queue fd is created once and its SIGIO trigger is armed for
> poll
> + * mode only; the interrupt mode cannot be toggled on an existing
> port.
> + */
> + if (pmd->intr_mode_set && pmd->intr_mode != intr_mode) {
> + TAP_LOG(ERR,
> + "%s: Rx interrupt mode is fixed after configure,
> close and reopen the port to change it",
> + dev->device->name);
> + return -ENOTSUP;
> + }
> +
> if (dev->data->nb_rx_queues != dev->data->nb_tx_queues) {
> TAP_LOG(ERR,
> "%s: number of rx queues %d must be equal to
> number of tx queues %d",
> @@ -947,6 +961,7 @@ tap_dev_configure(struct rte_eth_dev *dev)
> }
>
> pmd->intr_mode = intr_mode;
> + pmd->intr_mode_set = 1;
>
> TAP_LOG(INFO, "%s: %s: TX configured queues number: %u",
> dev->device->name, pmd->name, dev->data->nb_tx_queues);
> @@ -1620,6 +1635,7 @@ tap_rx_queue_setup(struct rte_eth_dev *dev,
> rxq->queue_id = rx_queue_id;
> rxq->max_rx_segs = max_rx_segs;
> rxq->rxmode = &dev->data->dev_conf.rxmode;
> + rxq->intr_mode = internals->intr_mode;
>
> dev->data->rx_queues[rx_queue_id] = rxq;
> int fd = tap_setup_queue(dev, rx_queue_id, 1);
> diff --git a/drivers/net/tap/rte_eth_tap.h b/drivers/net/tap/rte_eth_tap.h
> index 3180719c34..abe22aac9f 100644
> --- a/drivers/net/tap/rte_eth_tap.h
> +++ b/drivers/net/tap/rte_eth_tap.h
> @@ -50,6 +50,7 @@ struct rx_queue {
> uint16_t queue_id; /* queue ID*/
> struct queue_stats stats; /* Stats for this RX queue */
> uint16_t max_rx_segs; /* max scatter segments per packet
> */
> + uint16_t intr_mode; /* 1 when Rx queue interrupts are
> used */
> struct rte_eth_rxmode *rxmode; /* RX features */
> struct rte_mbuf *pool; /* mbufs pool for this queue */
> struct tun_pi pi; /* packet info for iovecs */
> @@ -94,6 +95,7 @@ struct pmd_internals {
>
> struct rte_intr_handle *intr_handle; /* LSC interrupt
> handle. */
> int intr_mode; /* Rx queue interrupt mode */
> + int intr_mode_set; /* intr_mode locked after
> configure */
> int ka_fd; /* keep-alive file descriptor */
> struct rte_mempool *gso_ctx_mp; /* Mempool for GSO packets */
> };
> --
> 2.43.0
>
>