From 38d5d3b3d5dbc0e0bb51fa6f7559d0d5a27916f6 Mon Sep 17 00:00:00 2001 From: Martin KaFai Lau Date: Tue, 24 Jul 2018 08:40:22 -0700 Subject: bpf: Introduce BPF_ANNOTATE_KV_PAIR This patch introduces BPF_ANNOTATE_KV_PAIR to signal the bpf loader about the btf key_type and value_type of a bpf map. Please refer to the changes in test_btf_haskv.c for its usage. Both iproute2 and libbpf loader will then have the same convention to find out the map's btf_key_type_id and btf_value_type_id from a map's name. Fixes: 8a138aed4a80 ("bpf: btf: Add BTF support to libbpf") Suggested-by: Daniel Borkmann Signed-off-by: Martin KaFai Lau Acked-by: Yonghong Song Signed-off-by: Daniel Borkmann --- tools/lib/bpf/libbpf.c | 75 +++++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 35 deletions(-) (limited to 'tools/lib/bpf/libbpf.c') diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 6deb4fe4fffe..d881d370616c 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -1014,68 +1015,72 @@ 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) { + const struct btf_type *container_type; + const struct btf_member *key, *value; struct bpf_map_def *def = &map->def; const size_t max_name = 256; + char container_name[max_name]; __s64 key_size, value_size; - __s32 key_id, value_id; - char name[max_name]; + __s32 container_id; - /* Find key type by name from BTF */ - if (snprintf(name, max_name, "%s_key", map->name) == max_name) { - pr_warning("map:%s length of BTF key_type:%s_key is too long\n", + 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; } - key_id = btf__find_by_name(btf, name); - if (key_id < 0) { - pr_debug("map:%s key_type:%s cannot be found in BTF\n", - map->name, name); - return key_id; + container_id = btf__find_by_name(btf, container_name); + if (container_id < 0) { + 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; } - key_size = btf__resolve_size(btf, key_id); - if (key_size < 0) { - pr_warning("map:%s key_type:%s cannot get the BTF type_size\n", - map->name, name); - return key_size; + 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 (def->key_size != key_size) { - pr_warning("map:%s key_type:%s has BTF type_size:%u != key_size:%u\n", - map->name, name, (unsigned int)key_size, def->key_size); + 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; } - /* Find value type from BTF */ - if (snprintf(name, max_name, "%s_value", map->name) == max_name) { - pr_warning("map:%s length of BTF value_type:%s_value is too long\n", - map->name, map->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; } - value_id = btf__find_by_name(btf, name); - if (value_id < 0) { - pr_debug("map:%s value_type:%s cannot be found in BTF\n", - map->name, name); - return value_id; + 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_id); + value_size = btf__resolve_size(btf, value->type); if (value_size < 0) { - pr_warning("map:%s value_type:%s cannot get the BTF type_size\n", - map->name, name); + 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 value_type:%s has BTF type_size:%u != value_size:%u\n", - map->name, name, (unsigned int)value_size, def->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_id; - map->btf_value_type_id = value_id; + map->btf_key_type_id = key->type; + map->btf_value_type_id = value->type; return 0; } -- cgit v1.2.3-55-g7522