freenode
Kernel & Low-Level

BPF gains common cgroup attach path for struct_ops maps

A bpf-next series reuses the existing bpf_link cgroup model so groups of BPF programs can share attach, ordering, and query semantics, with TCP sock ops as the first consumer.

BPF is gaining a shared way to attach struct_ops maps to cgroups, instead of each subsystem inventing its own hooks and lifetime rules.

Amery Hung, continuing earlier work by Martin KaFai Lau, posted a 15-patch series to the BPF list that extends the existing bpf_link cgroup API (already used for ordinary program types) to struct_ops. Conceptually a struct_ops map is a bundle of related BPF programs. Folding it into the same attach, detach, update, ordering, and query model keeps hierarchy behavior and tooling consistent, and avoids another round of one-off cgroup plumbing.

The push comes from LSF/MM/BPF discussions. Extending TCP via ever more BPF_SOCK_OPS_* callback enums has grown awkward: programs end up as large switches on a shared context that is hard to evolve when different hooks need different locking, arguments, and helpers. Attaching multiple programs on one cgroup also made the old reply-argument path unreliable. Separately, OOM and memory-cgroup work raised other cases that want struct_ops bound to a cgroup with predictable ordering.

The first concrete user is a new bpf_tcp_ops type. It mirrors the main TCP-related sockops hooks (connect, listen, established, RTT, retransmit, RTO, window and timeout init, and related state points), intentionally leaving out NEEDS_ECN and BASE_RTT. Header-option parse, length, and write hooks are included as well, reusing the existing reserve/store/load helpers so ports from legacy sockops stay mechanical. Return values can chain across multiple attachments, and placement supports before/after and preorder flags through the usual cgroup link options.

Libbpf gains a map attach helper and query support keyed by struct_ops type. Selftests cover attach, query, update, ordering, retval chaining, header options, and inheritance across a multi-level cgroup hierarchy.

If merged, subsystems that today bolt custom cgroup struct_ops paths can share one lifetime and ordering story, and TCP policy that once lived in sockops can move to typed per-callback struct_ops without growing the enum further.