From: Hannes Laimer <h.laimer@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: superseded: [PATCH proxmox v7 0/6] add proxmox-ebpf library
Date: Wed, 4 Nov 2026 18:31:31 +0100 [thread overview]
Message-ID: <e27a735f-2d81-4db3-b908-7b5211ff8c99@proxmox.com> (raw)
In-Reply-To: <20261104160105.2184145-1-h.laimer@proxmox.com>
superseded-by:
https://lore.proxmox.com/pve-devel/20261104172918.2643810-1-h.laimer@proxmox.com/
On 2026-11-04 17:02, Hannes Laimer wrote:
> proxmox-ebpf holds the eBPF programs and the code that loads, attaches
> and updates them, grouped into subsystems. It is a library only, whoever
> needs a subsystem pulls in just that one through a cargo feature and
> calls it from their side. This series is the shared part, the actual
> subsystems come as their own series on top.
>
> The core is the shared subsystem code. It takes care of everything from
> loading and attaching per interface to pinning in bpffs and tearing down
> again. So nothing has to keep running, and each call picks up where the
> last one left off. The build records a hash of the compiled object, the
> crate's version and a schema version per subsystem, so a call can tell
> what changed and an older build leaves a newer one's state alone. A
> changed program or map schema is swapped onto the existing links
> without interrupting traffic. The new maps are filled before the links
> move onto them. The BPF C code is also built natively against a small
> shim, so the parsing and packet building logic can be tested without a
> kernel. Packaging is debcargo like the other Rust crates.
>
> Every change runs under a lock per subsystem, a full apply takes it
> exclusively and a single-interface step shared, like the pmxcfs domain
> locks. The holder reads the input of its change under the lock and
> writes before it lets go. So a change and a full apply reach the kernel
> in the order they read their input, and nothing has to order them after
> the fact. A holder that never returns makes the waiters time out instead
> of hanging them. A subsystem can also hand over the whole content of its
> maps. The programs then move onto the new content one link at a time and
> never read a mix of old and new entries, and a write the kernel refuses
> leaves the old content in place. The programs of different subsystems on
> one interface run in a fixed order. An attach places its link relative
> to the links the other subsystems already hold there, so the order holds
> however the attaches are timed, and an update keeps every link in its
> place.
>
> The crate goes into the proxmox workspace, as the first one there with a
> build script. Building needs clang-21, libbpf-dev and
> proxmox-kernel-libc-dev, the programs compile against the UAPI headers
> from there.
>
> v7:
> * include rust pkg version next to fingerprint, so we can avoid
> flip-flopping the loaded programs in case a worker stays around
> during/after an upgrade
> * differentiate between a link swap failing on open or on the swap
> itself
> * replacing the maps and clearing take the lock guard mutably, so a map
> ref opened before cannot be written after the exchange, it would hit
> the retired map
> * the repair after an interrupted replacement also detaches the links
> of a direction the update dropped, a retry that failed afterwards
> left them attached
> * add context to io errors
> * merge a run order change, don't blindly replace, this covers cases
> where something was added and reordered in one
>
> v6:
> * loop all links at the start of every replace, moving links to live/
> is done one-by-one, so it can fail. a failed pass then has some links
> still on staging/, this makes sure we dont delete state that may
> still be attached. the kernel checks if it already exists on a swap,
> so this is a no-op, and at worst an atomic swap for links that still
> has staging/ attached
> * only allow adding to the run order, at least for live updates.
> removal or re-orders are applied on the next reboot
> * enforce that map refs live as long as the lock they were taken under
> * a pin that cannot be opened stays and fails the step instead of
> being unlinked, which under a descriptor shortage detached a working
> link
> * the harness tests run a C program of their own against the shim
> * move the crate into the proxmox workspace, the vendored vmlinux.h is
> gone, the programs build against the UAPI headers of
> proxmox-kernel-libc-dev with a versioned clang
>
> v5:
> * add a call that replaces the maps as a whole, it uses more space and
> writes everything instead of only what changed, but leaves the old
> content in place instead of a mix, in cases where the write fails
> with ENOMEM. Subsystems choose which they need
> * install/upgrade now also use this newly added replace path, this
> simplifies the process and also closes a hole where attached programs
> would read empty maps, shortly before they were filled after a schema
> version bump
> * the run order of the subsystems is written to
> `/run/proxmox-ebpf/order` by a full apply and every attach places by
> it, so a stale process running an older version attaches correctly
> against subsystems added by a process running a newer version
> * set correct permissions on `/run/..`
> * a build whose schema is older than the pinned one no longer counts
> its state as current, so its single steps back off as well
> * add `interrupted()` on the lock guard, true when a replacement left
> its staged set or an old schema directory behind, a full pass
> replaces then
> * an attach checks after attaching that the interface still has the
> index of its pin, one recreated under the same name in between is
> reported as gone
> * a map missing from a pinned set is reported by name
>
> v4, thanks @Stefan!:
> * drop the generation counter, a change takes the apply lock before it
> reads its input instead, so the lock order is the input order
> * new, the links of different subsystems on an interface are now
> ordered
> * the tc link plumbing is its own commit ahead of the subsystem code
> * subsystem programs are now a list of direction and name pairs
> * add short note for why not proxmox-sys's locking
> * improve tc error handling
> * fix smaller spacing and code stuff
>
>
> proxmox:
>
> Hannes Laimer (6):
> ebpf: add the crate with its BPF build
> ebpf: tc: add the link plumbing
> ebpf: subsystem: add the shared tc program handling
> ebpf: subsystem: place subsystem links in a fixed order
> ebpf: tests: add a native harness for the BPF C programs
> ebpf: debian: package the crate as a Rust library
>
> Cargo.toml | 2 +
> proxmox-ebpf/Cargo.toml | 22 +
> proxmox-ebpf/build.rs | 190 +++
> proxmox-ebpf/debian/changelog | 5 +
> proxmox-ebpf/debian/control | 50 +
> proxmox-ebpf/debian/copyright | 18 +
> proxmox-ebpf/debian/debcargo.toml | 13 +
> proxmox-ebpf/include/bpf_debug.h | 12 +
> proxmox-ebpf/src/bpf-shim/bpf/bpf_helpers.h | 34 +
> proxmox-ebpf/src/bpf-shim/bpf_debug.h | 10 +
> proxmox-ebpf/src/bpf-shim/linux/bpf.h | 25 +
> proxmox-ebpf/src/lib.rs | 6 +
> proxmox-ebpf/src/subsystem.rs | 1373 +++++++++++++++++++
> proxmox-ebpf/src/tc.rs | 326 +++++
> proxmox-ebpf/tests/bpf/fixture.bpf.c | 37 +
> proxmox-ebpf/tests/common/mod.rs | 211 +++
> proxmox-ebpf/tests/harness.rs | 84 ++
> 17 files changed, 2418 insertions(+)
> create mode 100644 proxmox-ebpf/Cargo.toml
> create mode 100644 proxmox-ebpf/build.rs
> create mode 100644 proxmox-ebpf/debian/changelog
> create mode 100644 proxmox-ebpf/debian/control
> create mode 100644 proxmox-ebpf/debian/copyright
> create mode 100644 proxmox-ebpf/debian/debcargo.toml
> create mode 100644 proxmox-ebpf/include/bpf_debug.h
> create mode 100644 proxmox-ebpf/src/bpf-shim/bpf/bpf_helpers.h
> create mode 100644 proxmox-ebpf/src/bpf-shim/bpf_debug.h
> create mode 100644 proxmox-ebpf/src/bpf-shim/linux/bpf.h
> create mode 100644 proxmox-ebpf/src/lib.rs
> create mode 100644 proxmox-ebpf/src/subsystem.rs
> create mode 100644 proxmox-ebpf/src/tc.rs
> create mode 100644 proxmox-ebpf/tests/bpf/fixture.bpf.c
> create mode 100644 proxmox-ebpf/tests/common/mod.rs
> create mode 100644 proxmox-ebpf/tests/harness.rs
>
>
> Summary over all repositories:
> 17 files changed, 2418 insertions(+), 0 deletions(-)
>
prev parent reply other threads:[~2026-11-04 17:32 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 16:00 [PATCH proxmox v7 0/6] add proxmox-ebpf library Hannes Laimer
2026-11-04 16:01 ` [PATCH proxmox v7 1/6] ebpf: add the crate with its BPF build Hannes Laimer
2026-11-04 16:01 ` [PATCH proxmox v7 2/6] ebpf: tc: add the link plumbing Hannes Laimer
2026-11-04 16:01 ` [PATCH proxmox v7 3/6] ebpf: subsystem: add the shared tc program handling Hannes Laimer
2026-11-04 16:01 ` [PATCH proxmox v7 4/6] ebpf: subsystem: place subsystem links in a fixed order Hannes Laimer
2026-11-04 16:01 ` [PATCH proxmox v7 5/6] ebpf: tests: add a native harness for the BPF C programs Hannes Laimer
2026-11-04 16:01 ` [PATCH proxmox v7 6/6] ebpf: debian: package the crate as a Rust library Hannes Laimer
2026-11-04 17:31 ` Hannes Laimer [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=e27a735f-2d81-4db3-b908-7b5211ff8c99@proxmox.com \
--to=h.laimer@proxmox.com \
--cc=pve-devel@lists.proxmox.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