From: David Gibson <david@gibson.dropbear.id.au>
To: Laurent Vivier <lvivier@redhat.com>
Cc: passt-dev@passt.top
Subject: Re: [PATCH v4 7/7] passt: Move main event loop processing into passt_worker()
Date: Mon, 20 Oct 2025 12:43:02 +1100 [thread overview]
Message-ID: <aPWTpg0W6m9RbArk@zatzit> (raw)
In-Reply-To: <20251017103129.229412-8-lvivier@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 6973 bytes --]
On Fri, Oct 17, 2025 at 12:31:29PM +0200, Laurent Vivier wrote:
> Extract the epoll event processing logic from main() into a separate
> passt_worker() function. This refactoring prepares the code for future
> threading support where passt_worker() will be called as a worker thread
> callback.
>
> The new function handles:
> - Processing epoll events and dispatching to protocol handlers
> - Event statistics tracking and printing
> - Post-handler periodic tasks (timers, deferred work)
> - Migration handling
>
> No functional changes, purely a code restructuring.
>
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Looks good as far as it goes, and I've though often in the past that
it would make more sense for the "engine" to go in its own function.
Wondering if it would make more sense to include the epoll_wait()
itself and the loop in this function, rather than leaving that
outside.
> ---
> passt.c | 160 +++++++++++++++++++++++++++++++-------------------------
> 1 file changed, 88 insertions(+), 72 deletions(-)
>
> diff --git a/passt.c b/passt.c
> index 37f2c897be84..5bfa4c6353d9 100644
> --- a/passt.c
> +++ b/passt.c
> @@ -229,6 +229,92 @@ static void print_stats(const struct ctx *c, const struct passt_stats *stats,
> lines_printed++;
> }
>
> +/**
> + * passt_worker() - Process epoll events and handle protocol operations
> + * @opaque: Pointer to execution context (struct ctx)
> + * @nfds: Number of file descriptors ready (epoll_wait return value)
> + * @events: epoll_event array of ready file descriptors
> + */
> +static void passt_worker(void *opaque, int nfds, struct epoll_event *events)
> +{
> + static struct passt_stats stats = { 0 };
> + struct ctx *c = opaque;
> + struct timespec now;
> + int i;
> +
> + if (clock_gettime(CLOCK_MONOTONIC, &now))
> + err_perror("Failed to get CLOCK_MONOTONIC time");
> +
> + for (i = 0; i < nfds; i++) {
> + union epoll_ref ref = *((union epoll_ref *)&events[i].data.u64);
> + uint32_t eventmask = events[i].events;
> +
> + trace("%s: epoll event on %s %i (events: 0x%08x)",
> + c->mode == MODE_PASTA ? "pasta" : "passt",
> + EPOLL_TYPE_STR(ref.type), ref.fd, eventmask);
> +
> + switch (ref.type) {
> + case EPOLL_TYPE_TAP_PASTA:
> + tap_handler_pasta(c, eventmask, &now);
> + break;
> + case EPOLL_TYPE_TAP_PASST:
> + tap_handler_passt(c, eventmask, &now);
> + break;
> + case EPOLL_TYPE_TAP_LISTEN:
> + tap_listen_handler(c, eventmask);
> + break;
> + case EPOLL_TYPE_NSQUIT_INOTIFY:
> + pasta_netns_quit_inotify_handler(c, ref.fd);
> + break;
> + case EPOLL_TYPE_NSQUIT_TIMER:
> + pasta_netns_quit_timer_handler(c, ref);
> + break;
> + case EPOLL_TYPE_TCP:
> + tcp_sock_handler(c, ref, eventmask);
> + break;
> + case EPOLL_TYPE_TCP_SPLICE:
> + tcp_splice_sock_handler(c, ref, eventmask);
> + break;
> + case EPOLL_TYPE_TCP_LISTEN:
> + tcp_listen_handler(c, ref, &now);
> + break;
> + case EPOLL_TYPE_TCP_TIMER:
> + tcp_timer_handler(c, ref);
> + break;
> + case EPOLL_TYPE_UDP_LISTEN:
> + udp_listen_sock_handler(c, ref, eventmask, &now);
> + break;
> + case EPOLL_TYPE_UDP:
> + udp_sock_handler(c, ref, eventmask, &now);
> + break;
> + case EPOLL_TYPE_PING:
> + icmp_sock_handler(c, ref);
> + break;
> + case EPOLL_TYPE_VHOST_CMD:
> + vu_control_handler(c->vdev, c->fd_tap, eventmask);
> + break;
> + case EPOLL_TYPE_VHOST_KICK:
> + vu_kick_cb(c->vdev, ref, &now);
> + break;
> + case EPOLL_TYPE_REPAIR_LISTEN:
> + repair_listen_handler(c, eventmask);
> + break;
> + case EPOLL_TYPE_REPAIR:
> + repair_handler(c, eventmask);
> + break;
> + default:
> + /* Can't happen */
> + ASSERT(0);
> + }
> + stats.events[ref.type]++;
> + print_stats(c, &stats, &now);
> + }
> +
> + post_handler(c, &now);
> +
> + migrate_handler(c);
> +}
> +
> /**
> * main() - Entry point and main loop
> * @argc: Argument count
> @@ -246,8 +332,7 @@ static void print_stats(const struct ctx *c, const struct passt_stats *stats,
> int main(int argc, char **argv)
> {
> struct epoll_event events[NUM_EPOLL_EVENTS];
> - struct passt_stats stats = { 0 };
> - int nfds, i, devnull_fd = -1;
> + int nfds, devnull_fd = -1;
> struct ctx c = { 0 };
> struct rlimit limit;
> struct timespec now;
> @@ -355,77 +440,8 @@ loop:
> if (nfds == -1 && errno != EINTR)
> die_perror("epoll_wait() failed in main loop");
>
> - if (clock_gettime(CLOCK_MONOTONIC, &now))
> - err_perror("Failed to get CLOCK_MONOTONIC time");
> -
> - for (i = 0; i < nfds; i++) {
> - union epoll_ref ref = *((union epoll_ref *)&events[i].data.u64);
> - uint32_t eventmask = events[i].events;
> -
> - trace("%s: epoll event on %s %i (events: 0x%08x)",
> - c.mode == MODE_PASTA ? "pasta" : "passt",
> - EPOLL_TYPE_STR(ref.type), ref.fd, eventmask);
> -
> - switch (ref.type) {
> - case EPOLL_TYPE_TAP_PASTA:
> - tap_handler_pasta(&c, eventmask, &now);
> - break;
> - case EPOLL_TYPE_TAP_PASST:
> - tap_handler_passt(&c, eventmask, &now);
> - break;
> - case EPOLL_TYPE_TAP_LISTEN:
> - tap_listen_handler(&c, eventmask);
> - break;
> - case EPOLL_TYPE_NSQUIT_INOTIFY:
> - pasta_netns_quit_inotify_handler(&c, ref.fd);
> - break;
> - case EPOLL_TYPE_NSQUIT_TIMER:
> - pasta_netns_quit_timer_handler(&c, ref);
> - break;
> - case EPOLL_TYPE_TCP:
> - tcp_sock_handler(&c, ref, eventmask);
> - break;
> - case EPOLL_TYPE_TCP_SPLICE:
> - tcp_splice_sock_handler(&c, ref, eventmask);
> - break;
> - case EPOLL_TYPE_TCP_LISTEN:
> - tcp_listen_handler(&c, ref, &now);
> - break;
> - case EPOLL_TYPE_TCP_TIMER:
> - tcp_timer_handler(&c, ref);
> - break;
> - case EPOLL_TYPE_UDP_LISTEN:
> - udp_listen_sock_handler(&c, ref, eventmask, &now);
> - break;
> - case EPOLL_TYPE_UDP:
> - udp_sock_handler(&c, ref, eventmask, &now);
> - break;
> - case EPOLL_TYPE_PING:
> - icmp_sock_handler(&c, ref);
> - break;
> - case EPOLL_TYPE_VHOST_CMD:
> - vu_control_handler(c.vdev, c.fd_tap, eventmask);
> - break;
> - case EPOLL_TYPE_VHOST_KICK:
> - vu_kick_cb(c.vdev, ref, &now);
> - break;
> - case EPOLL_TYPE_REPAIR_LISTEN:
> - repair_listen_handler(&c, eventmask);
> - break;
> - case EPOLL_TYPE_REPAIR:
> - repair_handler(&c, eventmask);
> - break;
> - default:
> - /* Can't happen */
> - ASSERT(0);
> - }
> - stats.events[ref.type]++;
> - print_stats(&c, &stats, &now);
> - }
> -
> - post_handler(&c, &now);
>
> - migrate_handler(&c);
> + passt_worker(&c, nfds, events);
>
> goto loop;
> }
> --
> 2.51.0
>
--
David Gibson (he or they) | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you, not the other way
| around.
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2025-10-20 1:43 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-17 10:31 [PATCH v4 0/7] Refactor epoll handling in preparation for multithreading Laurent Vivier
2025-10-17 10:31 ` [PATCH v4 1/7] util: Simplify epoll_del() interface to take epollfd directly Laurent Vivier
2025-10-17 10:31 ` [PATCH v4 2/7] epoll_ctl: Extract epoll operations Laurent Vivier
2025-10-17 11:48 ` Stefano Brivio
2025-10-17 12:21 ` Laurent Vivier
2025-10-17 13:05 ` Stefano Brivio
2025-10-20 1:20 ` David Gibson
2025-10-21 11:52 ` Laurent Vivier
2025-10-22 0:58 ` David Gibson
2025-10-17 10:31 ` [PATCH v4 3/7] util: Move epoll registration out of sock_l4_sa() Laurent Vivier
2025-10-17 10:31 ` [PATCH v4 4/7] tcp, flow: Replace per-connection in_epoll flag with threadnb in flow_common Laurent Vivier
2025-10-17 17:43 ` Stefano Brivio
2025-10-21 13:13 ` Laurent Vivier
2025-10-20 1:34 ` David Gibson
2025-10-21 12:14 ` Laurent Vivier
2025-10-22 1:00 ` David Gibson
2025-10-17 10:31 ` [PATCH v4 5/7] icmp: Use thread-based epoll management for ICMP flows Laurent Vivier
2025-10-20 1:35 ` David Gibson
2025-10-17 10:31 ` [PATCH v4 6/7] udp: Use thread-based epoll management for UDP flows Laurent Vivier
2025-10-20 1:39 ` David Gibson
2025-10-17 10:31 ` [PATCH v4 7/7] passt: Move main event loop processing into passt_worker() Laurent Vivier
2025-10-17 17:43 ` Stefano Brivio
2025-10-20 1:43 ` David Gibson [this message]
2025-10-21 8:00 ` Laurent Vivier
2025-10-22 0:53 ` David Gibson
2025-10-22 6:49 ` Laurent Vivier
2025-10-23 1:24 ` David Gibson
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=aPWTpg0W6m9RbArk@zatzit \
--to=david@gibson.dropbear.id.au \
--cc=lvivier@redhat.com \
--cc=passt-dev@passt.top \
/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.
Code repositories for project(s) associated with this public inbox
https://passt.top/passt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).