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. ====================
Unified · Split
| @@ -4669,6 +4669,30 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, b · 4668 unmodified lines | ||
| 4669 | 4669 | create_attr.inner_map_fd = map->inner_map_fd; |
| 4670 | 4670 | } |
| 4671 | 4671 | |
| 4672 | + switch (def->type) { | |
| 4673 | + case BPF_MAP_TYPE_PERF_EVENT_ARRAY: | |
| 4674 | + case BPF_MAP_TYPE_CGROUP_ARRAY: | |
| 4675 | + case BPF_MAP_TYPE_STACK_TRACE: | |
| 4676 | + case BPF_MAP_TYPE_ARRAY_OF_MAPS: | |
| 4677 | + case BPF_MAP_TYPE_HASH_OF_MAPS: | |
| 4678 | + case BPF_MAP_TYPE_DEVMAP: | |
| 4679 | + case BPF_MAP_TYPE_DEVMAP_HASH: | |
| 4680 | + case BPF_MAP_TYPE_CPUMAP: | |
| 4681 | + case BPF_MAP_TYPE_XSKMAP: | |
| 4682 | + case BPF_MAP_TYPE_SOCKMAP: | |
| 4683 | + case BPF_MAP_TYPE_SOCKHASH: | |
| 4684 | + case BPF_MAP_TYPE_QUEUE: | |
| 4685 | + case BPF_MAP_TYPE_STACK: | |
| 4686 | + case BPF_MAP_TYPE_RINGBUF: | |
| 4687 | + create_attr.btf_fd = 0; | |
| 4688 | + create_attr.btf_key_type_id = 0; | |
| 4689 | + create_attr.btf_value_type_id = 0; | |
| 4690 | + map->btf_key_type_id = 0; | |
| 4691 | + map->btf_value_type_id = 0; | |
| 4692 | + default: | |
| 4693 | + break; | |
| 4694 | + } | |
| 4695 | + | |
| 4672 | 4696 | if (obj->gen_loader) { |
| 4673 | 4697 | bpf_gen__map_create(obj->gen_loader, &create_attr, is_inner ? -1 : map - obj->maps); |
| 4674 | 4698 | /* Pretend to have valid FD to pass various fd >= 0 checks. |
| @@ -9,8 +9,8 @@ · 8 unmodified lines | ||
| 9 | 9 | char _license[] SEC("license") = "GPL"; |
| 10 | 10 | struct { |
| 11 | 11 | __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); |
| 12 | − __uint(key_size, sizeof(int)); | |
| 13 | − __uint(value_size, sizeof(int)); | |
| 12 | + __type(key, int); | |
| 13 | + __type(value, int); | |
| 14 | 14 | } perf_buf_map SEC(".maps"); |
| 15 | 15 | |
| 16 | 16 | #define _(P) (__builtin_preserve_access_index(P)) |
| @@ -11,8 +11,8 @@ typedef __u64 stack_trace_t[PERF_MAX_STACK_DEPTH]; · 10 unmodified lines | ||
| 11 | 11 | struct { |
| 12 | 12 | __uint(type, BPF_MAP_TYPE_STACK_TRACE); |
| 13 | 13 | __uint(max_entries, 16384); |
| 14 | − __uint(key_size, sizeof(__u32)); | |
| 15 | − __uint(value_size, sizeof(stack_trace_t)); | |
| 14 | + __type(key, __u32); | |
| 15 | + __type(value, stack_trace_t); | |
| 16 | 16 | } stackmap SEC(".maps"); |
| 17 | 17 | |
| 18 | 18 | struct { |
| @@ -7,22 +7,22 @@ int _version SEC("version") = 1; · 6 unmodified lines | ||
| 7 | 7 | struct { |
| 8 | 8 | __uint(type, BPF_MAP_TYPE_SOCKMAP); |
| 9 | 9 | __uint(max_entries, 20); |
| 10 | − __uint(key_size, sizeof(int)); | |
| 11 | − __uint(value_size, sizeof(int)); | |
| 10 | + __type(key, int); | |
| 11 | + __type(value, int); | |
| 12 | 12 | } sock_map_rx SEC(".maps"); |
| 13 | 13 | |
| 14 | 14 | struct { |
| 15 | 15 | __uint(type, BPF_MAP_TYPE_SOCKMAP); |
| 16 | 16 | __uint(max_entries, 20); |
| 17 | − __uint(key_size, sizeof(int)); | |
| 18 | − __uint(value_size, sizeof(int)); | |
| 17 | + __type(key, int); | |
| 18 | + __type(value, int); | |
| 19 | 19 | } sock_map_tx SEC(".maps"); |
| 20 | 20 | |
| 21 | 21 | struct { |
| 22 | 22 | __uint(type, BPF_MAP_TYPE_SOCKMAP); |
| 23 | 23 | __uint(max_entries, 20); |
| 24 | − __uint(key_size, sizeof(int)); | |
| 25 | − __uint(value_size, sizeof(int)); | |
| 24 | + __type(key, int); | |
| 25 | + __type(value, int); | |
| 26 | 26 | } sock_map_msg SEC(".maps"); |
| 27 | 27 | |
| 28 | 28 | struct { |
| @@ -21,8 +21,8 @@ struct inner_map_sz2 { · 20 unmodified lines | ||
| 21 | 21 | struct outer_arr { |
| 22 | 22 | __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); |
| 23 | 23 | __uint(max_entries, 3); |
| 24 | − __uint(key_size, sizeof(int)); | |
| 25 | − __uint(value_size, sizeof(int)); | |
| 24 | + __type(key, int); | |
| 25 | + __type(value, int); | |
| 26 | 26 | /* it's possible to use anonymous struct as inner map definition here */ |
| 27 | 27 | __array(values, struct { |
| 28 | 28 | __uint(type, BPF_MAP_TYPE_ARRAY); |
| @@ -61,8 +61,8 @@ struct inner_map_sz4 { · 32 unmodified lines | ||
| 61 | 61 | struct outer_arr_dyn { |
| 62 | 62 | __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); |
| 63 | 63 | __uint(max_entries, 3); |
| 64 | − __uint(key_size, sizeof(int)); | |
| 65 | − __uint(value_size, sizeof(int)); | |
| 64 | + __type(key, int); | |
| 65 | + __type(value, int); | |
| 66 | 66 | __array(values, struct { |
| 67 | 67 | __uint(type, BPF_MAP_TYPE_ARRAY); |
| 68 | 68 | __uint(map_flags, BPF_F_INNER_MAP); |
| @@ -81,7 +81,7 @@ struct outer_arr_dyn { · 12 unmodified lines | ||
| 81 | 81 | struct outer_hash { |
| 82 | 82 | __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); |
| 83 | 83 | __uint(max_entries, 5); |
| 84 | − __uint(key_size, sizeof(int)); | |
| 84 | + __type(key, int); | |
| 85 | 85 | /* Here everything works flawlessly due to reuse of struct inner_map |
| 86 | 86 | * and compiler will complain at the attempt to use non-inner_map |
| 87 | 87 | * references below. This is great experience. |
| @@ -111,8 +111,8 @@ struct sockarr_sz2 { · 23 unmodified lines | ||
| 111 | 111 | struct outer_sockarr_sz1 { |
| 112 | 112 | __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); |
| 113 | 113 | __uint(max_entries, 1); |
| 114 | − __uint(key_size, sizeof(int)); | |
| 115 | − __uint(value_size, sizeof(int)); | |
| 114 | + __type(key, int); | |
| 115 | + __type(value, int); | |
| 116 | 116 | __array(values, struct sockarr_sz1); |
| 117 | 117 | } outer_sockarr SEC(".maps") = { |
| 118 | 118 | .values = { (void *)&sockarr_sz1 }, |
| @@ -9,18 +9,16 @@ struct { · 8 unmodified lines | ||
| 9 | 9 | __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); |
| 10 | 10 | __uint(max_entries, 1); |
| 11 | 11 | __uint(map_flags, 0); |
| 12 | − __uint(key_size, sizeof(__u32)); | |
| 13 | − /* must be sizeof(__u32) for map in map */ | |
| 14 | − __uint(value_size, sizeof(__u32)); | |
| 12 | + __type(key, __u32); | |
| 13 | + __type(value, __u32); | |
| 15 | 14 | } mim_array SEC(".maps"); |
| 16 | 15 | |
| 17 | 16 | struct { |
| 18 | 17 | __uint(type, BPF_MAP_TYPE_HASH_OF_MAPS); |
| 19 | 18 | __uint(max_entries, 1); |
| 20 | 19 | __uint(map_flags, 0); |
| 21 | − __uint(key_size, sizeof(int)); | |
| 22 | − /* must be sizeof(__u32) for map in map */ | |
| 23 | − __uint(value_size, sizeof(__u32)); | |
| 20 | + __type(key, int); | |
| 21 | + __type(value, __u32); | |
| 24 | 22 | } mim_hash SEC(".maps"); |
| 25 | 23 | |
| 26 | 24 | SEC("xdp") |
| @@ -13,7 +13,7 @@ struct inner { · 12 unmodified lines | ||
| 13 | 13 | struct { |
| 14 | 14 | __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); |
| 15 | 15 | __uint(max_entries, 0); /* This will make map creation to fail */ |
| 16 | − __uint(key_size, sizeof(__u32)); | |
| 16 | + __type(key, __u32); | |
| 17 | 17 | __array(values, struct inner); |
| 18 | 18 | } mim SEC(".maps"); |
| 19 | 19 | |
| @@ -7,15 +7,15 @@ · 6 unmodified lines | ||
| 7 | 7 | struct { |
| 8 | 8 | __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); |
| 9 | 9 | __uint(max_entries, 1); |
| 10 | − __uint(key_size, sizeof(int)); | |
| 11 | − __uint(value_size, sizeof(int)); | |
| 10 | + __type(key, int); | |
| 11 | + __type(value, int); | |
| 12 | 12 | } array_1 SEC(".maps"); |
| 13 | 13 | |
| 14 | 14 | struct { |
| 15 | 15 | __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); |
| 16 | 16 | __uint(max_entries, 1); |
| 17 | − __uint(key_size, sizeof(int)); | |
| 18 | − __uint(value_size, sizeof(int)); | |
| 17 | + __type(key, int); | |
| 18 | + __type(value, int); | |
| 19 | 19 | __uint(map_flags, BPF_F_PRESERVE_ELEMS); |
| 20 | 20 | } array_2 SEC(".maps"); |
| 21 | 21 | |
| @@ -8,8 +8,8 @@ · 7 unmodified lines | ||
| 8 | 8 | |
| 9 | 9 | struct { |
| 10 | 10 | __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); |
| 11 | − __uint(key_size, sizeof(int)); | |
| 12 | − __uint(value_size, sizeof(int)); | |
| 11 | + __type(key, int); | |
| 12 | + __type(value, int); | |
| 13 | 13 | } perf_buf_map SEC(".maps"); |
| 14 | 14 | |
| 15 | 15 | SEC("tp/raw_syscalls/sys_enter") |
| @@ -24,8 +24,8 @@ int _version SEC("version") = 1; · 23 unmodified lines | ||
| 24 | 24 | struct { |
| 25 | 25 | __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS); |
| 26 | 26 | __uint(max_entries, 1); |
| 27 | − __uint(key_size, sizeof(__u32)); | |
| 28 | − __uint(value_size, sizeof(__u32)); | |
| 27 | + __type(key, __u32); | |
| 28 | + __type(value, __u32); | |
| 29 | 29 | } outer_map SEC(".maps"); |
| 30 | 30 | |
| 31 | 31 | struct { |
| @@ -28,8 +28,8 @@ struct { · 27 unmodified lines | ||
| 28 | 28 | __uint(type, BPF_MAP_TYPE_STACK_TRACE); |
| 29 | 29 | __uint(max_entries, 128); |
| 30 | 30 | __uint(map_flags, BPF_F_STACK_BUILD_ID); |
| 31 | − __uint(key_size, sizeof(__u32)); | |
| 32 | − __uint(value_size, sizeof(stack_trace_t)); | |
| 31 | + __type(key, __u32); | |
| 32 | + __type(value, stack_trace_t); | |
| 33 | 33 | } stackmap SEC(".maps"); |
| 34 | 34 | |
| 35 | 35 | struct { |
| @@ -27,8 +27,8 @@ typedef __u64 stack_trace_t[PERF_MAX_STACK_DEPTH]; · 26 unmodified lines | ||
| 27 | 27 | struct { |
| 28 | 28 | __uint(type, BPF_MAP_TYPE_STACK_TRACE); |
| 29 | 29 | __uint(max_entries, 16384); |
| 30 | − __uint(key_size, sizeof(__u32)); | |
| 31 | − __uint(value_size, sizeof(stack_trace_t)); | |
| 30 | + __type(key, __u32); | |
| 31 | + __type(value, stack_trace_t); | |
| 32 | 32 | } stackmap SEC(".maps"); |
| 33 | 33 | |
| 34 | 34 | struct { |
| @@ -24,8 +24,8 @@ struct { · 23 unmodified lines | ||
| 24 | 24 | struct { |
| 25 | 25 | __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); |
| 26 | 26 | __uint(max_entries, 2); |
| 27 | − __uint(key_size, sizeof(int)); | |
| 28 | − __uint(value_size, sizeof(__u32)); | |
| 27 | + __type(key, int); | |
| 28 | + __type(value, __u32); | |
| 29 | 29 | } perf_event_map SEC(".maps"); |
| 30 | 30 | |
| 31 | 31 | int _version SEC("version") = 1; |
| @@ -36,8 +36,8 @@ struct meta { · 35 unmodified lines | ||
| 36 | 36 | |
| 37 | 37 | struct { |
| 38 | 38 | __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); |
| 39 | − __uint(key_size, sizeof(int)); | |
| 40 | − __uint(value_size, sizeof(int)); | |
| 39 | + __type(key, int); | |
| 40 | + __type(value, int); | |
| 41 | 41 | } perf_buf_map SEC(".maps"); |
| 42 | 42 | |
| 43 | 43 | __u64 test_result_fentry = 0; |