DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Maxime Leroy <maxime@leroys.fr>
To: dev@dpdk.org
Cc: david.marchand@redhat.com, anatoly.burakov@intel.com,
	sivaprasad.tummala@amd.com, Maxime Leroy <maxime@leroys.fr>
Subject: [PATCH v2 6/6] examples/l3fwd-power: block until Rx interrupt or exit
Date: Wed,  9 Sep 2026 17:04:49 +0200	[thread overview]
Message-ID: <20260909150449.856295-7-maxime@leroys.fr> (raw)
In-Reply-To: <20260909150449.856295-1-maxime@leroys.fr>

In interrupt and legacy modes an idle worker arms its Rx queues and
sleeps in rte_epoll_wait() with a 10 ms timeout. The timeout lets the
worker wake periodically to re-check the quit flag, but it also hides a
broken interrupt path: with no interrupt delivered the worker still wakes
every 10 ms and polls, so traffic keeps flowing and interrupt mode looks
like it works when it does not.

Block indefinitely instead, so only a real Rx interrupt can wake the
worker. To still stop the workers on SIGINT, add an eventfd to each
worker epoll set; the signal handler writes it to wake every worker,
which then observes the quit flag and leaves its loop. Both loops share
this sleep path, so the eventfd is created for the interrupt and legacy
modes; it is skipped in the wakeup log so it is not reported as an Rx
interrupt.

Signed-off-by: Maxime Leroy <maxime@leroys.fr>
---
 examples/l3fwd-power/main.c | 40 +++++++++++++++++++++++++++++++++----
 1 file changed, 36 insertions(+), 4 deletions(-)

diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c
index c1ecf118f5..5ee8e5217e 100644
--- a/examples/l3fwd-power/main.c
+++ b/examples/l3fwd-power/main.c
@@ -9,6 +9,8 @@
 #include <sys/types.h>
 #include <string.h>
 #include <sys/queue.h>
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
 #include <stdarg.h>
 #include <errno.h>
 #include <getopt.h>
@@ -143,6 +145,9 @@ static int promiscuous_on = 0;
 /* NUMA is enabled by default. */
 static int numa_on = 1;
 volatile bool quit_signal;
+/* eventfd to wake idle workers out of a blocking rte_epoll_wait() at exit */
+static int wakeup_fd = -1;
+static struct rte_epoll_event wakeup_event[RTE_MAX_LCORE];
 /* timer to update telemetry every 500ms */
 static struct rte_timer telemetry_timer;
 
@@ -421,10 +426,17 @@ static int is_done(void)
 static void
 signal_exit_now(int sigtype)
 {
+	uint64_t one = 1;
+	ssize_t nbytes;
 
-	if (sigtype == SIGINT)
+	if (sigtype == SIGINT) {
 		quit_signal = true;
-
+		/* interrupt mode only: wake a worker blocked in rte_epoll_wait() */
+		if (wakeup_fd >= 0) {
+			nbytes = write(wakeup_fd, &one, sizeof(one));
+			RTE_SET_USED(nbytes);
+		}
+	}
 }
 
 /*  Frequency scale down timer callback */
@@ -836,7 +848,7 @@ sleep_until_rx_interrupt(int num, int lcore)
 	static alignas(RTE_CACHE_LINE_SIZE) struct {
 		bool wakeup;
 	} status[RTE_MAX_LCORE];
-	struct rte_epoll_event event[num];
+	struct rte_epoll_event event[num + 1];
 	int n, i;
 	uint16_t port_id;
 	uint16_t queue_id;
@@ -848,8 +860,10 @@ sleep_until_rx_interrupt(int num, int lcore)
 				rte_lcore_id());
 	}
 
-	n = rte_epoll_wait(RTE_EPOLL_PER_THREAD, event, num, 10);
+	n = rte_epoll_wait(RTE_EPOLL_PER_THREAD, event, num + 1, -1);
 	for (i = 0; i < n; i++) {
+		if (event[i].fd == wakeup_fd)
+			continue;
 		data = event[i].epdata.data;
 		port_id = ((uintptr_t)data) >> (sizeof(uint16_t) * CHAR_BIT);
 		queue_id = ((uintptr_t)data) &
@@ -922,6 +936,7 @@ rx_intr_enable_all(struct lcore_conf *qconf)
 static int event_register(struct lcore_conf *qconf)
 {
 	struct lcore_rx_queue *rx_queue;
+	struct rte_epoll_event *wev;
 	uint16_t queueid;
 	uint16_t portid;
 	uint32_t data;
@@ -947,6 +962,16 @@ static int event_register(struct lcore_conf *qconf)
 			return ret;
 	}
 
+	/* also watch the shutdown eventfd so a blocking wait wakes at exit */
+	if (wakeup_fd >= 0) {
+		wev = &wakeup_event[rte_lcore_id()];
+		wev->epdata.event = EPOLLIN | EPOLLPRI;
+		ret = rte_epoll_ctl(RTE_EPOLL_PER_THREAD, EPOLL_CTL_ADD,
+				    wakeup_fd, wev);
+		if (ret && ret != -EEXIST)
+			return ret;
+	}
+
 	return 0;
 }
 
@@ -2992,6 +3017,13 @@ main(int argc, char **argv)
 
 	check_all_ports_link_status(enabled_port_mask);
 
+	if (app_mode == APP_MODE_LEGACY || app_mode == APP_MODE_INTERRUPT) {
+		wakeup_fd = eventfd(0, EFD_NONBLOCK);
+		if (wakeup_fd < 0)
+			rte_exit(EXIT_FAILURE, "eventfd() failed: %s\n",
+				 strerror(errno));
+	}
+
 	/* launch per-lcore init on every lcore */
 	if (app_mode == APP_MODE_LEGACY) {
 		rte_eal_mp_remote_launch(main_legacy_loop, NULL, CALL_MAIN);
-- 
2.43.0


      parent reply	other threads:[~2026-09-09 15:05 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-20  8:00 [PATCH 0/6] examples/l3fwd-power: fix Rx interrupt mode for shared FD PMDs Maxime Leroy
2026-07-20  8:00 ` [PATCH 1/6] examples/l3fwd-power: factor out Rx interrupt sleep path Maxime Leroy
2026-07-20  8:00 ` [PATCH 2/6] examples/l3fwd-power: check Rx interrupt enable errors Maxime Leroy
2026-07-20  8:00 ` [PATCH 3/6] examples/l3fwd-power: enable Rx interrupt before epoll add Maxime Leroy
2026-09-04  9:15   ` David Marchand
2026-07-20  8:00 ` [PATCH 4/6] examples/l3fwd-power: accept shared Rx interrupt FD Maxime Leroy
2026-07-20  8:00 ` [PATCH 5/6] examples/l3fwd-power: recheck Rx queues before sleeping Maxime Leroy
2026-09-04  9:20   ` David Marchand
2026-09-04 20:25     ` Maxime Leroy
2026-07-20  8:00 ` [PATCH 6/6] examples/l3fwd-power: block until Rx interrupt or exit Maxime Leroy
2026-08-25  8:07 ` [PATCH 0/6] examples/l3fwd-power: fix Rx interrupt mode for shared FD PMDs Maxime Leroy
2026-09-04  9:30 ` David Marchand
2026-09-04 21:10   ` Maxime Leroy
2026-09-09 15:04 ` [PATCH v2 " Maxime Leroy
2026-09-09 15:04   ` [PATCH v2 1/6] examples/l3fwd-power: factor out Rx interrupt sleep path Maxime Leroy
2026-09-09 15:04   ` [PATCH v2 2/6] examples/l3fwd-power: check Rx interrupt enable errors Maxime Leroy
2026-09-09 15:04   ` [PATCH v2 3/6] examples/l3fwd-power: enable Rx interrupt before epoll add Maxime Leroy
2026-09-09 15:04   ` [PATCH v2 4/6] examples/l3fwd-power: accept shared Rx interrupt FD Maxime Leroy
2026-09-09 15:04   ` [PATCH v2 5/6] examples/l3fwd-power: recheck Rx queues before sleeping Maxime Leroy
2026-09-09 15:04   ` Maxime Leroy [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260909150449.856295-7-maxime@leroys.fr \
    --to=maxime@leroys.fr \
    --cc=anatoly.burakov@intel.com \
    --cc=david.marchand@redhat.com \
    --cc=dev@dpdk.org \
    --cc=sivaprasad.tummala@amd.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox