mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-05-21 00:22:33 +00:00
selftests/bpf: Check inner map deletion
Add a test case to check whether an unsuccessful creation of an outer map of a BTF-defined map-in-map destroys the inner map. As bpf_object__create_map() is a static function, we cannot just call it from the test case and then check whether a map accessible via map->inner_map_fd has been closed. Instead, we iterate over all maps and check whether the map "$MAP_NAME.inner" does not exist. Signed-off-by: Martynas Pumputis <m@lambda.lt> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Acked-by: John Fastabend <john.fastabend@gmail.com> Link: https://lore.kernel.org/bpf/20210719173838.423148-3-m@lambda.lt
This commit is contained in:
parent
a21ab4c59e
commit
08f71a1e39
2 changed files with 88 additions and 1 deletions
26
tools/testing/selftests/bpf/progs/test_map_in_map_invalid.c
Normal file
26
tools/testing/selftests/bpf/progs/test_map_in_map_invalid.c
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/* Copyright (c) 2021 Isovalent, Inc. */
|
||||||
|
#include <linux/bpf.h>
|
||||||
|
#include <bpf/bpf_helpers.h>
|
||||||
|
|
||||||
|
struct inner {
|
||||||
|
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||||
|
__type(key, __u32);
|
||||||
|
__type(value, int);
|
||||||
|
__uint(max_entries, 4);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
|
||||||
|
__uint(max_entries, 0); /* This will make map creation to fail */
|
||||||
|
__uint(key_size, sizeof(__u32));
|
||||||
|
__array(values, struct inner);
|
||||||
|
} mim SEC(".maps");
|
||||||
|
|
||||||
|
SEC("xdp")
|
||||||
|
int xdp_noop0(struct xdp_md *ctx)
|
||||||
|
{
|
||||||
|
return XDP_PASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
char _license[] SEC("license") = "GPL";
|
|
@ -1153,12 +1153,16 @@ out_sockmap:
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAPINMAP_PROG "./test_map_in_map.o"
|
#define MAPINMAP_PROG "./test_map_in_map.o"
|
||||||
|
#define MAPINMAP_INVALID_PROG "./test_map_in_map_invalid.o"
|
||||||
static void test_map_in_map(void)
|
static void test_map_in_map(void)
|
||||||
{
|
{
|
||||||
struct bpf_object *obj;
|
struct bpf_object *obj;
|
||||||
struct bpf_map *map;
|
struct bpf_map *map;
|
||||||
int mim_fd, fd, err;
|
int mim_fd, fd, err;
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
struct bpf_map_info info = {};
|
||||||
|
__u32 len = sizeof(info);
|
||||||
|
__u32 id = 0;
|
||||||
|
|
||||||
obj = bpf_object__open(MAPINMAP_PROG);
|
obj = bpf_object__open(MAPINMAP_PROG);
|
||||||
|
|
||||||
|
@ -1228,11 +1232,68 @@ static void test_map_in_map(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
bpf_object__close(obj);
|
bpf_object__close(obj);
|
||||||
|
|
||||||
|
/* Test that failing bpf_object__create_map() destroys the inner map */
|
||||||
|
obj = bpf_object__open(MAPINMAP_INVALID_PROG);
|
||||||
|
err = libbpf_get_error(obj);
|
||||||
|
if (err) {
|
||||||
|
printf("Failed to load %s program: %d %d",
|
||||||
|
MAPINMAP_INVALID_PROG, err, errno);
|
||||||
|
goto out_map_in_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
map = bpf_object__find_map_by_name(obj, "mim");
|
||||||
|
if (!map) {
|
||||||
|
printf("Failed to load array of maps from test prog\n");
|
||||||
|
goto out_map_in_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bpf_object__load(obj);
|
||||||
|
if (!err) {
|
||||||
|
printf("Loading obj supposed to fail\n");
|
||||||
|
goto out_map_in_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterate over all maps to check whether the internal map
|
||||||
|
* ("mim.internal") has been destroyed.
|
||||||
|
*/
|
||||||
|
while (true) {
|
||||||
|
err = bpf_map_get_next_id(id, &id);
|
||||||
|
if (err) {
|
||||||
|
if (errno == ENOENT)
|
||||||
|
break;
|
||||||
|
printf("Failed to get next map: %d", errno);
|
||||||
|
goto out_map_in_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = bpf_map_get_fd_by_id(id);
|
||||||
|
if (fd < 0) {
|
||||||
|
if (errno == ENOENT)
|
||||||
|
continue;
|
||||||
|
printf("Failed to get map by id %u: %d", id, errno);
|
||||||
|
goto out_map_in_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = bpf_obj_get_info_by_fd(fd, &info, &len);
|
||||||
|
if (err) {
|
||||||
|
printf("Failed to get map info by fd %d: %d", fd,
|
||||||
|
errno);
|
||||||
|
goto out_map_in_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(info.name, "mim.inner")) {
|
||||||
|
printf("Inner map mim.inner was not destroyed\n");
|
||||||
|
goto out_map_in_map;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
out_map_in_map:
|
out_map_in_map:
|
||||||
close(fd);
|
if (fd >= 0)
|
||||||
|
close(fd);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue