aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2018-07-25 00:57:56 -0400
committerDaniel Borkmann <daniel@iogearbox.net>2018-07-25 01:00:27 -0400
commit684cce1c31d2c0c9383cbcca200b9cf3b1f1d21d (patch)
treec19295299de7d53fcacffb42ea67b3c00206aeab
parent6283fa38dc8744dc7c2bd2a03bb0478fe42f79fa (diff)
parent38d5d3b3d5dbc0e0bb51fa6f7559d0d5a27916f6 (diff)
Merge branch 'bpf-annotate-kv-pair'
Martin KaFai Lau says: ==================== The series allows the BPF loader to figure out the btf_key_id and btf_value_id from a map's name by using BPF_ANNOTATE_KV_PAIR() similarly as in iproute2 commit f823f36012fb ("bpf: implement btf handling and map annotation"). It also removes the old 'typedef' way which requires two separate typedefs (one for the key and one for the value). By doing this, iproute2 and libbpf have one consistent way to figure out the btf_key_type_id and btf_value_type_id for a map. The first two patches are some prep/cleanup works. The last patch introduces BPF_ANNOTATE_KV_PAIR. v3: - Replace some more *int*_t and u* usages with the equivalent __[su]* in btf.c v2: - Fix the incorrect '&&' check on container_type in bpf_map_find_btf_info(). - Expose the existing static btf_type_by_id() instead of creating a new one. ==================== Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r--tools/include/uapi/linux/btf.h2
-rw-r--r--tools/lib/bpf/btf.c39
-rw-r--r--tools/lib/bpf/btf.h10
-rw-r--r--tools/lib/bpf/libbpf.c85
-rw-r--r--tools/lib/bpf/libbpf.h4
-rw-r--r--tools/testing/selftests/bpf/bpf_helpers.h9
-rw-r--r--tools/testing/selftests/bpf/test_btf_haskv.c7
7 files changed, 83 insertions, 73 deletions
diff --git a/tools/include/uapi/linux/btf.h b/tools/include/uapi/linux/btf.h
index 0b5ddbe135a4..972265f32871 100644
--- a/tools/include/uapi/linux/btf.h
+++ b/tools/include/uapi/linux/btf.h
@@ -76,7 +76,7 @@ struct btf_type {
76 */ 76 */
77#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24) 77#define BTF_INT_ENCODING(VAL) (((VAL) & 0x0f000000) >> 24)
78#define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16) 78#define BTF_INT_OFFSET(VAL) (((VAL & 0x00ff0000)) >> 16)
79#define BTF_INT_BITS(VAL) ((VAL) & 0x0000ffff) 79#define BTF_INT_BITS(VAL) ((VAL) & 0x000000ff)
80 80
81/* Attributes stored in the BTF_INT_ENCODING */ 81/* Attributes stored in the BTF_INT_ENCODING */
82#define BTF_INT_SIGNED (1 << 0) 82#define BTF_INT_SIGNED (1 << 0)
diff --git a/tools/lib/bpf/btf.c b/tools/lib/bpf/btf.c
index 8c54a4b6f187..2d270c560df3 100644
--- a/tools/lib/bpf/btf.c
+++ b/tools/lib/bpf/btf.c
@@ -2,7 +2,6 @@
2/* Copyright (c) 2018 Facebook */ 2/* Copyright (c) 2018 Facebook */
3 3
4#include <stdlib.h> 4#include <stdlib.h>
5#include <stdint.h>
6#include <string.h> 5#include <string.h>
7#include <unistd.h> 6#include <unistd.h>
8#include <errno.h> 7#include <errno.h>
@@ -27,13 +26,13 @@ struct btf {
27 struct btf_type **types; 26 struct btf_type **types;
28 const char *strings; 27 const char *strings;
29 void *nohdr_data; 28 void *nohdr_data;
30 uint32_t nr_types; 29 __u32 nr_types;
31 uint32_t types_size; 30 __u32 types_size;
32 uint32_t data_size; 31 __u32 data_size;
33 int fd; 32 int fd;
34}; 33};
35 34
36static const char *btf_name_by_offset(const struct btf *btf, uint32_t offset) 35static const char *btf_name_by_offset(const struct btf *btf, __u32 offset)
37{ 36{
38 if (offset < btf->hdr->str_len) 37 if (offset < btf->hdr->str_len)
39 return &btf->strings[offset]; 38 return &btf->strings[offset];
@@ -45,7 +44,7 @@ static int btf_add_type(struct btf *btf, struct btf_type *t)
45{ 44{
46 if (btf->types_size - btf->nr_types < 2) { 45 if (btf->types_size - btf->nr_types < 2) {
47 struct btf_type **new_types; 46 struct btf_type **new_types;
48 u32 expand_by, new_size; 47 __u32 expand_by, new_size;
49 48
50 if (btf->types_size == BTF_MAX_NR_TYPES) 49 if (btf->types_size == BTF_MAX_NR_TYPES)
51 return -E2BIG; 50 return -E2BIG;
@@ -72,7 +71,7 @@ static int btf_add_type(struct btf *btf, struct btf_type *t)
72static int btf_parse_hdr(struct btf *btf, btf_print_fn_t err_log) 71static int btf_parse_hdr(struct btf *btf, btf_print_fn_t err_log)
73{ 72{
74 const struct btf_header *hdr = btf->hdr; 73 const struct btf_header *hdr = btf->hdr;
75 u32 meta_left; 74 __u32 meta_left;
76 75
77 if (btf->data_size < sizeof(struct btf_header)) { 76 if (btf->data_size < sizeof(struct btf_header)) {
78 elog("BTF header not found\n"); 77 elog("BTF header not found\n");
@@ -151,7 +150,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)
151 150
152 while (next_type < end_type) { 151 while (next_type < end_type) {
153 struct btf_type *t = next_type; 152 struct btf_type *t = next_type;
154 uint16_t vlen = BTF_INFO_VLEN(t->info); 153 __u16 vlen = BTF_INFO_VLEN(t->info);
155 int err; 154 int err;
156 155
157 next_type += sizeof(*t); 156 next_type += sizeof(*t);
@@ -190,8 +189,7 @@ static int btf_parse_type_sec(struct btf *btf, btf_print_fn_t err_log)
190 return 0; 189 return 0;
191} 190}
192 191
193static const struct btf_type *btf_type_by_id(const struct btf *btf, 192const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 type_id)
194 uint32_t type_id)
195{ 193{
196 if (type_id > btf->nr_types) 194 if (type_id > btf->nr_types)
197 return NULL; 195 return NULL;
@@ -209,7 +207,7 @@ static bool btf_type_is_void_or_null(const struct btf_type *t)
209 return !t || btf_type_is_void(t); 207 return !t || btf_type_is_void(t);
210} 208}
211 209
212static int64_t btf_type_size(const struct btf_type *t) 210static __s64 btf_type_size(const struct btf_type *t)
213{ 211{
214 switch (BTF_INFO_KIND(t->info)) { 212 switch (BTF_INFO_KIND(t->info)) {
215 case BTF_KIND_INT: 213 case BTF_KIND_INT:
@@ -226,15 +224,15 @@ static int64_t btf_type_size(const struct btf_type *t)
226 224
227#define MAX_RESOLVE_DEPTH 32 225#define MAX_RESOLVE_DEPTH 32
228 226
229int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id) 227__s64 btf__resolve_size(const struct btf *btf, __u32 type_id)
230{ 228{
231 const struct btf_array *array; 229 const struct btf_array *array;
232 const struct btf_type *t; 230 const struct btf_type *t;
233 uint32_t nelems = 1; 231 __u32 nelems = 1;
234 int64_t size = -1; 232 __s64 size = -1;
235 int i; 233 int i;
236 234
237 t = btf_type_by_id(btf, type_id); 235 t = btf__type_by_id(btf, type_id);
238 for (i = 0; i < MAX_RESOLVE_DEPTH && !btf_type_is_void_or_null(t); 236 for (i = 0; i < MAX_RESOLVE_DEPTH && !btf_type_is_void_or_null(t);
239 i++) { 237 i++) {
240 size = btf_type_size(t); 238 size = btf_type_size(t);
@@ -259,7 +257,7 @@ int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id)
259 return -EINVAL; 257 return -EINVAL;
260 } 258 }
261 259
262 t = btf_type_by_id(btf, type_id); 260 t = btf__type_by_id(btf, type_id);
263 } 261 }
264 262
265 if (size < 0) 263 if (size < 0)
@@ -271,9 +269,9 @@ int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id)
271 return nelems * size; 269 return nelems * size;
272} 270}
273 271
274int32_t btf__find_by_name(const struct btf *btf, const char *type_name) 272__s32 btf__find_by_name(const struct btf *btf, const char *type_name)
275{ 273{
276 uint32_t i; 274 __u32 i;
277 275
278 if (!strcmp(type_name, "void")) 276 if (!strcmp(type_name, "void"))
279 return 0; 277 return 0;
@@ -302,10 +300,9 @@ void btf__free(struct btf *btf)
302 free(btf); 300 free(btf);
303} 301}
304 302
305struct btf *btf__new(uint8_t *data, uint32_t size, 303struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log)
306 btf_print_fn_t err_log)
307{ 304{
308 uint32_t log_buf_size = 0; 305 __u32 log_buf_size = 0;
309 char *log_buf = NULL; 306 char *log_buf = NULL;
310 struct btf *btf; 307 struct btf *btf;
311 int err; 308 int err;
diff --git a/tools/lib/bpf/btf.h b/tools/lib/bpf/btf.h
index 74bb344035bb..e2a09a155f84 100644
--- a/tools/lib/bpf/btf.h
+++ b/tools/lib/bpf/btf.h
@@ -4,19 +4,21 @@
4#ifndef __BPF_BTF_H 4#ifndef __BPF_BTF_H
5#define __BPF_BTF_H 5#define __BPF_BTF_H
6 6
7#include <stdint.h> 7#include <linux/types.h>
8 8
9#define BTF_ELF_SEC ".BTF" 9#define BTF_ELF_SEC ".BTF"
10 10
11struct btf; 11struct btf;
12struct btf_type;
12 13
13typedef int (*btf_print_fn_t)(const char *, ...) 14typedef int (*btf_print_fn_t)(const char *, ...)
14 __attribute__((format(printf, 1, 2))); 15 __attribute__((format(printf, 1, 2)));
15 16
16void btf__free(struct btf *btf); 17void btf__free(struct btf *btf);
17struct btf *btf__new(uint8_t *data, uint32_t size, btf_print_fn_t err_log); 18struct btf *btf__new(__u8 *data, __u32 size, btf_print_fn_t err_log);
18int32_t btf__find_by_name(const struct btf *btf, const char *type_name); 19__s32 btf__find_by_name(const struct btf *btf, const char *type_name);
19int64_t btf__resolve_size(const struct btf *btf, uint32_t type_id); 20const struct btf_type *btf__type_by_id(const struct btf *btf, __u32 id);
21__s64 btf__resolve_size(const struct btf *btf, __u32 type_id);
20int btf__fd(const struct btf *btf); 22int btf__fd(const struct btf *btf);
21 23
22#endif 24#endif
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index a1e96b5de5ff..d881d370616c 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -36,6 +36,7 @@
36#include <linux/err.h> 36#include <linux/err.h>
37#include <linux/kernel.h> 37#include <linux/kernel.h>
38#include <linux/bpf.h> 38#include <linux/bpf.h>
39#include <linux/btf.h>
39#include <linux/list.h> 40#include <linux/list.h>
40#include <linux/limits.h> 41#include <linux/limits.h>
41#include <sys/stat.h> 42#include <sys/stat.h>
@@ -216,8 +217,8 @@ struct bpf_map {
216 size_t offset; 217 size_t offset;
217 int map_ifindex; 218 int map_ifindex;
218 struct bpf_map_def def; 219 struct bpf_map_def def;
219 uint32_t btf_key_type_id; 220 __u32 btf_key_type_id;
220 uint32_t btf_value_type_id; 221 __u32 btf_value_type_id;
221 void *priv; 222 void *priv;
222 bpf_map_clear_priv_t clear_priv; 223 bpf_map_clear_priv_t clear_priv;
223}; 224};
@@ -1014,68 +1015,72 @@ bpf_program__collect_reloc(struct bpf_program *prog, GElf_Shdr *shdr,
1014 1015
1015static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf) 1016static int bpf_map_find_btf_info(struct bpf_map *map, const struct btf *btf)
1016{ 1017{
1018 const struct btf_type *container_type;
1019 const struct btf_member *key, *value;
1017 struct bpf_map_def *def = &map->def; 1020 struct bpf_map_def *def = &map->def;
1018 const size_t max_name = 256; 1021 const size_t max_name = 256;
1019 int64_t key_size, value_size; 1022 char container_name[max_name];
1020 int32_t key_id, value_id; 1023 __s64 key_size, value_size;
1021 char name[max_name]; 1024 __s32 container_id;
1022 1025
1023 /* Find key type by name from BTF */ 1026 if (snprintf(container_name, max_name, "____btf_map_%s", map->name) ==
1024 if (snprintf(name, max_name, "%s_key", map->name) == max_name) { 1027 max_name) {
1025 pr_warning("map:%s length of BTF key_type:%s_key is too long\n", 1028 pr_warning("map:%s length of '____btf_map_%s' is too long\n",
1026 map->name, map->name); 1029 map->name, map->name);
1027 return -EINVAL; 1030 return -EINVAL;
1028 } 1031 }
1029 1032
1030 key_id = btf__find_by_name(btf, name); 1033 container_id = btf__find_by_name(btf, container_name);
1031 if (key_id < 0) { 1034 if (container_id < 0) {
1032 pr_debug("map:%s key_type:%s cannot be found in BTF\n", 1035 pr_debug("map:%s container_name:%s cannot be found in BTF. Missing BPF_ANNOTATE_KV_PAIR?\n",
1033 map->name, name); 1036 map->name, container_name);
1034 return key_id; 1037 return container_id;
1035 } 1038 }
1036 1039
1037 key_size = btf__resolve_size(btf, key_id); 1040 container_type = btf__type_by_id(btf, container_id);
1038 if (key_size < 0) { 1041 if (!container_type) {
1039 pr_warning("map:%s key_type:%s cannot get the BTF type_size\n", 1042 pr_warning("map:%s cannot find BTF type for container_id:%u\n",
1040 map->name, name); 1043 map->name, container_id);
1041 return key_size; 1044 return -EINVAL;
1042 } 1045 }
1043 1046
1044 if (def->key_size != key_size) { 1047 if (BTF_INFO_KIND(container_type->info) != BTF_KIND_STRUCT ||
1045 pr_warning("map:%s key_type:%s has BTF type_size:%u != key_size:%u\n", 1048 BTF_INFO_VLEN(container_type->info) < 2) {
1046 map->name, name, (unsigned int)key_size, def->key_size); 1049 pr_warning("map:%s container_name:%s is an invalid container struct\n",
1050 map->name, container_name);
1047 return -EINVAL; 1051 return -EINVAL;
1048 } 1052 }
1049 1053
1050 /* Find value type from BTF */ 1054 key = (struct btf_member *)(container_type + 1);
1051 if (snprintf(name, max_name, "%s_value", map->name) == max_name) { 1055 value = key + 1;
1052 pr_warning("map:%s length of BTF value_type:%s_value is too long\n", 1056
1053 map->name, map->name); 1057 key_size = btf__resolve_size(btf, key->type);
1054 return -EINVAL; 1058 if (key_size < 0) {
1059 pr_warning("map:%s invalid BTF key_type_size\n",
1060 map->name);
1061 return key_size;
1055 } 1062 }
1056 1063
1057 value_id = btf__find_by_name(btf, name); 1064 if (def->key_size != key_size) {
1058 if (value_id < 0) { 1065 pr_warning("map:%s btf_key_type_size:%u != map_def_key_size:%u\n",
1059 pr_debug("map:%s value_type:%s cannot be found in BTF\n", 1066 map->name, (__u32)key_size, def->key_size);
1060 map->name, name); 1067 return -EINVAL;
1061 return value_id;
1062 } 1068 }
1063 1069
1064 value_size = btf__resolve_size(btf, value_id); 1070 value_size = btf__resolve_size(btf, value->type);
1065 if (value_size < 0) { 1071 if (value_size < 0) {
1066 pr_warning("map:%s value_type:%s cannot get the BTF type_size\n", 1072 pr_warning("map:%s invalid BTF value_type_size\n", map->name);
1067 map->name, name);
1068 return value_size; 1073 return value_size;
1069 } 1074 }
1070 1075
1071 if (def->value_size != value_size) { 1076 if (def->value_size != value_size) {
1072 pr_warning("map:%s value_type:%s has BTF type_size:%u != value_size:%u\n", 1077 pr_warning("map:%s btf_value_type_size:%u != map_def_value_size:%u\n",
1073 map->name, name, (unsigned int)value_size, def->value_size); 1078 map->name, (__u32)value_size, def->value_size);
1074 return -EINVAL; 1079 return -EINVAL;
1075 } 1080 }
1076 1081
1077 map->btf_key_type_id = key_id; 1082 map->btf_key_type_id = key->type;
1078 map->btf_value_type_id = value_id; 1083 map->btf_value_type_id = value->type;
1079 1084
1080 return 0; 1085 return 0;
1081} 1086}
@@ -2089,12 +2094,12 @@ const char *bpf_map__name(struct bpf_map *map)
2089 return map ? map->name : NULL; 2094 return map ? map->name : NULL;
2090} 2095}
2091 2096
2092uint32_t bpf_map__btf_key_type_id(const struct bpf_map *map) 2097__u32 bpf_map__btf_key_type_id(const struct bpf_map *map)
2093{ 2098{
2094 return map ? map->btf_key_type_id : 0; 2099 return map ? map->btf_key_type_id : 0;
2095} 2100}
2096 2101
2097uint32_t bpf_map__btf_value_type_id(const struct bpf_map *map) 2102__u32 bpf_map__btf_value_type_id(const struct bpf_map *map)
2098{ 2103{
2099 return map ? map->btf_value_type_id : 0; 2104 return map ? map->btf_value_type_id : 0;
2100} 2105}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 09976531aa74..b33ae02f7d0e 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -244,8 +244,8 @@ bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
244int bpf_map__fd(struct bpf_map *map); 244int bpf_map__fd(struct bpf_map *map);
245const struct bpf_map_def *bpf_map__def(struct bpf_map *map); 245const struct bpf_map_def *bpf_map__def(struct bpf_map *map);
246const char *bpf_map__name(struct bpf_map *map); 246const char *bpf_map__name(struct bpf_map *map);
247uint32_t bpf_map__btf_key_type_id(const struct bpf_map *map); 247__u32 bpf_map__btf_key_type_id(const struct bpf_map *map);
248uint32_t bpf_map__btf_value_type_id(const struct bpf_map *map); 248__u32 bpf_map__btf_value_type_id(const struct bpf_map *map);
249 249
250typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *); 250typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
251int bpf_map__set_priv(struct bpf_map *map, void *priv, 251int bpf_map__set_priv(struct bpf_map *map, void *priv,
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index f2f28b6c8915..810de20e8e26 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -158,6 +158,15 @@ struct bpf_map_def {
158 unsigned int numa_node; 158 unsigned int numa_node;
159}; 159};
160 160
161#define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \
162 struct ____btf_map_##name { \
163 type_key key; \
164 type_val value; \
165 }; \
166 struct ____btf_map_##name \
167 __attribute__ ((section(".maps." #name), used)) \
168 ____btf_map_##name = { }
169
161static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) = 170static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) =
162 (void *) BPF_FUNC_skb_load_bytes; 171 (void *) BPF_FUNC_skb_load_bytes;
163static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from, int len, int flags) = 172static int (*bpf_skb_store_bytes)(void *ctx, int off, void *from, int len, int flags) =
diff --git a/tools/testing/selftests/bpf/test_btf_haskv.c b/tools/testing/selftests/bpf/test_btf_haskv.c
index 8c7ca096ecf2..b21b876f475d 100644
--- a/tools/testing/selftests/bpf/test_btf_haskv.c
+++ b/tools/testing/selftests/bpf/test_btf_haskv.c
@@ -10,11 +10,6 @@ struct ipv_counts {
10 unsigned int v6; 10 unsigned int v6;
11}; 11};
12 12
13typedef int btf_map_key;
14typedef struct ipv_counts btf_map_value;
15btf_map_key dumm_key;
16btf_map_value dummy_value;
17
18struct bpf_map_def SEC("maps") btf_map = { 13struct bpf_map_def SEC("maps") btf_map = {
19 .type = BPF_MAP_TYPE_ARRAY, 14 .type = BPF_MAP_TYPE_ARRAY,
20 .key_size = sizeof(int), 15 .key_size = sizeof(int),
@@ -22,6 +17,8 @@ struct bpf_map_def SEC("maps") btf_map = {
22 .max_entries = 4, 17 .max_entries = 4,
23}; 18};
24 19
20BPF_ANNOTATE_KV_PAIR(btf_map, int, struct ipv_counts);
21
25struct dummy_tracepoint_args { 22struct dummy_tracepoint_args {
26 unsigned long long pad; 23 unsigned long long pad;
27 struct sock *sock; 24 struct sock *sock;