]> www.infradead.org Git - linux.git/commitdiff
selftests/bpf: Cover read access to skb metadata via dynptr
authorJakub Sitnicki <jakub@cloudflare.com>
Thu, 14 Aug 2025 09:59:32 +0000 (11:59 +0200)
committerMartin KaFai Lau <martin.lau@kernel.org>
Mon, 18 Aug 2025 17:29:42 +0000 (10:29 -0700)
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: Jakub Sitnicki <jakub@cloudflare.com>
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Reviewed-by: Jesse Brandeburg <jbrandeburg@cloudflare.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://patch.msgid.link/20250814-skb-metadata-thru-dynptr-v7-6-8a39e636e0fb@cloudflare.com
tools/testing/selftests/bpf/bpf_kfuncs.h
tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c
tools/testing/selftests/bpf/progs/test_xdp_meta.c

index 9386dfe8b8849edf797d1adda60eac8f4d2f246f..794d44d19c8865c6e6481efb7ee8cc277adad1c2 100644 (file)
@@ -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
index 6c66e27e5bc74af6950cd1226c8be9901939898d..7e4526461a4cb6ad6a39ac99dc4f2096c156c075 100644 (file)
@@ -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);
 }
index fcf6ca14f2ea285bc360af6239b8b9b45e8705f4..0ba647fb1b1d7be7871288d1edd7d58d0b81cd45 100644 (file)
@@ -1,8 +1,10 @@
+#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)
 {