Commit 153f6bfd authored by Jakub Sitnicki's avatar Jakub Sitnicki Committed by Martin KaFai Lau
Browse files

selftests/bpf: Cover read access to skb metadata via dynptr



Exercise reading from SKB metadata area in two new ways:
1. indirectly, with bpf_dynptr_read(), and
2. directly, with bpf_dynptr_slice().

Signed-off-by: default avatarJakub Sitnicki <jakub@cloudflare.com>
Signed-off-by: default avatarMartin KaFai Lau <martin.lau@kernel.org>
Reviewed-by: default avatarJesse Brandeburg <jbrandeburg@cloudflare.com>
Acked-by: default avatarEduard Zingerman <eddyz87@gmail.com>
Link: https://patch.msgid.link/20250814-skb-metadata-thru-dynptr-v7-6-8a39e636e0fb@cloudflare.com
parent dd9f6cfb
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ extern int bpf_dynptr_from_skb(struct __sk_buff *skb, __u64 flags,
extern int bpf_dynptr_from_xdp(struct xdp_md *xdp, __u64 flags,
			       struct bpf_dynptr *ptr__uninit) __ksym __weak;

extern int bpf_dynptr_from_skb_meta(struct __sk_buff *skb, __u64 flags,
				    struct bpf_dynptr *ptr__uninit) __ksym __weak;

/* Description
 *  Obtain a read-only pointer to the dynptr's data
 * Returns
+21 −0
Original line number Diff line number Diff line
@@ -171,6 +171,18 @@ static void assert_test_result(const struct bpf_map *result_map)
		     "test_result map contains test payload");
}

static bool clear_test_result(struct bpf_map *result_map)
{
	const __u8 v[sizeof(test_payload)] = {};
	const __u32 k = 0;
	int err;

	err = bpf_map__update_elem(result_map, &k, sizeof(k), v, sizeof(v), BPF_ANY);
	ASSERT_OK(err, "update test_result");

	return err == 0;
}

void test_xdp_context_veth(void)
{
	LIBBPF_OPTS(bpf_tc_hook, tc_hook, .attach_point = BPF_TC_INGRESS);
@@ -268,6 +280,9 @@ static void test_tuntap(struct bpf_program *xdp_prog,
	int tap_ifindex;
	int ret;

	if (!clear_test_result(result_map))
		return;

	ns = netns_new(TAP_NETNS, true);
	if (!ASSERT_OK_PTR(ns, "create and open ns"))
		return;
@@ -328,6 +343,12 @@ void test_xdp_context_tuntap(void)
	if (test__start_subtest("data_meta"))
		test_tuntap(skel->progs.ing_xdp, skel->progs.ing_cls,
			    skel->maps.test_result);
	if (test__start_subtest("dynptr_read"))
		test_tuntap(skel->progs.ing_xdp, skel->progs.ing_cls_dynptr_read,
			    skel->maps.test_result);
	if (test__start_subtest("dynptr_slice"))
		test_tuntap(skel->progs.ing_xdp, skel->progs.ing_cls_dynptr_slice,
			    skel->maps.test_result);

	test_xdp_meta__destroy(skel);
}
+42 −0
Original line number Diff line number Diff line
#include <stdbool.h>
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/pkt_cls.h>

#include <bpf/bpf_helpers.h>
#include "bpf_kfuncs.h"

#define META_SIZE 32

@@ -40,6 +42,46 @@ int ing_cls(struct __sk_buff *ctx)
	return TC_ACT_SHOT;
}

/* Read from metadata using bpf_dynptr_read helper */
SEC("tc")
int ing_cls_dynptr_read(struct __sk_buff *ctx)
{
	struct bpf_dynptr meta;
	const __u32 zero = 0;
	__u8 *dst;

	dst = bpf_map_lookup_elem(&test_result, &zero);
	if (!dst)
		return TC_ACT_SHOT;

	bpf_dynptr_from_skb_meta(ctx, 0, &meta);
	bpf_dynptr_read(dst, META_SIZE, &meta, 0, 0);

	return TC_ACT_SHOT;
}

/* Read from metadata using read-only dynptr slice */
SEC("tc")
int ing_cls_dynptr_slice(struct __sk_buff *ctx)
{
	struct bpf_dynptr meta;
	const __u32 zero = 0;
	__u8 *dst, *src;

	dst = bpf_map_lookup_elem(&test_result, &zero);
	if (!dst)
		return TC_ACT_SHOT;

	bpf_dynptr_from_skb_meta(ctx, 0, &meta);
	src = bpf_dynptr_slice(&meta, 0, NULL, META_SIZE);
	if (!src)
		return TC_ACT_SHOT;

	__builtin_memcpy(dst, src, META_SIZE);

	return TC_ACT_SHOT;
}

SEC("xdp")
int ing_xdp(struct xdp_md *ctx)
{