selftests/bpf: xdp_metadata: Check XDP_REDIRCT support for dev-bound progs
authorLorenzo Bianconi <lorenzo@kernel.org>
Mon, 28 Apr 2025 15:44:03 +0000 (17:44 +0200)
committerMartin KaFai Lau <martin.lau@kernel.org>
Thu, 1 May 2025 19:54:06 +0000 (12:54 -0700)
Improve xdp_metadata bpf selftest in order to check it is possible for a
XDP dev-bound program to perform XDP_REDIRECT into a DEVMAP but it is still
not allowed to attach a XDP dev-bound program to a DEVMAP entry.

Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Acked-by: Stanislav Fomichev <sdf@fomichev.me>
tools/testing/selftests/bpf/prog_tests/xdp_metadata.c
tools/testing/selftests/bpf/progs/xdp_metadata.c

index 3d47878..19f92af 100644 (file)
@@ -351,9 +351,10 @@ void test_xdp_metadata(void)
        struct xdp_metadata2 *bpf_obj2 = NULL;
        struct xdp_metadata *bpf_obj = NULL;
        struct bpf_program *new_prog, *prog;
+       struct bpf_devmap_val devmap_e = {};
+       struct bpf_map *prog_arr, *devmap;
        struct nstoken *tok = NULL;
        __u32 queue_id = QUEUE_ID;
-       struct bpf_map *prog_arr;
        struct xsk tx_xsk = {};
        struct xsk rx_xsk = {};
        __u32 val, key = 0;
@@ -409,6 +410,13 @@ void test_xdp_metadata(void)
        bpf_program__set_ifindex(prog, rx_ifindex);
        bpf_program__set_flags(prog, BPF_F_XDP_DEV_BOUND_ONLY);
 
+       /* Make sure we can load a dev-bound program that performs
+        * XDP_REDIRECT into a devmap.
+        */
+       new_prog = bpf_object__find_program_by_name(bpf_obj->obj, "redirect");
+       bpf_program__set_ifindex(new_prog, rx_ifindex);
+       bpf_program__set_flags(new_prog, BPF_F_XDP_DEV_BOUND_ONLY);
+
        if (!ASSERT_OK(xdp_metadata__load(bpf_obj), "load skeleton"))
                goto out;
 
@@ -423,6 +431,18 @@ void test_xdp_metadata(void)
                        "update prog_arr"))
                goto out;
 
+       /* Make sure we can't add dev-bound programs to devmaps. */
+       devmap = bpf_object__find_map_by_name(bpf_obj->obj, "dev_map");
+       if (!ASSERT_OK_PTR(devmap, "no dev_map found"))
+               goto out;
+
+       devmap_e.bpf_prog.fd = val;
+       if (!ASSERT_ERR(bpf_map__update_elem(devmap, &key, sizeof(key),
+                                            &devmap_e, sizeof(devmap_e),
+                                            BPF_ANY),
+                       "update dev_map"))
+               goto out;
+
        /* Attach BPF program to RX interface. */
 
        ret = bpf_xdp_attach(rx_ifindex,
index 31ca229..09bb8a0 100644 (file)
@@ -19,6 +19,13 @@ struct {
        __type(value, __u32);
 } prog_arr SEC(".maps");
 
+struct {
+       __uint(type, BPF_MAP_TYPE_DEVMAP);
+       __uint(key_size, sizeof(__u32));
+       __uint(value_size, sizeof(struct bpf_devmap_val));
+       __uint(max_entries, 1);
+} dev_map SEC(".maps");
+
 extern int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx,
                                         __u64 *timestamp) __ksym;
 extern int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, __u32 *hash,
@@ -95,4 +102,10 @@ int rx(struct xdp_md *ctx)
        return bpf_redirect_map(&xsk, ctx->rx_queue_index, XDP_PASS);
 }
 
+SEC("xdp")
+int redirect(struct xdp_md *ctx)
+{
+       return bpf_redirect_map(&dev_map, ctx->rx_queue_index, XDP_PASS);
+}
+
 char _license[] SEC("license") = "GPL";