Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/linux/bpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ struct bpf_map_owner {
bool xdp_has_frags;
u64 storage_cookie[MAX_BPF_CGROUP_STORAGE_TYPE];
const struct btf_type *attach_func_proto;
enum bpf_attach_type expected_attach_type;
};

struct bpf_map {
Expand Down
4 changes: 3 additions & 1 deletion kernel/bpf/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2361,6 +2361,7 @@ static bool __bpf_prog_map_compatible(struct bpf_map *map,
map->owner->type = prog_type;
map->owner->jited = fp->jited;
map->owner->xdp_has_frags = aux->xdp_has_frags;
map->owner->expected_attach_type = fp->expected_attach_type;
map->owner->attach_func_proto = aux->attach_func_proto;
for_each_cgroup_storage_type(i) {
map->owner->storage_cookie[i] =
Expand All @@ -2371,7 +2372,8 @@ static bool __bpf_prog_map_compatible(struct bpf_map *map,
} else {
ret = map->owner->type == prog_type &&
map->owner->jited == fp->jited &&
map->owner->xdp_has_frags == aux->xdp_has_frags;
map->owner->xdp_has_frags == aux->xdp_has_frags &&
map->owner->expected_attach_type == fp->expected_attach_type;
for_each_cgroup_storage_type(i) {
if (!ret)
break;
Expand Down
31 changes: 30 additions & 1 deletion tools/testing/selftests/bpf/prog_tests/xdp_devmap_attach.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <test_progs.h>

#include "test_xdp_devmap_helpers.skel.h"
#include "test_xdp_devmap_tailcall.skel.h"
#include "test_xdp_with_devmap_frags_helpers.skel.h"
#include "test_xdp_with_devmap_helpers.skel.h"

Expand Down Expand Up @@ -107,6 +108,29 @@ static void test_neg_xdp_devmap_helpers(void)
}
}

static void test_xdp_devmap_tailcall(enum bpf_attach_type prog_dev,
enum bpf_attach_type prog_tail,
bool expect_reject)
{
struct test_xdp_devmap_tailcall *skel;
int err;

skel = test_xdp_devmap_tailcall__open();
if (!ASSERT_OK_PTR(skel, "test_xdp_devmap_tailcall__open"))
return;

bpf_program__set_expected_attach_type(skel->progs.xdp_devmap, prog_dev);
bpf_program__set_expected_attach_type(skel->progs.xdp_entry, prog_tail);

err = test_xdp_devmap_tailcall__load(skel);
if (expect_reject)
ASSERT_ERR(err, "test_xdp_devmap_tailcall__load");
else
ASSERT_OK(err, "test_xdp_devmap_tailcall__load");

test_xdp_devmap_tailcall__destroy(skel);
}

static void test_xdp_with_devmap_frags_helpers(void)
{
struct test_xdp_with_devmap_frags_helpers *skel;
Expand Down Expand Up @@ -238,8 +262,13 @@ void serial_test_xdp_devmap_attach(void)
if (test__start_subtest("DEVMAP with frags programs in entries"))
test_xdp_with_devmap_frags_helpers();

if (test__start_subtest("Verifier check of DEVMAP programs"))
if (test__start_subtest("Verifier check of DEVMAP programs")) {
test_neg_xdp_devmap_helpers();
test_xdp_devmap_tailcall(BPF_XDP_DEVMAP, BPF_XDP_DEVMAP, false);
test_xdp_devmap_tailcall(0, 0, true);
test_xdp_devmap_tailcall(BPF_XDP_DEVMAP, 0, true);
test_xdp_devmap_tailcall(0, BPF_XDP_DEVMAP, true);
}

if (test__start_subtest("DEVMAP with programs in entries on veth"))
test_xdp_with_devmap_helpers_veth();
Expand Down
29 changes: 29 additions & 0 deletions tools/testing/selftests/bpf/progs/test_xdp_devmap_tailcall.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: GPL-2.0

#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>

SEC("xdp")
int xdp_devmap(struct xdp_md *ctx)
{
return ctx->egress_ifindex;
}

struct {
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
__uint(max_entries, 1);
__uint(key_size, sizeof(__u32));
__array(values, int (void *));
} xdp_map SEC(".maps") = {
.values = {
[0] = (void *)&xdp_devmap,
},
};

SEC("xdp")
int xdp_entry(struct xdp_md *ctx)
{
bpf_tail_call(ctx, &xdp_map, 0);
return 0;
}
Loading