diff options
author | Maciej Żenczykowski <maze@google.com> | 2019-04-17 17:48:02 -0700 |
---|---|---|
committer | Maciej Zenczykowski <maze@google.com> | 2019-05-10 04:50:40 +0000 |
commit | 5fe026a927b26d63fd8227d67a925b5541c5fb79 (patch) | |
tree | aa88e23a5e869553736f75bbceafa2d7a8e24566 | |
parent | 7a1bf84cebfbf4c755be888605fd1d9c6e193ed9 (diff) | |
download | bpf-5fe026a927b26d63fd8227d67a925b5541c5fb79.tar.gz |
Provide a macro to define a map along with type safe accessors
Test: atest libbpf_android_test libnetdbpf_test netd_integration_test netd_unit_test netdutils_test resolv_integration_test resolv_unit_test
Bug: 130746652
Bug: 131268436
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Change-Id: Ib7a351ff876891a2296e32deebd0308ff9c7fcc8
Merged-In: Ib7a351ff876891a2296e32deebd0308ff9c7fcc8
(cherry picked from commit 6564b8eac46fc27dde807a39856386d98d2471c3)
-rw-r--r-- | progs/include/bpf_helpers.h | 60 |
1 files changed, 56 insertions, 4 deletions
diff --git a/progs/include/bpf_helpers.h b/progs/include/bpf_helpers.h index 3ae4291..408a981 100644 --- a/progs/include/bpf_helpers.h +++ b/progs/include/bpf_helpers.h @@ -11,11 +11,63 @@ * Helper functions called from eBPF programs written in C. These are * implemented in the kernel sources. */ + /* generic functions */ -static void* (*bpf_map_lookup_elem)(void* map, void* key) = (void*) BPF_FUNC_map_lookup_elem; -static int (*bpf_map_update_elem)(void* map, void* key, void* value, - unsigned long long flags) = (void*) BPF_FUNC_map_update_elem; -static int (*bpf_map_delete_elem)(void* map, void* key) = (void*) BPF_FUNC_map_delete_elem; + +/* + * Type-unsafe bpf map functions - avoid if possible. + * + * Using these it is possible to pass in keys/values of the wrong type/size, + * or, for 'unsafe_bpf_map_lookup_elem' receive into a pointer to the wrong type. + * You will not get a compile time failure, and for certain types of errors you + * might not even get a failure from the kernel's ebpf verifier during program load, + * instead stuff might just not work right at runtime. + * + * Instead please use: + * DEFINE_BPF_MAP(foo_map, TYPE, KeyType, ValueType, num_entries) + * where TYPE can be something like HASH or ARRAY, and num_entries is an integer. + * + * This defines the map (hence this should not be used in a header file included + * from multiple locations) and provides type safe accessors: + * ValueType * bpf_foo_map_lookup_elem(KeyType *) + * int bpf_foo_map_update_elem(KeyType *, ValueType *, flags) + * int bpf_foo_map_delete_elem(KeyType *) + * + * This will make sure that if you change the type of a map you'll get compile + * errors at any spots you forget to update with the new type. + */ +static void* (*unsafe_bpf_map_lookup_elem)(void* map, void* key) = (void*)BPF_FUNC_map_lookup_elem; +static int (*unsafe_bpf_map_update_elem)(void* map, void* key, void* value, + unsigned long long flags) = (void*) + BPF_FUNC_map_update_elem; +static int (*unsafe_bpf_map_delete_elem)(void* map, void* key) = (void*)BPF_FUNC_map_delete_elem; + +/* type safe macro to declare a map and related accessor functions */ +#define DEFINE_BPF_MAP_NO_ACCESSORS(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries) \ + struct bpf_map_def SEC("maps") the_map = { \ + .type = BPF_MAP_TYPE_##TYPE, \ + .key_size = sizeof(TypeOfKey), \ + .value_size = sizeof(TypeOfValue), \ + .max_entries = (num_entries), \ + }; + +#define DEFINE_BPF_MAP(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries) \ + DEFINE_BPF_MAP_NO_ACCESSORS(the_map, TYPE, TypeOfKey, TypeOfValue, num_entries) \ + \ + static inline __always_inline __unused TypeOfValue* bpf_##the_map##_lookup_elem( \ + TypeOfKey* k) { \ + return unsafe_bpf_map_lookup_elem(&the_map, k); \ + }; \ + \ + static inline __always_inline __unused int bpf_##the_map##_update_elem( \ + TypeOfKey* k, TypeOfValue* v, unsigned long long flags) { \ + return unsafe_bpf_map_update_elem(&the_map, k, v, flags); \ + }; \ + \ + static inline __always_inline __unused int bpf_##the_map##_delete_elem(TypeOfKey* k) { \ + return unsafe_bpf_map_delete_elem(&the_map, k); \ + }; + static int (*bpf_probe_read)(void* dst, int size, void* unsafe_ptr) = (void*) BPF_FUNC_probe_read; static unsigned long long (*bpf_ktime_get_ns)(void) = (void*) BPF_FUNC_ktime_get_ns; static int (*bpf_trace_printk)(const char* fmt, int fmt_size, ...) = (void*) BPF_FUNC_trace_printk; |