From: Laurent Vivier <lvivier@redhat.com>
To: passt-dev@passt.top
Cc: Laurent Vivier <lvivier@redhat.com>
Subject: [PATCH v5 0/7] Refactor epoll handling in preparation for multithreading
Date: Tue, 21 Oct 2025 23:01:09 +0200 [thread overview]
Message-ID: <20251021210116.314674-1-lvivier@redhat.com> (raw)
This series refactors how epoll file descriptors are managed throughout
the codebase in preparation for introducing multithreading support.
Currently, passt uses a single global epollfd accessed through the
context structure. With multithreading, each thread will need its own
epollfd managing its subset of flows.
The key changes are:
1. Centralize epoll management by extracting helper functions into a new
epoll_ctl.c/h module and moving union epoll_ref from passt.h to its
more logical location in epoll_ctl.h.
2. Simplify epoll_del() to take the epollfd directly rather than
extracting it from the context structure, reducing coupling between
epoll operations and the global context.
3. Move epoll registration out of sock_l4_sa() into protocol-specific
code, giving callers explicit control over which epoll instance
manages each socket.
4. Replace the boolean in_epoll flag in TCP connections with an epollid
(epoll identifier) field in flow_common. This serves dual purposes:
tracking registration status (EPOLLFD_ID_INVALID = not registered)
and identifying which epoll instance manages the flow. An epoll ID to
epoll fd mapping allows retrieving the actual epoll file descriptor.
The epollid field is 8 bits, limiting values to 0-254 (255 =
EPOLLFD_ID_INVALID).
5. Apply this pattern consistently across all protocol handlers (TCP,
ICMP, UDP), storing the managing epoll ID in each flow's common
structure.
6. Extract the event loop processing logic into a separate passt_worker()
function, preparing the structure for future threading where this will
become a worker thread callback.
These changes make epoll instance ownership explicit in the flow tracking
system, enabling flows to be managed by different epoll instances, a
prerequisite for per-thread epollfd design in upcoming multithreading
work.
Changes since v1:
- New patch: "epoll_ctl: Extract epoll operations" - centralizes epoll
helpers into a dedicated module and relocates union epoll_ref from
passt.h to epoll_ctl.h
- Changed epollfd type in flow_common from int to 8-bit bitfield to avoid
exceeding cacheline size threshold
- Added flow_epollfd_valid() helper to check epoll registration status
- Added flow_set_epollfd() helper to set the epoll instance for a flow
Changes since v2:
- Renamed field in flow_common from epollfd to threadnb (thread number)
to better reflect that flows are now associated with threads rather
than directly with epoll file descriptors
- Introduced thread-to-epollfd mapping via threadnb_to_epollfd[] array
in flow.c, providing an indirection layer between threads and their
epoll instances
- Renamed/refactored helper functions:
- flow_set_epollfd() -> flow_epollfd_set() - now takes thread number
and epollfd parameters
- Added flow_epollfd_get() - retrieves the epoll fd for a flow's thread
- flow_epollfd_valid() - now checks threadnb instead of epollfd
- Updated constants: replaced EPOLLFD_* with FLOW_THREADNB_* equivalents
(e.g., EPOLLFD_INVALID -> FLOW_THREADNB_INVALID)
- Applied thread-based pattern consistently across TCP, ICMP, and UDP
Changes since v3:
- Change warn() by err() in epoll_add()
- Renamed flow_epollfd_valid() to flow_in_epoll(), flow_epollfd_get() to
flow_epollfd().
- Added flow_thread_register() to register an epollfd to a thread number,
and called it from main() to register c->epollfd for thread 0 (main loop)
- Replaced flow_epollfd_set() by flow_thread_set() to set the thread
number of a flow.
- Added new patch:
"passt: Move main event loop processing into passt_worker()"
Changes since v4:
- Renamed field in flow_common from threadnb to epollid (epoll identifier)
to better reflect the abstraction - flows are associated with an epoll
instance identifier rather than specifically a thread number
- Renamed mapping array from threadnb_to_epollfd[] to epoll_id_to_fd[]
- Renamed/refactored helper functions:
- flow_thread_set() -> flow_epollid_set() - sets the epoll ID
- flow_thread_register() -> flow_epollid_register() - registers the
epollfd for a given epoll ID
- Added flow_epollid_clear() - explicitly clears the epoll ID
- Updated constants: replaced FLOW_THREADNB_* with EPOLLFD_ID_* equivalents
(e.g., FLOW_THREADNB_INVALID -> EPOLLFD_ID_INVALID, FLOW_THREADNB_MAX ->
EPOLLFD_ID_MAX)
- Added EPOLLFD_ID_DEFAULT constant for the default (main loop) epoll instance
- Clarified that EPOLLFD_ID_BITS limits the number of epoll instances, not
threads (though initially there will be one epoll instance per thread)
Laurent Vivier (7):
util: Simplify epoll_del() interface to take epollfd directly
epoll_ctl: Extract epoll operations
util: Move epoll registration out of sock_l4_sa()
tcp, flow: Replace per-connection in_epoll flag with an epollid in
flow_common
icmp: Use epoll instance management for ICMP flows
udp: Use epoll instance management for UDP flows
passt: Move main event loop processing into passt_worker()
Makefile | 22 +++----
epoll_ctl.c | 45 ++++++++++++++
epoll_ctl.h | 51 ++++++++++++++++
flow.c | 71 +++++++++++++++++++---
flow.h | 15 ++++-
icmp.c | 23 +++++---
passt.c | 163 ++++++++++++++++++++++++++++-----------------------
passt.h | 34 -----------
pasta.c | 7 +--
pif.c | 32 +++++++---
repair.c | 18 +++---
tap.c | 15 ++---
tcp.c | 46 +++++++++------
tcp_conn.h | 8 +--
tcp_splice.c | 26 ++++----
udp.c | 2 +-
udp_flow.c | 23 ++++++--
util.c | 28 +--------
util.h | 6 +-
vhost_user.c | 14 ++---
vu_common.c | 2 +-
21 files changed, 403 insertions(+), 248 deletions(-)
create mode 100644 epoll_ctl.c
create mode 100644 epoll_ctl.h
--
2.51.0
next reply other threads:[~2025-10-21 21:01 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-21 21:01 Laurent Vivier [this message]
2025-10-21 21:01 ` [PATCH v5 1/7] util: Simplify epoll_del() interface to take epollfd directly Laurent Vivier
2025-10-21 21:01 ` [PATCH v5 2/7] epoll_ctl: Extract epoll operations Laurent Vivier
2025-10-23 1:29 ` David Gibson
2025-10-21 21:01 ` [PATCH v5 3/7] util: Move epoll registration out of sock_l4_sa() Laurent Vivier
2025-10-21 21:01 ` [PATCH v5 4/7] tcp, flow: Replace per-connection in_epoll flag with an epollid in flow_common Laurent Vivier
2025-10-23 1:39 ` David Gibson
2025-10-30 17:00 ` Stefano Brivio
2025-10-21 21:01 ` [PATCH v5 5/7] icmp: Use epoll instance management for ICMP flows Laurent Vivier
2025-10-21 21:01 ` [PATCH v5 6/7] udp: Use epoll instance management for UDP flows Laurent Vivier
2025-10-23 1:40 ` David Gibson
2025-10-21 21:01 ` [PATCH v5 7/7] passt: Move main event loop processing into passt_worker() Laurent Vivier
2025-10-23 1:42 ` David Gibson
2025-10-30 17:00 ` [PATCH v5 0/7] Refactor epoll handling in preparation for multithreading Stefano Brivio
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=20251021210116.314674-1-lvivier@redhat.com \
--to=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).