mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	tools/bpf: implement libbpf btf__get_map_kv_tids() API function
Currently, to get map key/value type id's, the macro BPF_ANNOTATE_KV_PAIR(<map_name>, <key_type>, <value_type>) needs to be defined in the bpf program for the corresponding map. During program/map loading time, the local static function bpf_map_find_btf_info() in libbpf.c is implemented to retrieve the key/value type ids given the map name. The patch refactored function bpf_map_find_btf_info() to create an API btf__get_map_kv_tids() which includes the bulk of implementation for the original function. The API btf__get_map_kv_tids() can be used by bcc, a JIT based bpf compilation system, which uses the same BPF_ANNOTATE_KV_PAIR to record map key/value types. Acked-by: Martin KaFai Lau <kafai@fb.com> Signed-off-by: Yonghong Song <yhs@fb.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
		
							parent
							
								
									b8dcf8d149
								
							
						
					
					
						commit
						96408c4344
					
				
					 4 changed files with 87 additions and 63 deletions
				
			
		| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
 | 
					// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
 | 
				
			||||||
/* Copyright (c) 2018 Facebook */
 | 
					/* Copyright (c) 2018 Facebook */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
#include <unistd.h>
 | 
					#include <unistd.h>
 | 
				
			||||||
| 
						 | 
					@ -504,6 +505,78 @@ int btf__get_from_id(__u32 id, struct btf **btf)
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int btf__get_map_kv_tids(const struct btf *btf, char *map_name,
 | 
				
			||||||
 | 
								 __u32 expected_key_size, __u32 expected_value_size,
 | 
				
			||||||
 | 
								 __u32 *key_type_id, __u32 *value_type_id)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						const struct btf_type *container_type;
 | 
				
			||||||
 | 
						const struct btf_member *key, *value;
 | 
				
			||||||
 | 
						const size_t max_name = 256;
 | 
				
			||||||
 | 
						char container_name[max_name];
 | 
				
			||||||
 | 
						__s64 key_size, value_size;
 | 
				
			||||||
 | 
						__s32 container_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (snprintf(container_name, max_name, "____btf_map_%s", map_name) ==
 | 
				
			||||||
 | 
						    max_name) {
 | 
				
			||||||
 | 
							pr_warning("map:%s length of '____btf_map_%s' is too long\n",
 | 
				
			||||||
 | 
								   map_name, map_name);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						container_id = btf__find_by_name(btf, container_name);
 | 
				
			||||||
 | 
						if (container_id < 0) {
 | 
				
			||||||
 | 
							pr_warning("map:%s container_name:%s cannot be found in BTF. Missing BPF_ANNOTATE_KV_PAIR?\n",
 | 
				
			||||||
 | 
								   map_name, container_name);
 | 
				
			||||||
 | 
							return container_id;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						container_type = btf__type_by_id(btf, container_id);
 | 
				
			||||||
 | 
						if (!container_type) {
 | 
				
			||||||
 | 
							pr_warning("map:%s cannot find BTF type for container_id:%u\n",
 | 
				
			||||||
 | 
								   map_name, container_id);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (BTF_INFO_KIND(container_type->info) != BTF_KIND_STRUCT ||
 | 
				
			||||||
 | 
						    BTF_INFO_VLEN(container_type->info) < 2) {
 | 
				
			||||||
 | 
							pr_warning("map:%s container_name:%s is an invalid container struct\n",
 | 
				
			||||||
 | 
								   map_name, container_name);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						key = (struct btf_member *)(container_type + 1);
 | 
				
			||||||
 | 
						value = key + 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						key_size = btf__resolve_size(btf, key->type);
 | 
				
			||||||
 | 
						if (key_size < 0) {
 | 
				
			||||||
 | 
							pr_warning("map:%s invalid BTF key_type_size\n", map_name);
 | 
				
			||||||
 | 
							return key_size;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (expected_key_size != key_size) {
 | 
				
			||||||
 | 
							pr_warning("map:%s btf_key_type_size:%u != map_def_key_size:%u\n",
 | 
				
			||||||
 | 
								   map_name, (__u32)key_size, expected_key_size);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						value_size = btf__resolve_size(btf, value->type);
 | 
				
			||||||
 | 
						if (value_size < 0) {
 | 
				
			||||||
 | 
							pr_warning("map:%s invalid BTF value_type_size\n", map_name);
 | 
				
			||||||
 | 
							return value_size;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (expected_value_size != value_size) {
 | 
				
			||||||
 | 
							pr_warning("map:%s btf_value_type_size:%u != map_def_value_size:%u\n",
 | 
				
			||||||
 | 
								   map_name, (__u32)value_size, expected_value_size);
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						*key_type_id = key->type;
 | 
				
			||||||
 | 
						*value_type_id = value->type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct btf_ext_sec_copy_param {
 | 
					struct btf_ext_sec_copy_param {
 | 
				
			||||||
	__u32 off;
 | 
						__u32 off;
 | 
				
			||||||
	__u32 len;
 | 
						__u32 len;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,6 +66,10 @@ LIBBPF_API int btf__resolve_type(const struct btf *btf, __u32 type_id);
 | 
				
			||||||
LIBBPF_API int btf__fd(const struct btf *btf);
 | 
					LIBBPF_API int btf__fd(const struct btf *btf);
 | 
				
			||||||
LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset);
 | 
					LIBBPF_API const char *btf__name_by_offset(const struct btf *btf, __u32 offset);
 | 
				
			||||||
LIBBPF_API int btf__get_from_id(__u32 id, struct btf **btf);
 | 
					LIBBPF_API int btf__get_from_id(__u32 id, struct btf **btf);
 | 
				
			||||||
 | 
					LIBBPF_API int btf__get_map_kv_tids(const struct btf *btf, char *map_name,
 | 
				
			||||||
 | 
									    __u32 expected_key_size,
 | 
				
			||||||
 | 
									    __u32 expected_value_size,
 | 
				
			||||||
 | 
									    __u32 *key_type_id, __u32 *value_type_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
LIBBPF_API struct btf_ext *btf_ext__new(__u8 *data, __u32 size);
 | 
					LIBBPF_API struct btf_ext *btf_ext__new(__u8 *data, __u32 size);
 | 
				
			||||||
LIBBPF_API void btf_ext__free(struct btf_ext *btf_ext);
 | 
					LIBBPF_API void btf_ext__free(struct btf_ext *btf_ext);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1056,72 +1056,18 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf)
 | 
					static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct btf_type *container_type;
 | 
					 | 
				
			||||||
	const struct btf_member *key, *value;
 | 
					 | 
				
			||||||
	struct bpf_map_def *def = &map->def;
 | 
						struct bpf_map_def *def = &map->def;
 | 
				
			||||||
	const size_t max_name = 256;
 | 
						__u32 key_type_id, value_type_id;
 | 
				
			||||||
	char container_name[max_name];
 | 
						int ret;
 | 
				
			||||||
	__s64 key_size, value_size;
 | 
					 | 
				
			||||||
	__s32 container_id;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (snprintf(container_name, max_name, "____btf_map_%s", map->name) ==
 | 
						ret = btf__get_map_kv_tids(btf, map->name, def->key_size,
 | 
				
			||||||
	    max_name) {
 | 
									   def->value_size, &key_type_id,
 | 
				
			||||||
		pr_warning("map:%s length of '____btf_map_%s' is too long\n",
 | 
									   &value_type_id);
 | 
				
			||||||
			   map->name, map->name);
 | 
						if (ret)
 | 
				
			||||||
		return -EINVAL;
 | 
							return ret;
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	container_id = btf__find_by_name(btf, container_name);
 | 
						map->btf_key_type_id = key_type_id;
 | 
				
			||||||
	if (container_id < 0) {
 | 
						map->btf_value_type_id = value_type_id;
 | 
				
			||||||
		pr_debug("map:%s container_name:%s cannot be found in BTF. Missing BPF_ANNOTATE_KV_PAIR?\n",
 | 
					 | 
				
			||||||
			 map->name, container_name);
 | 
					 | 
				
			||||||
		return container_id;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	container_type = btf__type_by_id(btf, container_id);
 | 
					 | 
				
			||||||
	if (!container_type) {
 | 
					 | 
				
			||||||
		pr_warning("map:%s cannot find BTF type for container_id:%u\n",
 | 
					 | 
				
			||||||
			   map->name, container_id);
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (BTF_INFO_KIND(container_type->info) != BTF_KIND_STRUCT ||
 | 
					 | 
				
			||||||
	    BTF_INFO_VLEN(container_type->info) < 2) {
 | 
					 | 
				
			||||||
		pr_warning("map:%s container_name:%s is an invalid container struct\n",
 | 
					 | 
				
			||||||
			   map->name, container_name);
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	key = (struct btf_member *)(container_type + 1);
 | 
					 | 
				
			||||||
	value = key + 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	key_size = btf__resolve_size(btf, key->type);
 | 
					 | 
				
			||||||
	if (key_size < 0) {
 | 
					 | 
				
			||||||
		pr_warning("map:%s invalid BTF key_type_size\n",
 | 
					 | 
				
			||||||
			   map->name);
 | 
					 | 
				
			||||||
		return key_size;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (def->key_size != key_size) {
 | 
					 | 
				
			||||||
		pr_warning("map:%s btf_key_type_size:%u != map_def_key_size:%u\n",
 | 
					 | 
				
			||||||
			   map->name, (__u32)key_size, def->key_size);
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	value_size = btf__resolve_size(btf, value->type);
 | 
					 | 
				
			||||||
	if (value_size < 0) {
 | 
					 | 
				
			||||||
		pr_warning("map:%s invalid BTF value_type_size\n", map->name);
 | 
					 | 
				
			||||||
		return value_size;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (def->value_size != value_size) {
 | 
					 | 
				
			||||||
		pr_warning("map:%s btf_value_type_size:%u != map_def_value_size:%u\n",
 | 
					 | 
				
			||||||
			   map->name, (__u32)value_size, def->value_size);
 | 
					 | 
				
			||||||
		return -EINVAL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	map->btf_key_type_id = key->type;
 | 
					 | 
				
			||||||
	map->btf_value_type_id = value->type;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -133,6 +133,7 @@ LIBBPF_0.0.2 {
 | 
				
			||||||
		bpf_map_lookup_elem_flags;
 | 
							bpf_map_lookup_elem_flags;
 | 
				
			||||||
		bpf_object__find_map_fd_by_name;
 | 
							bpf_object__find_map_fd_by_name;
 | 
				
			||||||
		bpf_get_link_xdp_id;
 | 
							bpf_get_link_xdp_id;
 | 
				
			||||||
 | 
							btf__get_map_kv_tids;
 | 
				
			||||||
		btf_ext__free;
 | 
							btf_ext__free;
 | 
				
			||||||
		btf_ext__func_info_rec_size;
 | 
							btf_ext__func_info_rec_size;
 | 
				
			||||||
		btf_ext__line_info_rec_size;
 | 
							btf_ext__line_info_rec_size;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue