On Mon, 20 Jul 2026 at 10:01, Maxime Leroy <[email protected]> wrote: > > After arming the Rx interrupts rx_interrupt_wait() sleeps in > rte_epoll_wait(). A packet that arrived between the last poll and the arm > can be missed on PMDs whose interrupt is edge-triggered on an empty to > non-empty transition, such as dpaa2: arming a queue that is already > non-empty raises no notification, so the lcore sleeps until the next > packet. > > Before sleeping, check whether any queue already holds traffic and, if > so, skip the wait and go back to polling. NICs with level-triggered > interrupts are unaffected: a pending packet keeps the interrupt asserted, > so rte_epoll_wait() would return immediately anyway. > > Signed-off-by: Maxime Leroy <[email protected]> > --- > examples/l3fwd-power/main.c | 27 ++++++++++++++++++++++++++- > 1 file changed, 26 insertions(+), 1 deletion(-) > > diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c > index fa64e28e5c..c423b0dba5 100644 > --- a/examples/l3fwd-power/main.c > +++ b/examples/l3fwd-power/main.c > @@ -949,6 +949,26 @@ static int event_register(struct lcore_conf *qconf) > return 0; > } > > +static bool > +rx_queue_pending(struct lcore_conf *qconf) > +{ > + struct lcore_rx_queue *rx_queue; > + uint16_t queue_id; > + uint16_t port_id; > + int i; > + > + for (i = 0; i < qconf->n_rx_queue; ++i) { > + rx_queue = &(qconf->rx_queue_list[i]); > + port_id = rx_queue->port_id; > + queue_id = rx_queue->queue_id; > + > + if (rte_eth_rx_queue_count(port_id, queue_id) > 0) > + return true; > + } > + > + return false; > +} > + > static int > rx_interrupt_wait(struct lcore_conf *qconf, int *intr_registered) > { > @@ -968,7 +988,12 @@ rx_interrupt_wait(struct lcore_conf *qconf, int > *intr_registered) > *intr_registered = 1; > } > > - sleep_until_rx_interrupt(qconf->n_rx_queue, rte_lcore_id()); > + /* > + * A packet that arrived during the arm window raises no new wakeup on > + * edge-triggered PMDs, so skip the sleep if a queue already has > traffic. > + */ > + if (!rx_queue_pending(qconf)) > + sleep_until_rx_interrupt(qconf->n_rx_queue, rte_lcore_id()); > rx_intr_disable_all(qconf); > return 0; > }
I don't see how this solves the race. There is stil a window between checking the queue count and sleeping. Looks like a bug that should be solved in the driver. -- David Marchand

