Commit 38d5d3b3 authored by Martin KaFai Lau's avatar Martin KaFai Lau Committed by Daniel Borkmann

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: 8a138aed ("bpf: btf: Add BTF support to libbpf")
Suggested-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Signed-off-by: default avatarMartin KaFai Lau <kafai@fb.com>
Acked-by: default avatarYonghong Song <yhs@fb.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
parent 5b891af7
...@@ -189,8 +189,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log) ...@@ -189,8 +189,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)
return 0; return 0;
} }
static const struct btf_type *btf_type_by_id(const struct btf *btf, const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 type_id)
__u32 type_id)
{ {
if (type_id > btf->nr_types) if (type_id > btf->nr_types)
return NULL; return NULL;
...@@ -233,7 +232,7 @@ __s64 btf__resolve_size(const struct btf *btf, __u32 type_id) ...@@ -233,7 +232,7 @@ __s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
__s64 size = -1; __s64 size = -1;
int i; int i;
t = btf_type_by_id(btf, type_id); t = btf__type_by_id(btf, type_id);
for (i = 0; i < MAX_RESOLVE_DEPTH && !btf_type_is_void_or_null(t); for (i = 0; i < MAX_RESOLVE_DEPTH && !btf_type_is_void_or_null(t);
i++) { i++) {
size = btf_type_size(t); size = btf_type_size(t);
...@@ -258,7 +257,7 @@ __s64 btf__resolve_size(const struct btf *btf, __u32 type_id) ...@@ -258,7 +257,7 @@ __s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
return -EINVAL; return -EINVAL;
} }
t = btf_type_by_id(btf, type_id); t = btf__type_by_id(btf, type_id);
} }
if (size < 0) if (size < 0)
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#define BTF_ELF_SEC ".BTF" #define BTF_ELF_SEC ".BTF"
struct btf; struct btf;
struct btf_type;
typedef int (*btf_print_fn_t)(const char *, ...) typedef int (*btf_print_fn_t)(const char *, ...)
__attribute__((format(printf, 1, 2))); __attribute__((format(printf, 1, 2)));
...@@ -16,6 +17,7 @@ typedef int (*btf_print_fn_t)(const char *, ...) ...@@ -16,6 +17,7 @@ typedef int (*btf_print_fn_t)(const char *, ...)
void btf__free(struct btf *btf); void btf__free(struct btf *btf);
struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log); struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log);
__s32 btf__find_by_name(const struct btf *btf, const char *type_name); __s32 btf__find_by_name(const struct btf *btf, const char *type_name);
const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 id);
__s64 btf__resolve_size(const struct btf *btf, __u32 type_id); __s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
int btf__fd(const struct btf *btf); int btf__fd(const struct btf *btf);
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/bpf.h> #include <linux/bpf.h>
#include <linux/btf.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/limits.h> #include <linux/limits.h>
#include <sys/stat.h> #include <sys/stat.h>
...@@ -1014,68 +1015,72 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr, ...@@ -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) 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; const size_t max_name = 256;
char container_name[max_name];
__s64 key_size, value_size; __s64 key_size, value_size;
__s32 key_id, value_id; __s32 container_id;
char name[max_name];
/* Find key type by name from BTF */ if (snprintf(container_name, max_name, "____btf_map_%s", map->name) ==
if (snprintf(name, max_name, "%s_key", map->name) == max_name) { max_name) {
pr_warning("map:%s length of BTF key_type:%s_key is too long\n", pr_warning("map:%s length of '____btf_map_%s' is too long\n",
map->name, map->name); map->name, map->name);
return -EINVAL; return -EINVAL;
} }
key_id = btf__find_by_name(btf, name); container_id = btf__find_by_name(btf, container_name);
if (key_id < 0) { if (container_id < 0) {
pr_debug("map:%s key_type:%s cannot be found in BTF\n", pr_debug("map:%s container_name:%s cannot be found in BTF. Missing BPF_ANNOTATE_KV_PAIR?\n",
map->name, name); map->name, container_name);
return key_id; return container_id;
} }
key_size = btf__resolve_size(btf, key_id); container_type = btf__type_by_id(btf, container_id);
if (key_size < 0) { if (!container_type) {
pr_warning("map:%s key_type:%s cannot get the BTF type_size\n", pr_warning("map:%s cannot find BTF type for container_id:%u\n",
map->name, name); map->name, container_id);
return key_size; return -EINVAL;
} }
if (def->key_size != key_size) { if (BTF_INFO_KIND(container_type->info) != BTF_KIND_STRUCT ||
pr_warning("map:%s key_type:%s has BTF type_size:%u != key_size:%u\n", BTF_INFO_VLEN(container_type->info) < 2) {
map->name, name, (unsigned int)key_size, def->key_size); pr_warning("map:%s container_name:%s is an invalid container struct\n",
map->name, container_name);
return -EINVAL; return -EINVAL;
} }
/* Find value type from BTF */ key = (struct btf_member *)(container_type + 1);
if (snprintf(name, max_name, "%s_value", map->name) == max_name) { value = key + 1;
pr_warning("map:%s length of BTF value_type:%s_value is too long\n",
map->name, map->name); key_size = btf__resolve_size(btf, key->type);
return -EINVAL; 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 (def->key_size != key_size) {
if (value_id < 0) { pr_warning("map:%s btf_key_type_size:%u != map_def_key_size:%u\n",
pr_debug("map:%s value_type:%s cannot be found in BTF\n", map->name, (__u32)key_size, def->key_size);
map->name, name); return -EINVAL;
return value_id;
} }
value_size = btf__resolve_size(btf, value_id); value_size = btf__resolve_size(btf, value->type);
if (value_size < 0) { if (value_size < 0) {
pr_warning("map:%s value_type:%s cannot get the BTF type_size\n", pr_warning("map:%s invalid BTF value_type_size\n", map->name);
map->name, name);
return value_size; return value_size;
} }
if (def->value_size != value_size) { if (def->value_size != value_size) {
pr_warning("map:%s value_type:%s has BTF type_size:%u != value_size:%u\n", pr_warning("map:%s btf_value_type_size:%u != map_def_value_size:%u\n",
map->name, name, (unsigned int)value_size, def->value_size); map->name, (__u32)value_size, def->value_size);
return -EINVAL; return -EINVAL;
} }
map->btf_key_type_id = key_id; map->btf_key_type_id = key->type;
map->btf_value_type_id = value_id; map->btf_value_type_id = value->type;
return 0; return 0;
} }
......
...@@ -158,6 +158,15 @@ struct bpf_map_def { ...@@ -158,6 +158,15 @@ struct bpf_map_def {
unsigned int numa_node; unsigned int numa_node;
}; };
#define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \
struct ____btf_map_##name { \
type_key key; \
type_val value; \
}; \
struct ____btf_map_##name \
__attribute__ ((section(".maps." #name), used)) \
____btf_map_##name = { }
static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) = static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) =
(void *) BPF_FUNC_skb_load_bytes; (void *) BPF_FUNC_skb_load_bytes;
static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from, int len, int flags) = static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from, int len, int flags) =
......
...@@ -10,11 +10,6 @@ struct ipv_counts { ...@@ -10,11 +10,6 @@ struct ipv_counts {
unsigned int v6; unsigned int v6;
}; };
typedef int btf_map_key;
typedef struct ipv_counts btf_map_value;
btf_map_key dumm_key;
btf_map_value dummy_value;
struct bpf_map_def SEC("maps") btf_map = { struct bpf_map_def SEC("maps") btf_map = {
.type = BPF_MAP_TYPE_ARRAY, .type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(int), .key_size = sizeof(int),
...@@ -22,6 +17,8 @@ struct bpf_map_def SEC("maps") btf_map = { ...@@ -22,6 +17,8 @@ struct bpf_map_def SEC("maps") btf_map = {
.max_entries = 4, .max_entries = 4,
}; };
BPF_ANNOTATE_KV_PAIR(btf_map, int, struct ipv_counts);
struct dummy_tracepoint_args { struct dummy_tracepoint_args {
unsigned long long pad; unsigned long long pad;
struct sock *sock; struct sock *sock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment