Thread (19 messages) flat view 19 messages, 3 authors, 1d ago
WARM1d

Revision v2 of 3 in this series.

Revisions (3)
  1. rfc [diff vs current]
  2. v1 [diff vs current]
  3. v2 current

[PATCH net-next v2 00/14] skb extension for BPF metadata

From: Jakub Sitnicki <jakub@cloudflare.com>
Date: 2026-09-10 14:02:44
Also in: bpf

This is the second spin of the per-packet metadata for BPF. See the RFC
cover letter for the full overview and motivation [1].

Since v1 the focus has been on getting skb scrubbing and extension sharing
right, driven by Sashiko's review:

1) skb scrubbing now simply deactivates all the extensions but the BPF
metadata. Made possible due to recent change in skb_ext_del semantics [2]
that already landed in net-next. Thanks to Florian and Paolo for guidance
on this.

2) Clones made by bpf_clone_redirect() share the extension block. A write
through a previously acquired writable dynptr would land in the shared
block and become visible to the clone, so v2 makes such writes fail until
the program re-acquires the dynptr with BPF_SKB_EXT_F_CREATE, which COWs
the block into a private writable copy.

3) Re-acquiring the extension with BPF_SKB_EXT_F_CREATE can COW and free
the old block, so a dynptr slice taken before that re-acquire would be left
pointing into freed memory. bpf_dynptr_from_skb_ext() is therefore marked
packet-changing, making the verifier invalidate such slices and forcing the
program to re-take them after the re-acquire.

4) Tracing and LSM programs can run on a shared skb concurrently on another
CPU, so creating the extension there would mutate skb->extensions without
synchronization. v2 rejects BPF_SKB_EXT_F_CREATE in these program types at
load time; read-only access remains available.

Regarding performance compared to consume_skb+kfree_skb tracepoints, I have
not yet re-run the experiment measuring the overhead when attaching
metadata to 5% instead of 1% of skbs in flight; happy to do so if it is a
blocker.

That said, as things stand we have already established in v1 [3] that for
our existing use case - attaching metadata to <1% of skbs - the
tracepoint-based approach is prohibitively expensive (+5% of CPU time), as
Jesper noted.

The skb-extension-based solution, in contrast, shows comparable-or-lower
overhead, making it a viable drop-in replacement that enables new use cases
for us and potentially offers a performance win.

Thanks,
-jkbs

[1] https://patch.msgid.link/20260714-bpf-meta-inside-skb-ext-v1-0-5871c07a8dd6@cloudflare.com
[2] https://lore.kernel.org/all/20260831-skb-ext-prep-work-v1-0-ecc2a8542fd9@cloudflare.com/ (local)
[3] https://patch.msgid.link/20260814-bpf-meta-inside-skb-ext-v1-0-767edd862656@cloudflare.com

Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com>
---
Changes in v2:
- Rework skb_ext_scrub() to simply delete all extensions but bpf_skb_ext
  now that the delete operation is idempotent. (Florian, sashiko)
- Fail writes through a dynptr while the extension block is shared with
  clones: bpf_dynptr_write() now returns -EBUSY and bpf_dynptr_slice_rdwr()
  returns NULL; re-acquiring the dynptr with BPF_SKB_EXT_F_CREATE COWs the
  block and restores write access. (sashiko)
- Mark bpf_dynptr_from_skb_ext() as packet-changing so the verifier
  invalidates slices from an earlier dynptr when a re-open with F_CREATE
  can COW the block and leave them dangling (use-after-free). (sashiko)
- Reject bpf_dynptr_from_skb_ext(BPF_SKB_EXT_F_CREATE) in tracing and LSM
  programs, which can run on a shared skb concurrently on another CPU;
  require a constant flags argument without F_CREATE at load time, keeping
  read-only access. (sashiko)
- selftests: Add verifier negative tests for the new tracing/LSM
  restrictions (F_CREATE and non-constant flags rejected). (sashiko)
- selftests: Add clone_redirect coverage into the cloned-skbs test
  (clone_redir_ext_write_after / clone_redir_ext_slice_write_after),
  queueing the clone on a netem-delayed loopback; enable
  CONFIG_NET_SCH_NETEM.
- selftests: Fix if_nametoindex() assertions to use ASSERT_GT(..., 0) so a
  lookup failure is not silently accepted as ifindex 0. (sashiko)
- selftests: Use int (not __be16) for get_socket_local_port() so a negative
  error is not truncated and masked. (sashiko)
- selftests: Validate send()/recv() return values and switch the sk_skb
  stream test to recv_timeout() to avoid a hang when the data path
  regresses. (Jack Wang, sashiko)
- selftests: Split the LWT test cleanup so bpf_tc_hook_destroy() does not
  delete the base-namespace clsact qdisc on the error path. (sashiko)
- selftests: Unify multi-line function comments to the "/*" on its own line
  style. (sashiko)
- Link to v1: https://patch.msgid.link/20260814-bpf-meta-inside-skb-ext-v1-0-767edd862656@cloudflare.com

Changes in v1:
- Don't scrub BPF skb extension. Remove F_NO_SCRUB flag. (Stan)
- Allow calling bpf_dynptr_from_skb_ext from NETFILTER, LWT_*, SK_SKB progs.
- Reorg tests into smaller commits. Add missing coverage.
- Link to RFC: https://patch.msgid.link/20260714-bpf-meta-inside-skb-ext-v1-0-5871c07a8dd6@cloudflare.com

---
Jakub Sitnicki (14):
      bpf: Introduce per-packet metadata storage for BPF programs
      bpf: Allow access to bpf_sock_ops_kern->skb
      bpf: Make BPF skb extension survive packet scrubbing
      selftests/bpf: Add tests for bpf_dynptr_from_skb_ext
      selftests/bpf: Test skb_ext on cloned skbs
      selftests/bpf: Test skb_ext survival across veth and GRE
      selftests/bpf: Test skb_ext read from cgroup_skb and sk_filter hooks
      selftests/bpf: Test skb_ext read from sock_ops and LSM hooks
      selftests/bpf: Test skb_ext read from kfree_skb tracepoint
      selftests/bpf: Test skb_ext read from netfilter hook
      selftests/bpf: Test skb_ext from LWT in, out, and xmit hooks
      selftests/bpf: Test skb_ext read from seg6local End.BPF hook
      selftests/bpf: Test skb_ext read from sk_skb stream verdict hook
      selftests/bpf: Use non-trivial test payload in xdp_context tests

 include/linux/bpf.h                                |   10 +
 include/linux/filter.h                             |   27 +
 include/linux/skbuff.h                             |   13 +
 include/uapi/linux/bpf.h                           |    5 +
 kernel/bpf/helpers.c                               |   21 +-
 kernel/bpf/log.c                                   |    2 +
 kernel/bpf/verifier.c                              |   25 +-
 net/Kconfig                                        |   20 +
 net/core/filter.c                                  |  149 +++
 net/core/skbuff.c                                  |   27 +-
 net/ipv4/udp.c                                     |    6 +-
 tools/testing/selftests/bpf/config                 |    2 +
 .../selftests/bpf/prog_tests/socket_helpers.h      |    1 +
 tools/testing/selftests/bpf/prog_tests/verifier.c  |    2 +
 .../bpf/prog_tests/xdp_context_test_run.c          | 1117 +++++++++++++++++++-
 tools/testing/selftests/bpf/progs/test_xdp_meta.c  |  569 +++++++++-
 .../testing/selftests/bpf/progs/verifier_skb_ext.c |  122 +++
 17 files changed, 2094 insertions(+), 24 deletions(-)
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help