Commit d636c8da authored by Andrii Nakryiko's avatar Andrii Nakryiko
Browse files

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: default avatarAndrii Nakryiko <andrii@kernel.org>
parents 7bceeb95 bd368cb5
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
@@ -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.
+2 −2
Original line number Diff line number Diff line
@@ -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))
+2 −2
Original line number Diff line number Diff line
@@ -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 {
+6 −6
Original line number Diff line number Diff line
@@ -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 {
+7 −7
Original line number Diff line number Diff line
@@ -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 },
Loading