From: Jakub Sitnicki <jakub@cloudflare.com>
To: bpf@vger.kernel.org
Cc: "David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
Martin KaFai Lau <martin.lau@linux.dev>,
Daniel Borkmann <daniel@iogearbox.net>,
John Fastabend <john.fastabend@gmail.com>,
Stanislav Fomichev <sdf@fomichev.me>,
Alexei Starovoitov <ast@kernel.org>,
Andrii Nakryiko <andrii@kernel.org>,
Eduard Zingerman <eddyz87@gmail.com>, Song Liu <song@kernel.org>,
Yonghong Song <yonghong.song@linux.dev>,
KP Singh <kpsingh@kernel.org>, Hao Luo <haoluo@google.com>,
Jiri Olsa <jolsa@kernel.org>,
Arthur Fabre <arthur@arthurfabre.com>,
Jesper Dangaard Brouer <hawk@kernel.org>,
netdev@vger.kernel.org, kernel-team@cloudflare.com
Subject: [PATCH bpf-next v4 14/16] selftests/bpf: Cover skb metadata access after bpf_skb_adjust_room
Date: Wed, 05 Nov 2025 21:19:51 +0100 [thread overview]
Message-ID: <20251105-skb-meta-rx-path-v4-14-5ceb08a9b37b@cloudflare.com> (raw)
In-Reply-To: <20251105-skb-meta-rx-path-v4-0-5ceb08a9b37b@cloudflare.com>
Add a test to verify that skb metadata remains accessible after calling
bpf_skb_adjust_room(), which modifies the packet headroom and can trigger
head reallocation.
The helper expects an Ethernet frame carrying an IP packet so switch test
packet identification by source MAC address since we can no longer rely on
Ethernet proto being set to zero.
Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com>
---
.../bpf/prog_tests/xdp_context_test_run.c | 25 ++++++---
tools/testing/selftests/bpf/progs/test_xdp_meta.c | 61 ++++++++++++++++++----
2 files changed, 71 insertions(+), 15 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c b/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c
index 97c8f876f673..a3b82cf2f9e9 100644
--- a/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c
@@ -124,10 +124,10 @@ static int send_test_packet(int ifindex)
int n, sock = -1;
__u8 packet[sizeof(struct ethhdr) + TEST_PAYLOAD_LEN];
- /* The ethernet header is not relevant for this test and doesn't need to
- * be meaningful.
- */
- struct ethhdr eth = { 0 };
+ /* We use the Ethernet header only to identify the test packet */
+ struct ethhdr eth = {
+ .h_source = { 0x12, 0x34, 0xDE, 0xAD, 0xBE, 0xEF },
+ };
memcpy(packet, ð, sizeof(eth));
memcpy(packet + sizeof(eth), test_payload, TEST_PAYLOAD_LEN);
@@ -160,8 +160,16 @@ static int write_test_packet(int tap_fd)
__u8 packet[sizeof(struct ethhdr) + TEST_PAYLOAD_LEN];
int n;
- /* The ethernet header doesn't need to be valid for this test */
- memset(packet, 0, sizeof(struct ethhdr));
+ /* The Ethernet header is mostly not relevant. We use it to identify the
+ * test packet and some BPF helpers we exercise expect to operate on
+ * Ethernet frames carrying IP packets. Pretend that's the case.
+ */
+ struct ethhdr eth = {
+ .h_source = { 0x12, 0x34, 0xDE, 0xAD, 0xBE, 0xEF },
+ .h_proto = htons(ETH_P_IP),
+ };
+
+ memcpy(packet, ð, sizeof(eth));
memcpy(packet + sizeof(struct ethhdr), test_payload, TEST_PAYLOAD_LEN);
n = write(tap_fd, packet, sizeof(packet));
@@ -484,6 +492,11 @@ void test_xdp_context_tuntap(void)
skel->progs.helper_skb_vlan_push_pop,
NULL, /* tc prio 2 */
&skel->bss->test_pass);
+ if (test__start_subtest("helper_skb_adjust_room"))
+ test_tuntap(skel->progs.ing_xdp,
+ skel->progs.helper_skb_adjust_room,
+ NULL, /* tc prio 2 */
+ &skel->bss->test_pass);
test_xdp_meta__destroy(skel);
}
diff --git a/tools/testing/selftests/bpf/progs/test_xdp_meta.c b/tools/testing/selftests/bpf/progs/test_xdp_meta.c
index 04c7487bb350..6edc84d8dc52 100644
--- a/tools/testing/selftests/bpf/progs/test_xdp_meta.c
+++ b/tools/testing/selftests/bpf/progs/test_xdp_meta.c
@@ -20,6 +20,10 @@
bool test_pass;
+static const __u8 smac_want[ETH_ALEN] = {
+ 0x12, 0x34, 0xDE, 0xAD, 0xBE, 0xEF,
+};
+
static const __u8 meta_want[META_SIZE] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
@@ -27,6 +31,11 @@ static const __u8 meta_want[META_SIZE] = {
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
};
+static bool check_smac(const struct ethhdr *eth)
+{
+ return !__builtin_memcmp(eth->h_source, smac_want, ETH_ALEN);
+}
+
static bool check_metadata(const char *file, int line, __u8 *meta_have)
{
if (!__builtin_memcmp(meta_have, meta_want, META_SIZE))
@@ -281,7 +290,7 @@ int ing_xdp_zalloc_meta(struct xdp_md *ctx)
/* Drop any non-test packets */
if (eth + 1 > ctx_ptr(ctx, data_end))
return XDP_DROP;
- if (eth->h_proto != 0)
+ if (!check_smac(eth))
return XDP_DROP;
ret = bpf_xdp_adjust_meta(ctx, -META_SIZE);
@@ -321,9 +330,9 @@ int ing_xdp(struct xdp_md *ctx)
/* The Linux networking stack may send other packets on the test
* interface that interfere with the test. Just drop them.
- * The test packets can be recognized by their ethertype of zero.
+ * The test packets can be recognized by their source MAC address.
*/
- if (eth->h_proto != 0)
+ if (!check_smac(eth))
return XDP_DROP;
__builtin_memcpy(data_meta, payload, META_SIZE);
@@ -343,7 +352,7 @@ int clone_data_meta_survives_data_write(struct __sk_buff *ctx)
if (eth + 1 > ctx_ptr(ctx, data_end))
goto out;
/* Ignore non-test packets */
- if (eth->h_proto != 0)
+ if (!check_smac(eth))
goto out;
if (meta_have + META_SIZE > eth)
@@ -373,7 +382,7 @@ int clone_data_meta_survives_meta_write(struct __sk_buff *ctx)
if (eth + 1 > ctx_ptr(ctx, data_end))
goto out;
/* Ignore non-test packets */
- if (eth->h_proto != 0)
+ if (!check_smac(eth))
goto out;
if (meta_have + META_SIZE > eth)
@@ -406,7 +415,7 @@ int clone_meta_dynptr_survives_data_slice_write(struct __sk_buff *ctx)
if (!eth)
goto out;
/* Ignore non-test packets */
- if (eth->h_proto != 0)
+ if (!check_smac(eth))
goto out;
bpf_dynptr_from_skb_meta(ctx, 0, &meta);
@@ -435,7 +444,7 @@ int clone_meta_dynptr_survives_meta_slice_write(struct __sk_buff *ctx)
if (!eth)
goto out;
/* Ignore non-test packets */
- if (eth->h_proto != 0)
+ if (!check_smac(eth))
goto out;
bpf_dynptr_from_skb_meta(ctx, 0, &meta);
@@ -469,7 +478,7 @@ int clone_meta_dynptr_rw_before_data_dynptr_write(struct __sk_buff *ctx)
if (!eth)
goto out;
/* Ignore non-test packets */
- if (eth->h_proto != 0)
+ if (!check_smac(eth))
goto out;
/* Expect read-write metadata before unclone */
@@ -511,7 +520,7 @@ int clone_meta_dynptr_rw_before_meta_dynptr_write(struct __sk_buff *ctx)
if (!eth)
goto out;
/* Ignore non-test packets */
- if (eth->h_proto != 0)
+ if (!check_smac(eth))
goto out;
/* Expect read-write metadata before unclone */
@@ -568,4 +577,38 @@ int helper_skb_vlan_push_pop(struct __sk_buff *ctx)
return TC_ACT_SHOT;
}
+SEC("tc")
+int helper_skb_adjust_room(struct __sk_buff *ctx)
+{
+ int err;
+
+ /* Grow a 1 byte hole after the MAC header */
+ err = bpf_skb_adjust_room(ctx, 1, BPF_ADJ_ROOM_MAC, 0);
+ if (err)
+ goto out;
+
+ if (!check_skb_metadata(ctx))
+ goto out;
+
+ /* Shrink a 1 byte hole after the MAC header */
+ err = bpf_skb_adjust_room(ctx, -1, BPF_ADJ_ROOM_MAC, 0);
+ if (err)
+ goto out;
+
+ if (!check_skb_metadata(ctx))
+ goto out;
+
+ /* Grow a 256 byte hole to trigger head reallocation */
+ err = bpf_skb_adjust_room(ctx, 256, BPF_ADJ_ROOM_MAC, 0);
+ if (err)
+ goto out;
+
+ if (!check_skb_metadata(ctx))
+ goto out;
+
+ test_pass = true;
+out:
+ return TC_ACT_SHOT;
+}
+
char _license[] SEC("license") = "GPL";
--
2.43.0
next prev parent reply other threads:[~2025-11-05 20:20 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-05 20:19 [PATCH bpf-next v4 00/16] Make TC BPF helpers preserve skb metadata Jakub Sitnicki
2025-11-05 20:19 ` [PATCH bpf-next v4 01/16] net: Helper to move packet data and metadata after skb_push/pull Jakub Sitnicki
2025-11-05 20:19 ` [PATCH bpf-next v4 02/16] net: Preserve metadata on pskb_expand_head Jakub Sitnicki
2025-11-05 20:19 ` [PATCH bpf-next v4 03/16] bpf: Unclone skb head on bpf_dynptr_write to skb metadata Jakub Sitnicki
2025-11-05 20:19 ` [PATCH bpf-next v4 04/16] vlan: Make vlan_remove_tag return nothing Jakub Sitnicki
2025-11-05 20:19 ` [PATCH bpf-next v4 05/16] bpf: Make bpf_skb_vlan_pop helper metadata-safe Jakub Sitnicki
2025-11-05 20:19 ` [PATCH bpf-next v4 06/16] bpf: Make bpf_skb_vlan_push " Jakub Sitnicki
2025-11-05 20:19 ` [PATCH bpf-next v4 07/16] bpf: Make bpf_skb_adjust_room metadata-safe Jakub Sitnicki
2025-11-05 20:42 ` bot+bpf-ci
2025-11-10 12:17 ` Jakub Sitnicki
2025-11-05 20:19 ` [PATCH bpf-next v4 08/16] bpf: Make bpf_skb_change_proto helper metadata-safe Jakub Sitnicki
2025-11-05 20:19 ` [PATCH bpf-next v4 09/16] bpf: Make bpf_skb_change_head " Jakub Sitnicki
2025-11-05 20:19 ` [PATCH bpf-next v4 10/16] selftests/bpf: Verify skb metadata in BPF instead of userspace Jakub Sitnicki
2025-11-05 20:19 ` [PATCH bpf-next v4 11/16] selftests/bpf: Dump skb metadata on verification failure Jakub Sitnicki
2025-11-05 20:19 ` [PATCH bpf-next v4 12/16] selftests/bpf: Expect unclone to preserve skb metadata Jakub Sitnicki
2025-11-05 20:19 ` [PATCH bpf-next v4 13/16] selftests/bpf: Cover skb metadata access after vlan push/pop helper Jakub Sitnicki
2025-11-05 20:19 ` Jakub Sitnicki [this message]
2025-11-05 20:19 ` [PATCH bpf-next v4 15/16] selftests/bpf: Cover skb metadata access after change_head/tail helper Jakub Sitnicki
2025-11-05 20:19 ` [PATCH bpf-next v4 16/16] selftests/bpf: Cover skb metadata access after bpf_skb_change_proto Jakub Sitnicki
2025-11-10 19:30 ` [PATCH bpf-next v4 00/16] Make TC BPF helpers preserve skb metadata patchwork-bot+netdevbpf
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=20251105-skb-meta-rx-path-v4-14-5ceb08a9b37b@cloudflare.com \
--to=jakub@cloudflare.com \
--cc=andrii@kernel.org \
--cc=arthur@arthurfabre.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=eddyz87@gmail.com \
--cc=edumazet@google.com \
--cc=haoluo@google.com \
--cc=hawk@kernel.org \
--cc=horms@kernel.org \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=kernel-team@cloudflare.com \
--cc=kpsingh@kernel.org \
--cc=kuba@kernel.org \
--cc=martin.lau@linux.dev \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=sdf@fomichev.me \
--cc=song@kernel.org \
--cc=yonghong.song@linux.dev \
/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;
as well as URLs for NNTP newsgroup(s).