Merge branch 'libbpf: Support uniform BTF-defined key/value specification across all BPF maps'
Hengqi Chen says: ==================== Currently a bunch of (usually pretty specialized) BPF maps do not support specifying BTF types for they key and value. For such maps, specifying their definition like this: struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); __type(key, int); __type(value, int); } my_perf_buf SEC(".maps"); Would actually produce warnings about retrying BPF map creation without BTF. Users are forced to know such nuances and use __uint(key_size, 4) instead. This is non-uniform, annoying, and inconvenient. This patch set teaches libbpf to recognize those specialized maps and removes BTF type IDs when creating BPF map. Also, update existing BPF selftests to exericse this change. ==================== Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
This commit is contained in:
@ -4669,6 +4669,30 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, b
|
||||
create_attr.inner_map_fd = map->inner_map_fd;
|
||||
}
|
||||
|
||||
switch (def->type) {
|
||||
case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
|
||||
case BPF_MAP_TYPE_CGROUP_ARRAY:
|
||||
case BPF_MAP_TYPE_STACK_TRACE:
|
||||
case BPF_MAP_TYPE_ARRAY_OF_MAPS:
|
||||
case BPF_MAP_TYPE_HASH_OF_MAPS:
|
||||
case BPF_MAP_TYPE_DEVMAP:
|
||||
case BPF_MAP_TYPE_DEVMAP_HASH:
|
||||
case BPF_MAP_TYPE_CPUMAP:
|
||||
case BPF_MAP_TYPE_XSKMAP:
|
||||
case BPF_MAP_TYPE_SOCKMAP:
|
||||
case BPF_MAP_TYPE_SOCKHASH:
|
||||
case BPF_MAP_TYPE_QUEUE:
|
||||
case BPF_MAP_TYPE_STACK:
|
||||
case BPF_MAP_TYPE_RINGBUF:
|
||||
create_attr.btf_fd = 0;
|
||||
create_attr.btf_key_type_id = 0;
|
||||
create_attr.btf_value_type_id = 0;
|
||||
map->btf_key_type_id = 0;
|
||||
map->btf_value_type_id = 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (obj->gen_loader) {
|
||||
bpf_gen__map_create(obj->gen_loader, &create_attr, is_inner ? -1 : map - obj->maps);
|
||||
/* Pretend to have valid FD to pass various fd >= 0 checks.
|
||||
|
@ -9,8 +9,8 @@
|
||||
char _license[] SEC("license") = "GPL";
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, sizeof(int));
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
} perf_buf_map SEC(".maps");
|
||||
|
||||
#define _(P) (__builtin_preserve_access_index(P))
|
||||
|
@ -11,8 +11,8 @@ typedef __u64 stack_trace_t[PERF_MAX_STACK_DEPTH];
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_STACK_TRACE);
|
||||
__uint(max_entries, 16384);
|
||||
__uint(key_size, sizeof(__u32));
|
||||
__uint(value_size, sizeof(stack_trace_t));
|
||||
__type(key, __u32);
|
||||
__type(value, stack_trace_t);
|
||||
} stackmap SEC(".maps");
|
||||
|
||||
struct {
|
||||
|
@ -7,22 +7,22 @@ int _version SEC("version") = 1;
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_SOCKMAP);
|
||||
__uint(max_entries, 20);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, sizeof(int));
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
} sock_map_rx SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_SOCKMAP);
|
||||
__uint(max_entries, 20);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, sizeof(int));
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
} sock_map_tx SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_SOCKMAP);
|
||||
__uint(max_entries, 20);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, sizeof(int));
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
} sock_map_msg SEC(".maps");
|
||||
|
||||
struct {
|
||||
|
@ -21,8 +21,8 @@ struct inner_map_sz2 {
|
||||
struct outer_arr {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
|
||||
__uint(max_entries, 3);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, sizeof(int));
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
/* it's possible to use anonymous struct as inner map definition here */
|
||||
__array(values, struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
@ -61,8 +61,8 @@ struct inner_map_sz4 {
|
||||
struct outer_arr_dyn {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
|
||||
__uint(max_entries, 3);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, sizeof(int));
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
__array(values, struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY);
|
||||
__uint(map_flags, BPF_F_INNER_MAP);
|
||||
@ -81,7 +81,7 @@ struct outer_arr_dyn {
|
||||
struct outer_hash {
|
||||
__uint(type, BPF_MAP_TYPE_HASH_OF_MAPS);
|
||||
__uint(max_entries, 5);
|
||||
__uint(key_size, sizeof(int));
|
||||
__type(key, int);
|
||||
/* Here everything works flawlessly due to reuse of struct inner_map
|
||||
* and compiler will complain at the attempt to use non-inner_map
|
||||
* references below. This is great experience.
|
||||
@ -111,8 +111,8 @@ struct sockarr_sz2 {
|
||||
struct outer_sockarr_sz1 {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
|
||||
__uint(max_entries, 1);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, sizeof(int));
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
__array(values, struct sockarr_sz1);
|
||||
} outer_sockarr SEC(".maps") = {
|
||||
.values = { (void *)&sockarr_sz1 },
|
||||
|
@ -9,18 +9,16 @@ struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
|
||||
__uint(max_entries, 1);
|
||||
__uint(map_flags, 0);
|
||||
__uint(key_size, sizeof(__u32));
|
||||
/* must be sizeof(__u32) for map in map */
|
||||
__uint(value_size, sizeof(__u32));
|
||||
__type(key, __u32);
|
||||
__type(value, __u32);
|
||||
} mim_array SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH_OF_MAPS);
|
||||
__uint(max_entries, 1);
|
||||
__uint(map_flags, 0);
|
||||
__uint(key_size, sizeof(int));
|
||||
/* must be sizeof(__u32) for map in map */
|
||||
__uint(value_size, sizeof(__u32));
|
||||
__type(key, int);
|
||||
__type(value, __u32);
|
||||
} mim_hash SEC(".maps");
|
||||
|
||||
SEC("xdp")
|
||||
|
@ -13,7 +13,7 @@ struct inner {
|
||||
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));
|
||||
__type(key, __u32);
|
||||
__array(values, struct inner);
|
||||
} mim SEC(".maps");
|
||||
|
||||
|
@ -7,15 +7,15 @@
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
|
||||
__uint(max_entries, 1);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, sizeof(int));
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
} array_1 SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
|
||||
__uint(max_entries, 1);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, sizeof(int));
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
__uint(map_flags, BPF_F_PRESERVE_ELEMS);
|
||||
} array_2 SEC(".maps");
|
||||
|
||||
|
@ -8,8 +8,8 @@
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, sizeof(int));
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
} perf_buf_map SEC(".maps");
|
||||
|
||||
SEC("tp/raw_syscalls/sys_enter")
|
||||
|
@ -24,8 +24,8 @@ int _version SEC("version") = 1;
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
|
||||
__uint(max_entries, 1);
|
||||
__uint(key_size, sizeof(__u32));
|
||||
__uint(value_size, sizeof(__u32));
|
||||
__type(key, __u32);
|
||||
__type(value, __u32);
|
||||
} outer_map SEC(".maps");
|
||||
|
||||
struct {
|
||||
|
@ -28,8 +28,8 @@ struct {
|
||||
__uint(type, BPF_MAP_TYPE_STACK_TRACE);
|
||||
__uint(max_entries, 128);
|
||||
__uint(map_flags, BPF_F_STACK_BUILD_ID);
|
||||
__uint(key_size, sizeof(__u32));
|
||||
__uint(value_size, sizeof(stack_trace_t));
|
||||
__type(key, __u32);
|
||||
__type(value, stack_trace_t);
|
||||
} stackmap SEC(".maps");
|
||||
|
||||
struct {
|
||||
|
@ -27,8 +27,8 @@ typedef __u64 stack_trace_t[PERF_MAX_STACK_DEPTH];
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_STACK_TRACE);
|
||||
__uint(max_entries, 16384);
|
||||
__uint(key_size, sizeof(__u32));
|
||||
__uint(value_size, sizeof(stack_trace_t));
|
||||
__type(key, __u32);
|
||||
__type(value, stack_trace_t);
|
||||
} stackmap SEC(".maps");
|
||||
|
||||
struct {
|
||||
|
@ -24,8 +24,8 @@ struct {
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
|
||||
__uint(max_entries, 2);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, sizeof(__u32));
|
||||
__type(key, int);
|
||||
__type(value, __u32);
|
||||
} perf_event_map SEC(".maps");
|
||||
|
||||
int _version SEC("version") = 1;
|
||||
|
@ -36,8 +36,8 @@ struct meta {
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
|
||||
__uint(key_size, sizeof(int));
|
||||
__uint(value_size, sizeof(int));
|
||||
__type(key, int);
|
||||
__type(value, int);
|
||||
} perf_buf_map SEC(".maps");
|
||||
|
||||
__u64 test_result_fentry = 0;
|
||||
|
Reference in New Issue
Block a user