Skip to content

Commit

Permalink
selftests/bpf: Add a test for using a cpumap from an freplace-to-XDP …
Browse files Browse the repository at this point in the history
…program

This adds a simple test for inserting an XDP program into a cpumap that is
"owned" by an XDP program that was loaded as PROG_TYPE_EXT (as libxdp
does). Prior to the kernel fix this would fail because the map type
ownership would be set to PROG_TYPE_EXT instead of being resolved to
PROG_TYPE_XDP.

v4:
- Use skeletons for selftest
v3:
- Update comment to better explain the cause
- Add Yonghong's ACK

Acked-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
  • Loading branch information
tohojo authored and Kernel Patches Daemon committed Dec 14, 2022
1 parent 10188a0 commit d95b49e
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
54 changes: 54 additions & 0 deletions tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
Expand Up @@ -4,6 +4,8 @@
#include <network_helpers.h>
#include <bpf/btf.h>
#include "bind4_prog.skel.h"
#include "freplace_progmap.skel.h"
#include "xdp_dummy.skel.h"

typedef int (*test_cb)(struct bpf_object *obj);

Expand Down Expand Up @@ -500,6 +502,56 @@ static void test_fentry_to_cgroup_bpf(void)
bind4_prog__destroy(skel);
}

static void test_func_replace_progmap(void)
{
struct bpf_cpumap_val value = { .qsize = 1 };
struct freplace_progmap *skel = NULL;
struct xdp_dummy *tgt_skel = NULL;
int err, tgt_fd;
__u32 key = 0;

skel = freplace_progmap__open();
if (!ASSERT_OK_PTR(skel, "prog_open"))
return;

tgt_skel = xdp_dummy__open_and_load();
if (!ASSERT_OK_PTR(tgt_skel, "tgt_prog_load"))
goto out;

tgt_fd = bpf_program__fd(tgt_skel->progs.xdp_dummy_prog);

/* Change the 'redirect' program type to be a PROG_TYPE_EXT
* with an XDP target
*/
bpf_program__set_type(skel->progs.xdp_cpumap_prog, BPF_PROG_TYPE_EXT);
bpf_program__set_expected_attach_type(skel->progs.xdp_cpumap_prog, 0);
err = bpf_program__set_attach_target(skel->progs.xdp_cpumap_prog,
tgt_fd, "xdp_dummy_prog");
if (!ASSERT_OK(err, "set_attach_target"))
goto out;

err = freplace_progmap__load(skel);
if (!ASSERT_OK(err, "obj_load"))
goto out;

/* Prior to fixing the kernel, loading the PROG_TYPE_EXT 'redirect'
* program above will cause the map owner type of 'cpumap' to be set to
* PROG_TYPE_EXT. This in turn will cause the bpf_map_update_elem()
* below to fail, because the program we are inserting into the map is
* of PROG_TYPE_XDP. After fixing the kernel, the initial ownership will
* be correctly resolved to the *target* of the PROG_TYPE_EXT program
* (i.e., PROG_TYPE_XDP) and the map update will succeed.
*/
value.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_drop_prog);
err = bpf_map_update_elem(bpf_map__fd(skel->maps.cpu_map),
&key, &value, 0);
ASSERT_OK(err, "map_update");

out:
xdp_dummy__destroy(tgt_skel);
freplace_progmap__destroy(skel);
}

/* NOTE: affect other tests, must run in serial mode */
void serial_test_fexit_bpf2bpf(void)
{
Expand All @@ -525,4 +577,6 @@ void serial_test_fexit_bpf2bpf(void)
test_func_replace_global_func();
if (test__start_subtest("fentry_to_cgroup_bpf"))
test_fentry_to_cgroup_bpf();
if (test__start_subtest("func_replace_progmap"))
test_func_replace_progmap();
}
24 changes: 24 additions & 0 deletions tools/testing/selftests/bpf/progs/freplace_progmap.c
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>

struct {
__uint(type, BPF_MAP_TYPE_CPUMAP);
__uint(key_size, sizeof(__u32));
__uint(value_size, sizeof(struct bpf_cpumap_val));
__uint(max_entries, 1);
} cpu_map SEC(".maps");

SEC("xdp/cpumap")
int xdp_drop_prog(struct xdp_md *ctx)
{
return XDP_DROP;
}

SEC("xdp")
int xdp_cpumap_prog(struct xdp_md *ctx)
{
return bpf_redirect_map(&cpu_map, 0, XDP_PASS);
}

char _license[] SEC("license") = "GPL";

0 comments on commit d95b49e

Please sign in to comment.