This patch set makes bpf_helpers.h and bpf_endian.h a part of libbpf itself for consumption by user BPF programs, not just selftests. It also splits off tracing helpers into bpf_tracing.h, which also becomes part of libbpf. Some of the legacy stuff (BPF_ANNOTATE_KV_PAIR, load_{byte,half,word}, bpf_map_def with unsupported fields, etc, is extracted into selftests-only bpf_legacy.h. All the selftests and samples are switched to use libbpf's headers and selftests' ones are removed. As part of this patch set we also add BPF_CORE_READ variadic macros, that are simplifying BPF CO-RE reads, especially the ones that have to follow few pointers. E.g., what in non-BPF world (and when using BCC) would be: int x = s->a->b.c->d; /* s, a, and b.c are pointers */ today would have to be written using explicit bpf_probe_read() calls as: void *t; int x; bpf_probe_read(&t, sizeof(t), s->a); bpf_probe_read(&t, sizeof(t), ((struct b *)t)->b.c); bpf_probe_read(&x, sizeof(x), ((struct c *)t)->d); This is super inconvenient and distracts from program logic a lot. Now, with added BPF_CORE_READ() macros, you can write the above as: int x = BPF_CORE_READ(s, a, b.c, d); Up to 9 levels of pointer chasing are supported, which should be enough for any practical purpose, hopefully, without adding too much boilerplate macro definitions (though there is admittedly some, given how variadic and recursive C macro have to be implemented). There is also BPF_CORE_READ_INTO() variant, which relies on caller to allocate space for result: int x; BPF_CORE_READ_INTO(&x, s, a, b.c, d); Result of last bpf_probe_read() call in the chain of calls is the result of BPF_CORE_READ_INTO(). If any intermediate bpf_probe_read() aall fails, then all the subsequent ones will fail too, so this is sufficient to know whether overall "operation" succeeded or not. No short-circuiting of bpf_probe_read()s is done, though. BPF_CORE_READ_STR_INTO() is added as well, which differs from BPF_CORE_READ_INTO() only in that last bpf_probe_read() call (to read final field after chasing pointers) is replaced with bpf_probe_read_str(). Result of bpf_probe_read_str() is returned as a result of BPF_CORE_READ_STR_INTO() macro itself, so that applications can track return code and/or length of read string. Patch set outline: - patch #1 undoes previously added GCC-specific bpf-helpers.h include; - patch #2 splits off legacy stuff we don't want to carry over; - patch #3 adjusts CO-RE reloc tests to avoid subsequent naming conflict with BPF_CORE_READ; - patch #4 splits off bpf_tracing.h; - patch #5 moves bpf_{helpers,endian,tracing}.h into libbpf and adjusts Makefiles to include libbpf for header search; - patch #6 adds variadic BPF_CORE_READ() macro family, as described above; - patch #7 adds tests to verify all possible levels of pointer nestedness for BPF_CORE_READ(), as well as correctness test for BPF_CORE_READ_STR_INTO(). v1->v2: - fix CO-RE reloc tests before bpf_helpers.h move (Song); - split off legacy stuff we don't want to carry over (Daniel, Toke); - split off bpf_tracing.h (Daniel); - fix samples/bpf build (assuming other fixes are applied); - switch remaining maps either to bpf_map_def_legacy or BTF-defined maps; Andrii Nakryiko (7): selftests/bpf: undo GCC-specific bpf_helpers.h changes selftests/bpf: samples/bpf: split off legacy stuff from bpf_helpers.h selftests/bpf: adjust CO-RE reloc tests for new bpf_core_read() macro selftests/bpf: split off tracing-only helpers into bpf_tracing.h libbpf: move bpf_{helpers,endian,tracing}.h into libbpf libbpf: add BPF_CORE_READ/BPF_CORE_READ_INTO helpers selftests/bpf: add BPF_CORE_READ and BPF_CORE_READ_STR_INTO macro tests samples/bpf/Makefile | 2 +- samples/bpf/hbm_kern.h | 28 +- samples/bpf/map_perf_test_kern.c | 24 +- samples/bpf/offwaketime_kern.c | 1 + samples/bpf/parse_ldabs.c | 1 + samples/bpf/sampleip_kern.c | 1 + samples/bpf/sockex1_kern.c | 1 + samples/bpf/sockex2_kern.c | 1 + samples/bpf/sockex3_kern.c | 1 + samples/bpf/spintest_kern.c | 1 + samples/bpf/tcbpf1_kern.c | 1 + samples/bpf/test_map_in_map_kern.c | 16 +- samples/bpf/test_overhead_kprobe_kern.c | 1 + samples/bpf/test_probe_write_user_kern.c | 1 + samples/bpf/trace_event_kern.c | 1 + samples/bpf/tracex1_kern.c | 1 + samples/bpf/tracex2_kern.c | 1 + samples/bpf/tracex3_kern.c | 1 + samples/bpf/tracex4_kern.c | 1 + samples/bpf/tracex5_kern.c | 1 + tools/lib/bpf/Makefile | 5 +- .../selftests => lib}/bpf/bpf_endian.h | 0 .../selftests => lib}/bpf/bpf_helpers.h | 391 +++++++----------- tools/lib/bpf/bpf_tracing.h | 195 +++++++++ tools/testing/selftests/bpf/Makefile | 2 +- tools/testing/selftests/bpf/bpf_legacy.h | 39 ++ .../selftests/bpf/prog_tests/core_reloc.c | 8 +- .../selftests/bpf/progs/core_reloc_types.h | 9 + tools/testing/selftests/bpf/progs/loop1.c | 1 + tools/testing/selftests/bpf/progs/loop2.c | 1 + tools/testing/selftests/bpf/progs/loop3.c | 1 + .../testing/selftests/bpf/progs/sockopt_sk.c | 13 +- tools/testing/selftests/bpf/progs/tcp_rtt.c | 13 +- .../selftests/bpf/progs/test_btf_haskv.c | 1 + .../selftests/bpf/progs/test_btf_newkv.c | 1 + .../bpf/progs/test_core_reloc_arrays.c | 10 +- .../bpf/progs/test_core_reloc_flavors.c | 8 +- .../bpf/progs/test_core_reloc_ints.c | 18 +- .../bpf/progs/test_core_reloc_kernel.c | 60 ++- .../bpf/progs/test_core_reloc_misc.c | 8 +- .../bpf/progs/test_core_reloc_mods.c | 18 +- .../bpf/progs/test_core_reloc_nesting.c | 6 +- .../bpf/progs/test_core_reloc_primitives.c | 12 +- .../bpf/progs/test_core_reloc_ptr_as_arr.c | 4 +- 44 files changed, 587 insertions(+), 323 deletions(-) rename tools/{testing/selftests => lib}/bpf/bpf_endian.h (100%) rename tools/{testing/selftests => lib}/bpf/bpf_helpers.h (66%) create mode 100644 tools/lib/bpf/bpf_tracing.h create mode 100644 tools/testing/selftests/bpf/bpf_legacy.h -- 2.17.1
Having GCC provide its own bpf-helper.h is not the right approach and is going to be changed. Undo bpf_helpers.h change before moving bpf_helpers.h into libbpf. Acked-by: Song Liu <songliubraving@fb.com> Acked-by: Ilya Leoshkevich <iii@linux.ibm.com> Acked-by: John Fastabend <john.fastabend@gmail.com> Signed-off-by: Andrii Nakryiko <andriin@fb.com> --- tools/testing/selftests/bpf/bpf_helpers.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index 54a50699bbfd..a1d9b97b8e15 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h @@ -13,8 +13,6 @@ ##__VA_ARGS__); \ }) -#ifdef __clang__ - /* helper macro to place programs, maps, license in * different sections in elf_bpf file. Section names * are interpreted by elf_bpf loader @@ -258,12 +256,6 @@ struct bpf_map_def { unsigned int numa_node; }; -#else - -#include <bpf-helpers.h> - -#endif - #define BPF_ANNOTATE_KV_PAIR(name, type_key, type_val) \ struct ____btf_map_##name { \ type_key key; \ -- 2.17.1
Split off few legacy things from bpf_helpers.h into separate bpf_legacy.h file: - load_{byte|half|word}; - remove extra inner_idx and numa_node fields from bpf_map_def and introduce bpf_map_def_legacy for use in samples; - move BPF_ANNOTATE_KV_PAIR into bpf_legacy.h. Adjust samples and selftests accordingly by either including bpf_legacy.h and using bpf_map_def_legacy, or switching to BTF-defined maps altogether. Signed-off-by: Andrii Nakryiko <andriin@fb.com> --- samples/bpf/hbm_kern.h | 28 +++++++------ samples/bpf/map_perf_test_kern.c | 23 +++++------ samples/bpf/parse_ldabs.c | 1 + samples/bpf/sockex1_kern.c | 1 + samples/bpf/sockex2_kern.c | 1 + samples/bpf/sockex3_kern.c | 1 + samples/bpf/tcbpf1_kern.c | 1 + samples/bpf/test_map_in_map_kern.c | 15 +++---- tools/testing/selftests/bpf/bpf_helpers.h | 24 +----------- tools/testing/selftests/bpf/bpf_legacy.h | 39 +++++++++++++++++++ .../testing/selftests/bpf/progs/sockopt_sk.c | 13 +++---- tools/testing/selftests/bpf/progs/tcp_rtt.c | 13 +++---- .../selftests/bpf/progs/test_btf_haskv.c | 1 + .../selftests/bpf/progs/test_btf_newkv.c | 1 + 14 files changed, 92 insertions(+), 70 deletions(-) create mode 100644 tools/testing/selftests/bpf/bpf_legacy.h diff --git a/samples/bpf/hbm_kern.h b/samples/bpf/hbm_kern.h index aa207a2eebbd..91880a0e9c2f 100644 --- a/samples/bpf/hbm_kern.h +++ b/samples/bpf/hbm_kern.h @@ -24,6 +24,7 @@ #include <net/inet_ecn.h> #include "bpf_endian.h" #include "bpf_helpers.h" +#include "bpf_legacy.h" #include "hbm.h" #define DROP_PKT 0 @@ -59,21 +60,18 @@ #define BYTES_PER_NS(delta, rate) ((((u64)(delta)) * (rate)) >> 20) #define BYTES_TO_NS(bytes, rate) div64_u64(((u64)(bytes)) << 20, (u64)(rate)) -struct bpf_map_def SEC("maps") queue_state = { - .type = BPF_MAP_TYPE_CGROUP_STORAGE, - .key_size = sizeof(struct bpf_cgroup_storage_key), - .value_size = sizeof(struct hbm_vqueue), -}; -BPF_ANNOTATE_KV_PAIR(queue_state, struct bpf_cgroup_storage_key, - struct hbm_vqueue); - -struct bpf_map_def SEC("maps") queue_stats = { - .type = BPF_MAP_TYPE_ARRAY, - .key_size = sizeof(u32), - .value_size = sizeof(struct hbm_queue_stats), - .max_entries = 1, -}; -BPF_ANNOTATE_KV_PAIR(queue_stats, int, struct hbm_queue_stats); +struct { + __uint(type, BPF_MAP_TYPE_CGROUP_STORAGE); + __type(key, struct bpf_cgroup_storage_key); + __type(value, struct hbm_vqueue); +} queue_state SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 1); + __type(key, u32); + __type(value, struct hvm_queue_stats); +} queue_stats SEC(".maps"); struct hbm_pkt_info { int cwnd; diff --git a/samples/bpf/map_perf_test_kern.c b/samples/bpf/map_perf_test_kern.c index 2b2ffb97018b..f47ee513cb7c 100644 --- a/samples/bpf/map_perf_test_kern.c +++ b/samples/bpf/map_perf_test_kern.c @@ -9,25 +9,26 @@ #include <linux/version.h> #include <uapi/linux/bpf.h> #include "bpf_helpers.h" +#include "bpf_legacy.h" #define MAX_ENTRIES 1000 #define MAX_NR_CPUS 1024 -struct bpf_map_def SEC("maps") hash_map = { +struct bpf_map_def_legacy SEC("maps") hash_map = { .type = BPF_MAP_TYPE_HASH, .key_size = sizeof(u32), .value_size = sizeof(long), .max_entries = MAX_ENTRIES, }; -struct bpf_map_def SEC("maps") lru_hash_map = { +struct bpf_map_def_legacy SEC("maps") lru_hash_map = { .type = BPF_MAP_TYPE_LRU_HASH, .key_size = sizeof(u32), .value_size = sizeof(long), .max_entries = 10000, }; -struct bpf_map_def SEC("maps") nocommon_lru_hash_map = { +struct bpf_map_def_legacy SEC("maps") nocommon_lru_hash_map = { .type = BPF_MAP_TYPE_LRU_HASH, .key_size = sizeof(u32), .value_size = sizeof(long), @@ -35,7 +36,7 @@ struct bpf_map_def SEC("maps") nocommon_lru_hash_map = { .map_flags = BPF_F_NO_COMMON_LRU, }; -struct bpf_map_def SEC("maps") inner_lru_hash_map = { +struct bpf_map_def_legacy SEC("maps") inner_lru_hash_map = { .type = BPF_MAP_TYPE_LRU_HASH, .key_size = sizeof(u32), .value_size = sizeof(long), @@ -44,20 +45,20 @@ struct bpf_map_def SEC("maps") inner_lru_hash_map = { .numa_node = 0, }; -struct bpf_map_def SEC("maps") array_of_lru_hashs = { +struct bpf_map_def_legacy SEC("maps") array_of_lru_hashs = { .type = BPF_MAP_TYPE_ARRAY_OF_MAPS, .key_size = sizeof(u32), .max_entries = MAX_NR_CPUS, }; -struct bpf_map_def SEC("maps") percpu_hash_map = { +struct bpf_map_def_legacy SEC("maps") percpu_hash_map = { .type = BPF_MAP_TYPE_PERCPU_HASH, .key_size = sizeof(u32), .value_size = sizeof(long), .max_entries = MAX_ENTRIES, }; -struct bpf_map_def SEC("maps") hash_map_alloc = { +struct bpf_map_def_legacy SEC("maps") hash_map_alloc = { .type = BPF_MAP_TYPE_HASH, .key_size = sizeof(u32), .value_size = sizeof(long), @@ -65,7 +66,7 @@ struct bpf_map_def SEC("maps") hash_map_alloc = { .map_flags = BPF_F_NO_PREALLOC, }; -struct bpf_map_def SEC("maps") percpu_hash_map_alloc = { +struct bpf_map_def_legacy SEC("maps") percpu_hash_map_alloc = { .type = BPF_MAP_TYPE_PERCPU_HASH, .key_size = sizeof(u32), .value_size = sizeof(long), @@ -73,7 +74,7 @@ struct bpf_map_def SEC("maps") percpu_hash_map_alloc = { .map_flags = BPF_F_NO_PREALLOC, }; -struct bpf_map_def SEC("maps") lpm_trie_map_alloc = { +struct bpf_map_def_legacy SEC("maps") lpm_trie_map_alloc = { .type = BPF_MAP_TYPE_LPM_TRIE, .key_size = 8, .value_size = sizeof(long), @@ -81,14 +82,14 @@ struct bpf_map_def SEC("maps") lpm_trie_map_alloc = { .map_flags = BPF_F_NO_PREALLOC, }; -struct bpf_map_def SEC("maps") array_map = { +struct bpf_map_def_legacy SEC("maps") array_map = { .type = BPF_MAP_TYPE_ARRAY, .key_size = sizeof(u32), .value_size = sizeof(long), .max_entries = MAX_ENTRIES, }; -struct bpf_map_def SEC("maps") lru_hash_lookup_map = { +struct bpf_map_def_legacy SEC("maps") lru_hash_lookup_map = { .type = BPF_MAP_TYPE_LRU_HASH, .key_size = sizeof(u32), .value_size = sizeof(long), diff --git a/samples/bpf/parse_ldabs.c b/samples/bpf/parse_ldabs.c index 6db6b21fdc6d..ef5892377beb 100644 --- a/samples/bpf/parse_ldabs.c +++ b/samples/bpf/parse_ldabs.c @@ -12,6 +12,7 @@ #include <linux/udp.h> #include <uapi/linux/bpf.h> #include "bpf_helpers.h" +#include "bpf_legacy.h" #define DEFAULT_PKTGEN_UDP_PORT 9 #define IP_MF 0x2000 diff --git a/samples/bpf/sockex1_kern.c b/samples/bpf/sockex1_kern.c index ed18e9a4909c..f96943f443ab 100644 --- a/samples/bpf/sockex1_kern.c +++ b/samples/bpf/sockex1_kern.c @@ -3,6 +3,7 @@ #include <uapi/linux/if_packet.h> #include <uapi/linux/ip.h> #include "bpf_helpers.h" +#include "bpf_legacy.h" struct bpf_map_def SEC("maps") my_map = { .type = BPF_MAP_TYPE_ARRAY, diff --git a/samples/bpf/sockex2_kern.c b/samples/bpf/sockex2_kern.c index f2f9dbc021b0..5566fa7d92fa 100644 --- a/samples/bpf/sockex2_kern.c +++ b/samples/bpf/sockex2_kern.c @@ -1,5 +1,6 @@ #include <uapi/linux/bpf.h> #include "bpf_helpers.h" +#include "bpf_legacy.h" #include <uapi/linux/in.h> #include <uapi/linux/if.h> #include <uapi/linux/if_ether.h> diff --git a/samples/bpf/sockex3_kern.c b/samples/bpf/sockex3_kern.c index c527b57d3ec8..151dd842ecc0 100644 --- a/samples/bpf/sockex3_kern.c +++ b/samples/bpf/sockex3_kern.c @@ -6,6 +6,7 @@ */ #include <uapi/linux/bpf.h> #include "bpf_helpers.h" +#include "bpf_legacy.h" #include <uapi/linux/in.h> #include <uapi/linux/if.h> #include <uapi/linux/if_ether.h> diff --git a/samples/bpf/tcbpf1_kern.c b/samples/bpf/tcbpf1_kern.c index 274c884c87fe..ff43341bdfce 100644 --- a/samples/bpf/tcbpf1_kern.c +++ b/samples/bpf/tcbpf1_kern.c @@ -8,6 +8,7 @@ #include <uapi/linux/filter.h> #include <uapi/linux/pkt_cls.h> #include "bpf_helpers.h" +#include "bpf_legacy.h" /* compiler workaround */ #define _htonl __builtin_bswap32 diff --git a/samples/bpf/test_map_in_map_kern.c b/samples/bpf/test_map_in_map_kern.c index 42c44d091dd1..8101bf3dc7f7 100644 --- a/samples/bpf/test_map_in_map_kern.c +++ b/samples/bpf/test_map_in_map_kern.c @@ -11,11 +11,12 @@ #include <uapi/linux/bpf.h> #include <uapi/linux/in6.h> #include "bpf_helpers.h" +#include "bpf_legacy.h" #define MAX_NR_PORTS 65536 /* map #0 */ -struct bpf_map_def SEC("maps") port_a = { +struct bpf_map_def_legacy SEC("maps") port_a = { .type = BPF_MAP_TYPE_ARRAY, .key_size = sizeof(u32), .value_size = sizeof(int), @@ -23,7 +24,7 @@ struct bpf_map_def SEC("maps") port_a = { }; /* map #1 */ -struct bpf_map_def SEC("maps") port_h = { +struct bpf_map_def_legacy SEC("maps") port_h = { .type = BPF_MAP_TYPE_HASH, .key_size = sizeof(u32), .value_size = sizeof(int), @@ -31,7 +32,7 @@ struct bpf_map_def SEC("maps") port_h = { }; /* map #2 */ -struct bpf_map_def SEC("maps") reg_result_h = { +struct bpf_map_def_legacy SEC("maps") reg_result_h = { .type = BPF_MAP_TYPE_HASH, .key_size = sizeof(u32), .value_size = sizeof(int), @@ -39,7 +40,7 @@ struct bpf_map_def SEC("maps") reg_result_h = { }; /* map #3 */ -struct bpf_map_def SEC("maps") inline_result_h = { +struct bpf_map_def_legacy SEC("maps") inline_result_h = { .type = BPF_MAP_TYPE_HASH, .key_size = sizeof(u32), .value_size = sizeof(int), @@ -47,7 +48,7 @@ struct bpf_map_def SEC("maps") inline_result_h = { }; /* map #4 */ /* Test case #0 */ -struct bpf_map_def SEC("maps") a_of_port_a = { +struct bpf_map_def_legacy SEC("maps") a_of_port_a = { .type = BPF_MAP_TYPE_ARRAY_OF_MAPS, .key_size = sizeof(u32), .inner_map_idx = 0, /* map_fd[0] is port_a */ @@ -55,7 +56,7 @@ struct bpf_map_def SEC("maps") a_of_port_a = { }; /* map #5 */ /* Test case #1 */ -struct bpf_map_def SEC("maps") h_of_port_a = { +struct bpf_map_def_legacy SEC("maps") h_of_port_a = { .type = BPF_MAP_TYPE_HASH_OF_MAPS, .key_size = sizeof(u32), .inner_map_idx = 0, /* map_fd[0] is port_a */ @@ -63,7 +64,7 @@ struct bpf_map_def SEC("maps") h_of_port_a = { }; /* map #6 */ /* Test case #2 */ -struct bpf_map_def SEC("maps") h_of_port_h = { +struct bpf_map_def_legacy SEC("maps") h_of_port_h = { .type = BPF_MAP_TYPE_HASH_OF_MAPS, .key_size = sizeof(u32), .inner_map_idx = 1, /* map_fd[1] is port_h */ diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index a1d9b97b8e15..7b75c38238e4 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h @@ -232,19 +232,8 @@ static long long (*bpf_tcp_gen_syncookie)(struct bpf_sock *sk, void *ip, int ip_len, void *tcp, int tcp_len) = (void *) BPF_FUNC_tcp_gen_syncookie; -/* llvm builtin functions that eBPF C program may use to - * emit BPF_LD_ABS and BPF_LD_IND instructions - */ -struct sk_buff; -unsigned long long load_byte(void *skb, - unsigned long long off) asm("llvm.bpf.load.byte"); -unsigned long long load_half(void *skb, - unsigned long long off) asm("llvm.bpf.load.half"); -unsigned long long load_word(void *skb, - unsigned long long off) asm("llvm.bpf.load.word"); - /* a helper structure used by eBPF C program - * to describe map attributes to elf_bpf loader + * to describe BPF map attributes to libbpf loader */ struct bpf_map_def { unsigned int type; @@ -252,19 +241,8 @@ struct bpf_map_def { unsigned int value_size; unsigned int max_entries; unsigned int map_flags; - unsigned int inner_map_idx; - 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) = (void *) BPF_FUNC_skb_load_bytes; static int (*bpf_skb_load_bytes_relative)(void *ctx, int off, void *to, int len, __u32 start_header) = diff --git a/tools/testing/selftests/bpf/bpf_legacy.h b/tools/testing/selftests/bpf/bpf_legacy.h new file mode 100644 index 000000000000..6f8988738bc1 --- /dev/null +++ b/tools/testing/selftests/bpf/bpf_legacy.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ +#ifndef __BPF_LEGACY__ +#define __BPF_LEGACY__ + +/* + * legacy bpf_map_def with extra fields supported only by bpf_load(), do not + * use outside of samples/bpf + */ +struct bpf_map_def_legacy { + unsigned int type; + unsigned int key_size; + unsigned int value_size; + unsigned int max_entries; + unsigned int map_flags; + unsigned int inner_map_idx; + 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 = { } + +/* llvm builtin functions that eBPF C program may use to + * emit BPF_LD_ABS and BPF_LD_IND instructions + */ +unsigned long long load_byte(void *skb, + unsigned long long off) asm("llvm.bpf.load.byte"); +unsigned long long load_half(void *skb, + unsigned long long off) asm("llvm.bpf.load.half"); +unsigned long long load_word(void *skb, + unsigned long long off) asm("llvm.bpf.load.word"); + +#endif + diff --git a/tools/testing/selftests/bpf/progs/sockopt_sk.c b/tools/testing/selftests/bpf/progs/sockopt_sk.c index 9a3d1c79e6fe..1bafbb944e37 100644 --- a/tools/testing/selftests/bpf/progs/sockopt_sk.c +++ b/tools/testing/selftests/bpf/progs/sockopt_sk.c @@ -14,13 +14,12 @@ struct sockopt_sk { __u8 val; }; -struct bpf_map_def SEC("maps") socket_storage_map = { - .type = BPF_MAP_TYPE_SK_STORAGE, - .key_size = sizeof(int), - .value_size = sizeof(struct sockopt_sk), - .map_flags = BPF_F_NO_PREALLOC, -}; -BPF_ANNOTATE_KV_PAIR(socket_storage_map, int, struct sockopt_sk); +struct { + __uint(type, BPF_MAP_TYPE_SK_STORAGE); + __uint(map_flags, BPF_F_NO_PREALLOC); + __type(key, int); + __type(value, struct sockopt_sk); +} socket_storage_map SEC(".maps"); SEC("cgroup/getsockopt") int _getsockopt(struct bpf_sockopt *ctx) diff --git a/tools/testing/selftests/bpf/progs/tcp_rtt.c b/tools/testing/selftests/bpf/progs/tcp_rtt.c index 233bdcb1659e..2cf813a06b83 100644 --- a/tools/testing/selftests/bpf/progs/tcp_rtt.c +++ b/tools/testing/selftests/bpf/progs/tcp_rtt.c @@ -13,13 +13,12 @@ struct tcp_rtt_storage { __u32 icsk_retransmits; }; -struct bpf_map_def SEC("maps") socket_storage_map = { - .type = BPF_MAP_TYPE_SK_STORAGE, - .key_size = sizeof(int), - .value_size = sizeof(struct tcp_rtt_storage), - .map_flags = BPF_F_NO_PREALLOC, -}; -BPF_ANNOTATE_KV_PAIR(socket_storage_map, int, struct tcp_rtt_storage); +struct { + __uint(type, BPF_MAP_TYPE_SK_STORAGE); + __uint(map_flags, BPF_F_NO_PREALLOC); + __type(key, int); + __type(value, struct tcp_rtt_storage); +} socket_storage_map SEC(".maps"); SEC("sockops") int _sockops(struct bpf_sock_ops *ctx) diff --git a/tools/testing/selftests/bpf/progs/test_btf_haskv.c b/tools/testing/selftests/bpf/progs/test_btf_haskv.c index e5c79fe0ffdb..763c51447c19 100644 --- a/tools/testing/selftests/bpf/progs/test_btf_haskv.c +++ b/tools/testing/selftests/bpf/progs/test_btf_haskv.c @@ -2,6 +2,7 @@ /* Copyright (c) 2018 Facebook */ #include <linux/bpf.h> #include "bpf_helpers.h" +#include "bpf_legacy.h" int _version SEC("version") = 1; diff --git a/tools/testing/selftests/bpf/progs/test_btf_newkv.c b/tools/testing/selftests/bpf/progs/test_btf_newkv.c index 5ee3622ddebb..96f9e8451029 100644 --- a/tools/testing/selftests/bpf/progs/test_btf_newkv.c +++ b/tools/testing/selftests/bpf/progs/test_btf_newkv.c @@ -2,6 +2,7 @@ /* Copyright (c) 2018 Facebook */ #include <linux/bpf.h> #include "bpf_helpers.h" +#include "bpf_legacy.h" int _version SEC("version") = 1; -- 2.17.1
To allow adding a variadic BPF_CORE_READ macro with slightly different syntax and semantics, define CORE_READ in CO-RE reloc tests, which is a thin wrapper around low-level bpf_core_read() macro, which in turn is just a wrapper around bpf_probe_read(). Acked-by: John Fastabend <john.fastabend@gmail.com> Acked-by: Song Liu <songliubraving@fb.com> Signed-off-by: Andrii Nakryiko <andriin@fb.com> --- tools/testing/selftests/bpf/bpf_helpers.h | 8 ++++---- .../bpf/progs/test_core_reloc_arrays.c | 10 ++++++---- .../bpf/progs/test_core_reloc_flavors.c | 8 +++++--- .../selftests/bpf/progs/test_core_reloc_ints.c | 18 ++++++++++-------- .../bpf/progs/test_core_reloc_kernel.c | 6 ++++-- .../selftests/bpf/progs/test_core_reloc_misc.c | 8 +++++--- .../selftests/bpf/progs/test_core_reloc_mods.c | 18 ++++++++++-------- .../bpf/progs/test_core_reloc_nesting.c | 6 ++++-- .../bpf/progs/test_core_reloc_primitives.c | 12 +++++++----- .../bpf/progs/test_core_reloc_ptr_as_arr.c | 4 +++- 10 files changed, 58 insertions(+), 40 deletions(-) diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index 7b75c38238e4..5210cc7d7c5c 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h @@ -483,7 +483,7 @@ struct pt_regs; #endif /* - * BPF_CORE_READ abstracts away bpf_probe_read() call and captures offset + * bpf_core_read() abstracts away bpf_probe_read() call and captures offset * relocation for source address using __builtin_preserve_access_index() * built-in, provided by Clang. * @@ -498,8 +498,8 @@ struct pt_regs; * actual field offset, based on target kernel BTF type that matches original * (local) BTF, used to record relocation. */ -#define BPF_CORE_READ(dst, src) \ - bpf_probe_read((dst), sizeof(*(src)), \ - __builtin_preserve_access_index(src)) +#define bpf_core_read(dst, sz, src) \ + bpf_probe_read(dst, sz, \ + (const void *)__builtin_preserve_access_index(src)) #endif diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c b/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c index bf67f0fdf743..58efe4944594 100644 --- a/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c @@ -31,6 +31,8 @@ struct core_reloc_arrays { struct core_reloc_arrays_substruct d[1][2]; }; +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) + SEC("raw_tracepoint/sys_enter") int test_core_arrays(void *ctx) { @@ -38,16 +40,16 @@ int test_core_arrays(void *ctx) struct core_reloc_arrays_output *out = (void *)&data.out; /* in->a[2] */ - if (BPF_CORE_READ(&out->a2, &in->a[2])) + if (CORE_READ(&out->a2, &in->a[2])) return 1; /* in->b[1][2][3] */ - if (BPF_CORE_READ(&out->b123, &in->b[1][2][3])) + if (CORE_READ(&out->b123, &in->b[1][2][3])) return 1; /* in->c[1].c */ - if (BPF_CORE_READ(&out->c1c, &in->c[1].c)) + if (CORE_READ(&out->c1c, &in->c[1].c)) return 1; /* in->d[0][0].d */ - if (BPF_CORE_READ(&out->d00d, &in->d[0][0].d)) + if (CORE_READ(&out->d00d, &in->d[0][0].d)) return 1; return 0; diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_flavors.c b/tools/testing/selftests/bpf/progs/test_core_reloc_flavors.c index 9fda73e87972..3348acc7e50b 100644 --- a/tools/testing/selftests/bpf/progs/test_core_reloc_flavors.c +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_flavors.c @@ -39,6 +39,8 @@ struct core_reloc_flavors___weird { }; }; +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) + SEC("raw_tracepoint/sys_enter") int test_core_flavors(void *ctx) { @@ -48,13 +50,13 @@ int test_core_flavors(void *ctx) struct core_reloc_flavors *out = (void *)&data.out; /* read a using weird layout */ - if (BPF_CORE_READ(&out->a, &in_weird->a)) + if (CORE_READ(&out->a, &in_weird->a)) return 1; /* read b using reversed layout */ - if (BPF_CORE_READ(&out->b, &in_rev->b)) + if (CORE_READ(&out->b, &in_rev->b)) return 1; /* read c using original layout */ - if (BPF_CORE_READ(&out->c, &in_orig->c)) + if (CORE_READ(&out->c, &in_orig->c)) return 1; return 0; diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_ints.c b/tools/testing/selftests/bpf/progs/test_core_reloc_ints.c index d99233c8008a..cfe16ede48dd 100644 --- a/tools/testing/selftests/bpf/progs/test_core_reloc_ints.c +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_ints.c @@ -23,20 +23,22 @@ struct core_reloc_ints { int64_t s64_field; }; +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) + SEC("raw_tracepoint/sys_enter") int test_core_ints(void *ctx) { struct core_reloc_ints *in = (void *)&data.in; struct core_reloc_ints *out = (void *)&data.out; - if (BPF_CORE_READ(&out->u8_field, &in->u8_field) || - BPF_CORE_READ(&out->s8_field, &in->s8_field) || - BPF_CORE_READ(&out->u16_field, &in->u16_field) || - BPF_CORE_READ(&out->s16_field, &in->s16_field) || - BPF_CORE_READ(&out->u32_field, &in->u32_field) || - BPF_CORE_READ(&out->s32_field, &in->s32_field) || - BPF_CORE_READ(&out->u64_field, &in->u64_field) || - BPF_CORE_READ(&out->s64_field, &in->s64_field)) + if (CORE_READ(&out->u8_field, &in->u8_field) || + CORE_READ(&out->s8_field, &in->s8_field) || + CORE_READ(&out->u16_field, &in->u16_field) || + CORE_READ(&out->s16_field, &in->s16_field) || + CORE_READ(&out->u32_field, &in->u32_field) || + CORE_READ(&out->s32_field, &in->s32_field) || + CORE_READ(&out->u64_field, &in->u64_field) || + CORE_READ(&out->s64_field, &in->s64_field)) return 1; return 0; diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c b/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c index 37e02aa3f0c8..e5308026cfda 100644 --- a/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c @@ -17,6 +17,8 @@ struct task_struct { int tgid; }; +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) + SEC("raw_tracepoint/sys_enter") int test_core_kernel(void *ctx) { @@ -24,8 +26,8 @@ int test_core_kernel(void *ctx) uint64_t pid_tgid = bpf_get_current_pid_tgid(); int pid, tgid; - if (BPF_CORE_READ(&pid, &task->pid) || - BPF_CORE_READ(&tgid, &task->tgid)) + if (CORE_READ(&pid, &task->pid) || + CORE_READ(&tgid, &task->tgid)) return 1; /* validate pid + tgid matches */ diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_misc.c b/tools/testing/selftests/bpf/progs/test_core_reloc_misc.c index c59984bd3e23..40c4638ab5cc 100644 --- a/tools/testing/selftests/bpf/progs/test_core_reloc_misc.c +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_misc.c @@ -32,6 +32,8 @@ struct core_reloc_misc_extensible { int b; }; +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) + SEC("raw_tracepoint/sys_enter") int test_core_misc(void *ctx) { @@ -41,15 +43,15 @@ int test_core_misc(void *ctx) struct core_reloc_misc_output *out = (void *)&data.out; /* record two different relocations with the same accessor string */ - if (BPF_CORE_READ(&out->a, &in_a->a1) || /* accessor: 0:0 */ - BPF_CORE_READ(&out->b, &in_b->b1)) /* accessor: 0:0 */ + if (CORE_READ(&out->a, &in_a->a1) || /* accessor: 0:0 */ + CORE_READ(&out->b, &in_b->b1)) /* accessor: 0:0 */ return 1; /* Validate relocations capture array-only accesses for structs with * fixed header, but with potentially extendable tail. This will read * first 4 bytes of 2nd element of in_ext array of potentially * variably sized struct core_reloc_misc_extensible. */ - if (BPF_CORE_READ(&out->c, &in_ext[2])) /* accessor: 2 */ + if (CORE_READ(&out->c, &in_ext[2])) /* accessor: 2 */ return 1; return 0; diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_mods.c b/tools/testing/selftests/bpf/progs/test_core_reloc_mods.c index f98b942c062b..99fc9ee21895 100644 --- a/tools/testing/selftests/bpf/progs/test_core_reloc_mods.c +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_mods.c @@ -41,20 +41,22 @@ struct core_reloc_mods { core_reloc_mods_substruct_t h; }; +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) + SEC("raw_tracepoint/sys_enter") int test_core_mods(void *ctx) { struct core_reloc_mods *in = (void *)&data.in; struct core_reloc_mods_output *out = (void *)&data.out; - if (BPF_CORE_READ(&out->a, &in->a) || - BPF_CORE_READ(&out->b, &in->b) || - BPF_CORE_READ(&out->c, &in->c) || - BPF_CORE_READ(&out->d, &in->d) || - BPF_CORE_READ(&out->e, &in->e[2]) || - BPF_CORE_READ(&out->f, &in->f[1]) || - BPF_CORE_READ(&out->g, &in->g.x) || - BPF_CORE_READ(&out->h, &in->h.y)) + if (CORE_READ(&out->a, &in->a) || + CORE_READ(&out->b, &in->b) || + CORE_READ(&out->c, &in->c) || + CORE_READ(&out->d, &in->d) || + CORE_READ(&out->e, &in->e[2]) || + CORE_READ(&out->f, &in->f[1]) || + CORE_READ(&out->g, &in->g.x) || + CORE_READ(&out->h, &in->h.y)) return 1; return 0; diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_nesting.c b/tools/testing/selftests/bpf/progs/test_core_reloc_nesting.c index 3ca30cec2b39..c84fff3bdd72 100644 --- a/tools/testing/selftests/bpf/progs/test_core_reloc_nesting.c +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_nesting.c @@ -30,15 +30,17 @@ struct core_reloc_nesting { } b; }; +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) + SEC("raw_tracepoint/sys_enter") int test_core_nesting(void *ctx) { struct core_reloc_nesting *in = (void *)&data.in; struct core_reloc_nesting *out = (void *)&data.out; - if (BPF_CORE_READ(&out->a.a.a, &in->a.a.a)) + if (CORE_READ(&out->a.a.a, &in->a.a.a)) return 1; - if (BPF_CORE_READ(&out->b.b.b, &in->b.b.b)) + if (CORE_READ(&out->b.b.b, &in->b.b.b)) return 1; return 0; diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_primitives.c b/tools/testing/selftests/bpf/progs/test_core_reloc_primitives.c index add52f23ab35..4038e9907162 100644 --- a/tools/testing/selftests/bpf/progs/test_core_reloc_primitives.c +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_primitives.c @@ -25,17 +25,19 @@ struct core_reloc_primitives { int (*f)(const char *); }; +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) + SEC("raw_tracepoint/sys_enter") int test_core_primitives(void *ctx) { struct core_reloc_primitives *in = (void *)&data.in; struct core_reloc_primitives *out = (void *)&data.out; - if (BPF_CORE_READ(&out->a, &in->a) || - BPF_CORE_READ(&out->b, &in->b) || - BPF_CORE_READ(&out->c, &in->c) || - BPF_CORE_READ(&out->d, &in->d) || - BPF_CORE_READ(&out->f, &in->f)) + if (CORE_READ(&out->a, &in->a) || + CORE_READ(&out->b, &in->b) || + CORE_READ(&out->c, &in->c) || + CORE_READ(&out->d, &in->d) || + CORE_READ(&out->f, &in->f)) return 1; return 0; diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_ptr_as_arr.c b/tools/testing/selftests/bpf/progs/test_core_reloc_ptr_as_arr.c index 526b7ddc7ea1..414d44620258 100644 --- a/tools/testing/selftests/bpf/progs/test_core_reloc_ptr_as_arr.c +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_ptr_as_arr.c @@ -16,13 +16,15 @@ struct core_reloc_ptr_as_arr { int a; }; +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) + SEC("raw_tracepoint/sys_enter") int test_core_ptr_as_arr(void *ctx) { struct core_reloc_ptr_as_arr *in = (void *)&data.in; struct core_reloc_ptr_as_arr *out = (void *)&data.out; - if (BPF_CORE_READ(&out->a, &in[2].a)) + if (CORE_READ(&out->a, &in[2].a)) return 1; return 0; -- 2.17.1
Split-off PT_REGS-related helpers into bpf_tracing.h header. Adjust selftests and samples to include it where necessary. Signed-off-by: Andrii Nakryiko <andriin@fb.com> --- samples/bpf/map_perf_test_kern.c | 1 + samples/bpf/offwaketime_kern.c | 1 + samples/bpf/sampleip_kern.c | 1 + samples/bpf/spintest_kern.c | 1 + samples/bpf/test_map_in_map_kern.c | 1 + samples/bpf/test_overhead_kprobe_kern.c | 1 + samples/bpf/test_probe_write_user_kern.c | 1 + samples/bpf/trace_event_kern.c | 1 + samples/bpf/tracex1_kern.c | 1 + samples/bpf/tracex2_kern.c | 1 + samples/bpf/tracex3_kern.c | 1 + samples/bpf/tracex4_kern.c | 1 + samples/bpf/tracex5_kern.c | 1 + tools/testing/selftests/bpf/bpf_helpers.h | 210 ++-------------------- tools/testing/selftests/bpf/bpf_tracing.h | 195 ++++++++++++++++++++ tools/testing/selftests/bpf/progs/loop1.c | 1 + tools/testing/selftests/bpf/progs/loop2.c | 1 + tools/testing/selftests/bpf/progs/loop3.c | 1 + 18 files changed, 221 insertions(+), 200 deletions(-) create mode 100644 tools/testing/selftests/bpf/bpf_tracing.h diff --git a/samples/bpf/map_perf_test_kern.c b/samples/bpf/map_perf_test_kern.c index f47ee513cb7c..5c11aefbc489 100644 --- a/samples/bpf/map_perf_test_kern.c +++ b/samples/bpf/map_perf_test_kern.c @@ -10,6 +10,7 @@ #include <uapi/linux/bpf.h> #include "bpf_helpers.h" #include "bpf_legacy.h" +#include "bpf_tracing.h" #define MAX_ENTRIES 1000 #define MAX_NR_CPUS 1024 diff --git a/samples/bpf/offwaketime_kern.c b/samples/bpf/offwaketime_kern.c index e7d9a0a3d45b..9cb5207a692f 100644 --- a/samples/bpf/offwaketime_kern.c +++ b/samples/bpf/offwaketime_kern.c @@ -6,6 +6,7 @@ */ #include <uapi/linux/bpf.h> #include "bpf_helpers.h" +#include "bpf_tracing.h" #include <uapi/linux/ptrace.h> #include <uapi/linux/perf_event.h> #include <linux/version.h> diff --git a/samples/bpf/sampleip_kern.c b/samples/bpf/sampleip_kern.c index ceabf31079cf..4a190893894f 100644 --- a/samples/bpf/sampleip_kern.c +++ b/samples/bpf/sampleip_kern.c @@ -9,6 +9,7 @@ #include <uapi/linux/bpf.h> #include <uapi/linux/bpf_perf_event.h> #include "bpf_helpers.h" +#include "bpf_tracing.h" #define MAX_IPS 8192 diff --git a/samples/bpf/spintest_kern.c b/samples/bpf/spintest_kern.c index ce0167d09cdc..6e9478aa2938 100644 --- a/samples/bpf/spintest_kern.c +++ b/samples/bpf/spintest_kern.c @@ -10,6 +10,7 @@ #include <uapi/linux/bpf.h> #include <uapi/linux/perf_event.h> #include "bpf_helpers.h" +#include "bpf_tracing.h" struct bpf_map_def SEC("maps") my_map = { .type = BPF_MAP_TYPE_HASH, diff --git a/samples/bpf/test_map_in_map_kern.c b/samples/bpf/test_map_in_map_kern.c index 8101bf3dc7f7..4f80cbe74c72 100644 --- a/samples/bpf/test_map_in_map_kern.c +++ b/samples/bpf/test_map_in_map_kern.c @@ -12,6 +12,7 @@ #include <uapi/linux/in6.h> #include "bpf_helpers.h" #include "bpf_legacy.h" +#include "bpf_tracing.h" #define MAX_NR_PORTS 65536 diff --git a/samples/bpf/test_overhead_kprobe_kern.c b/samples/bpf/test_overhead_kprobe_kern.c index 468a66a92ef9..8d2518e68db9 100644 --- a/samples/bpf/test_overhead_kprobe_kern.c +++ b/samples/bpf/test_overhead_kprobe_kern.c @@ -8,6 +8,7 @@ #include <linux/ptrace.h> #include <uapi/linux/bpf.h> #include "bpf_helpers.h" +#include "bpf_tracing.h" #define _(P) ({typeof(P) val = 0; bpf_probe_read(&val, sizeof(val), &P); val;}) diff --git a/samples/bpf/test_probe_write_user_kern.c b/samples/bpf/test_probe_write_user_kern.c index 3a677c807044..a543358218e6 100644 --- a/samples/bpf/test_probe_write_user_kern.c +++ b/samples/bpf/test_probe_write_user_kern.c @@ -9,6 +9,7 @@ #include <uapi/linux/bpf.h> #include <linux/version.h> #include "bpf_helpers.h" +#include "bpf_tracing.h" struct bpf_map_def SEC("maps") dnat_map = { .type = BPF_MAP_TYPE_HASH, diff --git a/samples/bpf/trace_event_kern.c b/samples/bpf/trace_event_kern.c index 7068fbdde951..8dc18d233a27 100644 --- a/samples/bpf/trace_event_kern.c +++ b/samples/bpf/trace_event_kern.c @@ -10,6 +10,7 @@ #include <uapi/linux/bpf_perf_event.h> #include <uapi/linux/perf_event.h> #include "bpf_helpers.h" +#include "bpf_tracing.h" struct key_t { char comm[TASK_COMM_LEN]; diff --git a/samples/bpf/tracex1_kern.c b/samples/bpf/tracex1_kern.c index 107da148820f..1a15f6605129 100644 --- a/samples/bpf/tracex1_kern.c +++ b/samples/bpf/tracex1_kern.c @@ -9,6 +9,7 @@ #include <uapi/linux/bpf.h> #include <linux/version.h> #include "bpf_helpers.h" +#include "bpf_tracing.h" #define _(P) ({typeof(P) val = 0; bpf_probe_read(&val, sizeof(val), &P); val;}) diff --git a/samples/bpf/tracex2_kern.c b/samples/bpf/tracex2_kern.c index 5e11c20ce5ec..d70b3ea79ea7 100644 --- a/samples/bpf/tracex2_kern.c +++ b/samples/bpf/tracex2_kern.c @@ -9,6 +9,7 @@ #include <linux/version.h> #include <uapi/linux/bpf.h> #include "bpf_helpers.h" +#include "bpf_tracing.h" struct bpf_map_def SEC("maps") my_map = { .type = BPF_MAP_TYPE_HASH, diff --git a/samples/bpf/tracex3_kern.c b/samples/bpf/tracex3_kern.c index ea1d4c19c132..9af546bebfa9 100644 --- a/samples/bpf/tracex3_kern.c +++ b/samples/bpf/tracex3_kern.c @@ -9,6 +9,7 @@ #include <linux/version.h> #include <uapi/linux/bpf.h> #include "bpf_helpers.h" +#include "bpf_tracing.h" struct bpf_map_def SEC("maps") my_map = { .type = BPF_MAP_TYPE_HASH, diff --git a/samples/bpf/tracex4_kern.c b/samples/bpf/tracex4_kern.c index 6dd8e384de96..2a02cbe9d9a1 100644 --- a/samples/bpf/tracex4_kern.c +++ b/samples/bpf/tracex4_kern.c @@ -8,6 +8,7 @@ #include <linux/version.h> #include <uapi/linux/bpf.h> #include "bpf_helpers.h" +#include "bpf_tracing.h" struct pair { u64 val; diff --git a/samples/bpf/tracex5_kern.c b/samples/bpf/tracex5_kern.c index 35cb0eed3be5..b3557b21a8fe 100644 --- a/samples/bpf/tracex5_kern.c +++ b/samples/bpf/tracex5_kern.c @@ -11,6 +11,7 @@ #include <uapi/linux/unistd.h> #include "syscall_nrs.h" #include "bpf_helpers.h" +#include "bpf_tracing.h" #define PROG(F) SEC("kprobe/"__stringify(F)) int bpf_func_##F diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h index 5210cc7d7c5c..cb9d4d2224af 100644 --- a/tools/testing/selftests/bpf/bpf_helpers.h +++ b/tools/testing/selftests/bpf/bpf_helpers.h @@ -232,17 +232,6 @@ static long long (*bpf_tcp_gen_syncookie)(struct bpf_sock *sk, void *ip, int ip_len, void *tcp, int tcp_len) = (void *) BPF_FUNC_tcp_gen_syncookie; -/* a helper structure used by eBPF C program - * to describe BPF map attributes to libbpf loader - */ -struct bpf_map_def { - unsigned int type; - unsigned int key_size; - unsigned int value_size; - unsigned int max_entries; - unsigned int map_flags; -}; - static int (*bpf_skb_load_bytes)(void *ctx, int off, void *to, int len) = (void *) BPF_FUNC_skb_load_bytes; static int (*bpf_skb_load_bytes_relative)(void *ctx, int off, void *to, int len, __u32 start_header) = @@ -292,195 +281,16 @@ static int (*bpf_skb_adjust_room)(void *ctx, __s32 len_diff, __u32 mode, unsigned long long flags) = (void *) BPF_FUNC_skb_adjust_room; -/* Scan the ARCH passed in from ARCH env variable (see Makefile) */ -#if defined(__TARGET_ARCH_x86) - #define bpf_target_x86 - #define bpf_target_defined -#elif defined(__TARGET_ARCH_s390) - #define bpf_target_s390 - #define bpf_target_defined -#elif defined(__TARGET_ARCH_arm) - #define bpf_target_arm - #define bpf_target_defined -#elif defined(__TARGET_ARCH_arm64) - #define bpf_target_arm64 - #define bpf_target_defined -#elif defined(__TARGET_ARCH_mips) - #define bpf_target_mips - #define bpf_target_defined -#elif defined(__TARGET_ARCH_powerpc) - #define bpf_target_powerpc - #define bpf_target_defined -#elif defined(__TARGET_ARCH_sparc) - #define bpf_target_sparc - #define bpf_target_defined -#else - #undef bpf_target_defined -#endif - -/* Fall back to what the compiler says */ -#ifndef bpf_target_defined -#if defined(__x86_64__) - #define bpf_target_x86 -#elif defined(__s390__) - #define bpf_target_s390 -#elif defined(__arm__) - #define bpf_target_arm -#elif defined(__aarch64__) - #define bpf_target_arm64 -#elif defined(__mips__) - #define bpf_target_mips -#elif defined(__powerpc__) - #define bpf_target_powerpc -#elif defined(__sparc__) - #define bpf_target_sparc -#endif -#endif - -#if defined(bpf_target_x86) - -#ifdef __KERNEL__ -#define PT_REGS_PARM1(x) ((x)->di) -#define PT_REGS_PARM2(x) ((x)->si) -#define PT_REGS_PARM3(x) ((x)->dx) -#define PT_REGS_PARM4(x) ((x)->cx) -#define PT_REGS_PARM5(x) ((x)->r8) -#define PT_REGS_RET(x) ((x)->sp) -#define PT_REGS_FP(x) ((x)->bp) -#define PT_REGS_RC(x) ((x)->ax) -#define PT_REGS_SP(x) ((x)->sp) -#define PT_REGS_IP(x) ((x)->ip) -#else -#ifdef __i386__ -/* i386 kernel is built with -mregparm=3 */ -#define PT_REGS_PARM1(x) ((x)->eax) -#define PT_REGS_PARM2(x) ((x)->edx) -#define PT_REGS_PARM3(x) ((x)->ecx) -#define PT_REGS_PARM4(x) 0 -#define PT_REGS_PARM5(x) 0 -#define PT_REGS_RET(x) ((x)->esp) -#define PT_REGS_FP(x) ((x)->ebp) -#define PT_REGS_RC(x) ((x)->eax) -#define PT_REGS_SP(x) ((x)->esp) -#define PT_REGS_IP(x) ((x)->eip) -#else -#define PT_REGS_PARM1(x) ((x)->rdi) -#define PT_REGS_PARM2(x) ((x)->rsi) -#define PT_REGS_PARM3(x) ((x)->rdx) -#define PT_REGS_PARM4(x) ((x)->rcx) -#define PT_REGS_PARM5(x) ((x)->r8) -#define PT_REGS_RET(x) ((x)->rsp) -#define PT_REGS_FP(x) ((x)->rbp) -#define PT_REGS_RC(x) ((x)->rax) -#define PT_REGS_SP(x) ((x)->rsp) -#define PT_REGS_IP(x) ((x)->rip) -#endif -#endif - -#elif defined(bpf_target_s390) - -/* s390 provides user_pt_regs instead of struct pt_regs to userspace */ -struct pt_regs; -#define PT_REGS_S390 const volatile user_pt_regs -#define PT_REGS_PARM1(x) (((PT_REGS_S390 *)(x))->gprs[2]) -#define PT_REGS_PARM2(x) (((PT_REGS_S390 *)(x))->gprs[3]) -#define PT_REGS_PARM3(x) (((PT_REGS_S390 *)(x))->gprs[4]) -#define PT_REGS_PARM4(x) (((PT_REGS_S390 *)(x))->gprs[5]) -#define PT_REGS_PARM5(x) (((PT_REGS_S390 *)(x))->gprs[6]) -#define PT_REGS_RET(x) (((PT_REGS_S390 *)(x))->gprs[14]) -/* Works only with CONFIG_FRAME_POINTER */ -#define PT_REGS_FP(x) (((PT_REGS_S390 *)(x))->gprs[11]) -#define PT_REGS_RC(x) (((PT_REGS_S390 *)(x))->gprs[2]) -#define PT_REGS_SP(x) (((PT_REGS_S390 *)(x))->gprs[15]) -#define PT_REGS_IP(x) (((PT_REGS_S390 *)(x))->psw.addr) - -#elif defined(bpf_target_arm) - -#define PT_REGS_PARM1(x) ((x)->uregs[0]) -#define PT_REGS_PARM2(x) ((x)->uregs[1]) -#define PT_REGS_PARM3(x) ((x)->uregs[2]) -#define PT_REGS_PARM4(x) ((x)->uregs[3]) -#define PT_REGS_PARM5(x) ((x)->uregs[4]) -#define PT_REGS_RET(x) ((x)->uregs[14]) -#define PT_REGS_FP(x) ((x)->uregs[11]) /* Works only with CONFIG_FRAME_POINTER */ -#define PT_REGS_RC(x) ((x)->uregs[0]) -#define PT_REGS_SP(x) ((x)->uregs[13]) -#define PT_REGS_IP(x) ((x)->uregs[12]) - -#elif defined(bpf_target_arm64) - -/* arm64 provides struct user_pt_regs instead of struct pt_regs to userspace */ -struct pt_regs; -#define PT_REGS_ARM64 const volatile struct user_pt_regs -#define PT_REGS_PARM1(x) (((PT_REGS_ARM64 *)(x))->regs[0]) -#define PT_REGS_PARM2(x) (((PT_REGS_ARM64 *)(x))->regs[1]) -#define PT_REGS_PARM3(x) (((PT_REGS_ARM64 *)(x))->regs[2]) -#define PT_REGS_PARM4(x) (((PT_REGS_ARM64 *)(x))->regs[3]) -#define PT_REGS_PARM5(x) (((PT_REGS_ARM64 *)(x))->regs[4]) -#define PT_REGS_RET(x) (((PT_REGS_ARM64 *)(x))->regs[30]) -/* Works only with CONFIG_FRAME_POINTER */ -#define PT_REGS_FP(x) (((PT_REGS_ARM64 *)(x))->regs[29]) -#define PT_REGS_RC(x) (((PT_REGS_ARM64 *)(x))->regs[0]) -#define PT_REGS_SP(x) (((PT_REGS_ARM64 *)(x))->sp) -#define PT_REGS_IP(x) (((PT_REGS_ARM64 *)(x))->pc) - -#elif defined(bpf_target_mips) - -#define PT_REGS_PARM1(x) ((x)->regs[4]) -#define PT_REGS_PARM2(x) ((x)->regs[5]) -#define PT_REGS_PARM3(x) ((x)->regs[6]) -#define PT_REGS_PARM4(x) ((x)->regs[7]) -#define PT_REGS_PARM5(x) ((x)->regs[8]) -#define PT_REGS_RET(x) ((x)->regs[31]) -#define PT_REGS_FP(x) ((x)->regs[30]) /* Works only with CONFIG_FRAME_POINTER */ -#define PT_REGS_RC(x) ((x)->regs[1]) -#define PT_REGS_SP(x) ((x)->regs[29]) -#define PT_REGS_IP(x) ((x)->cp0_epc) - -#elif defined(bpf_target_powerpc) - -#define PT_REGS_PARM1(x) ((x)->gpr[3]) -#define PT_REGS_PARM2(x) ((x)->gpr[4]) -#define PT_REGS_PARM3(x) ((x)->gpr[5]) -#define PT_REGS_PARM4(x) ((x)->gpr[6]) -#define PT_REGS_PARM5(x) ((x)->gpr[7]) -#define PT_REGS_RC(x) ((x)->gpr[3]) -#define PT_REGS_SP(x) ((x)->sp) -#define PT_REGS_IP(x) ((x)->nip) - -#elif defined(bpf_target_sparc) - -#define PT_REGS_PARM1(x) ((x)->u_regs[UREG_I0]) -#define PT_REGS_PARM2(x) ((x)->u_regs[UREG_I1]) -#define PT_REGS_PARM3(x) ((x)->u_regs[UREG_I2]) -#define PT_REGS_PARM4(x) ((x)->u_regs[UREG_I3]) -#define PT_REGS_PARM5(x) ((x)->u_regs[UREG_I4]) -#define PT_REGS_RET(x) ((x)->u_regs[UREG_I7]) -#define PT_REGS_RC(x) ((x)->u_regs[UREG_I0]) -#define PT_REGS_SP(x) ((x)->u_regs[UREG_FP]) - -/* Should this also be a bpf_target check for the sparc case? */ -#if defined(__arch64__) -#define PT_REGS_IP(x) ((x)->tpc) -#else -#define PT_REGS_IP(x) ((x)->pc) -#endif - -#endif - -#if defined(bpf_target_powerpc) -#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = (ctx)->link; }) -#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP -#elif defined(bpf_target_sparc) -#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = PT_REGS_RET(ctx); }) -#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP -#else -#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ \ - bpf_probe_read(&(ip), sizeof(ip), (void *)PT_REGS_RET(ctx)); }) -#define BPF_KRETPROBE_READ_RET_IP(ip, ctx) ({ \ - bpf_probe_read(&(ip), sizeof(ip), \ - (void *)(PT_REGS_FP(ctx) + sizeof(ip))); }) -#endif +/* a helper structure used by eBPF C program + * to describe BPF map attributes to libbpf loader + */ +struct bpf_map_def { + unsigned int type; + unsigned int key_size; + unsigned int value_size; + unsigned int max_entries; + unsigned int map_flags; +}; /* * bpf_core_read() abstracts away bpf_probe_read() call and captures offset diff --git a/tools/testing/selftests/bpf/bpf_tracing.h b/tools/testing/selftests/bpf/bpf_tracing.h new file mode 100644 index 000000000000..b0dafe8b4ebc --- /dev/null +++ b/tools/testing/selftests/bpf/bpf_tracing.h @@ -0,0 +1,195 @@ +/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ +#ifndef __BPF_TRACING_H__ +#define __BPF_TRACING_H__ + +/* Scan the ARCH passed in from ARCH env variable (see Makefile) */ +#if defined(__TARGET_ARCH_x86) + #define bpf_target_x86 + #define bpf_target_defined +#elif defined(__TARGET_ARCH_s390) + #define bpf_target_s390 + #define bpf_target_defined +#elif defined(__TARGET_ARCH_arm) + #define bpf_target_arm + #define bpf_target_defined +#elif defined(__TARGET_ARCH_arm64) + #define bpf_target_arm64 + #define bpf_target_defined +#elif defined(__TARGET_ARCH_mips) + #define bpf_target_mips + #define bpf_target_defined +#elif defined(__TARGET_ARCH_powerpc) + #define bpf_target_powerpc + #define bpf_target_defined +#elif defined(__TARGET_ARCH_sparc) + #define bpf_target_sparc + #define bpf_target_defined +#else + #undef bpf_target_defined +#endif + +/* Fall back to what the compiler says */ +#ifndef bpf_target_defined +#if defined(__x86_64__) + #define bpf_target_x86 +#elif defined(__s390__) + #define bpf_target_s390 +#elif defined(__arm__) + #define bpf_target_arm +#elif defined(__aarch64__) + #define bpf_target_arm64 +#elif defined(__mips__) + #define bpf_target_mips +#elif defined(__powerpc__) + #define bpf_target_powerpc +#elif defined(__sparc__) + #define bpf_target_sparc +#endif +#endif + +#if defined(bpf_target_x86) + +#ifdef __KERNEL__ +#define PT_REGS_PARM1(x) ((x)->di) +#define PT_REGS_PARM2(x) ((x)->si) +#define PT_REGS_PARM3(x) ((x)->dx) +#define PT_REGS_PARM4(x) ((x)->cx) +#define PT_REGS_PARM5(x) ((x)->r8) +#define PT_REGS_RET(x) ((x)->sp) +#define PT_REGS_FP(x) ((x)->bp) +#define PT_REGS_RC(x) ((x)->ax) +#define PT_REGS_SP(x) ((x)->sp) +#define PT_REGS_IP(x) ((x)->ip) +#else +#ifdef __i386__ +/* i386 kernel is built with -mregparm=3 */ +#define PT_REGS_PARM1(x) ((x)->eax) +#define PT_REGS_PARM2(x) ((x)->edx) +#define PT_REGS_PARM3(x) ((x)->ecx) +#define PT_REGS_PARM4(x) 0 +#define PT_REGS_PARM5(x) 0 +#define PT_REGS_RET(x) ((x)->esp) +#define PT_REGS_FP(x) ((x)->ebp) +#define PT_REGS_RC(x) ((x)->eax) +#define PT_REGS_SP(x) ((x)->esp) +#define PT_REGS_IP(x) ((x)->eip) +#else +#define PT_REGS_PARM1(x) ((x)->rdi) +#define PT_REGS_PARM2(x) ((x)->rsi) +#define PT_REGS_PARM3(x) ((x)->rdx) +#define PT_REGS_PARM4(x) ((x)->rcx) +#define PT_REGS_PARM5(x) ((x)->r8) +#define PT_REGS_RET(x) ((x)->rsp) +#define PT_REGS_FP(x) ((x)->rbp) +#define PT_REGS_RC(x) ((x)->rax) +#define PT_REGS_SP(x) ((x)->rsp) +#define PT_REGS_IP(x) ((x)->rip) +#endif +#endif + +#elif defined(bpf_target_s390) + +/* s390 provides user_pt_regs instead of struct pt_regs to userspace */ +struct pt_regs; +#define PT_REGS_S390 const volatile user_pt_regs +#define PT_REGS_PARM1(x) (((PT_REGS_S390 *)(x))->gprs[2]) +#define PT_REGS_PARM2(x) (((PT_REGS_S390 *)(x))->gprs[3]) +#define PT_REGS_PARM3(x) (((PT_REGS_S390 *)(x))->gprs[4]) +#define PT_REGS_PARM4(x) (((PT_REGS_S390 *)(x))->gprs[5]) +#define PT_REGS_PARM5(x) (((PT_REGS_S390 *)(x))->gprs[6]) +#define PT_REGS_RET(x) (((PT_REGS_S390 *)(x))->gprs[14]) +/* Works only with CONFIG_FRAME_POINTER */ +#define PT_REGS_FP(x) (((PT_REGS_S390 *)(x))->gprs[11]) +#define PT_REGS_RC(x) (((PT_REGS_S390 *)(x))->gprs[2]) +#define PT_REGS_SP(x) (((PT_REGS_S390 *)(x))->gprs[15]) +#define PT_REGS_IP(x) (((PT_REGS_S390 *)(x))->psw.addr) + +#elif defined(bpf_target_arm) + +#define PT_REGS_PARM1(x) ((x)->uregs[0]) +#define PT_REGS_PARM2(x) ((x)->uregs[1]) +#define PT_REGS_PARM3(x) ((x)->uregs[2]) +#define PT_REGS_PARM4(x) ((x)->uregs[3]) +#define PT_REGS_PARM5(x) ((x)->uregs[4]) +#define PT_REGS_RET(x) ((x)->uregs[14]) +#define PT_REGS_FP(x) ((x)->uregs[11]) /* Works only with CONFIG_FRAME_POINTER */ +#define PT_REGS_RC(x) ((x)->uregs[0]) +#define PT_REGS_SP(x) ((x)->uregs[13]) +#define PT_REGS_IP(x) ((x)->uregs[12]) + +#elif defined(bpf_target_arm64) + +/* arm64 provides struct user_pt_regs instead of struct pt_regs to userspace */ +struct pt_regs; +#define PT_REGS_ARM64 const volatile struct user_pt_regs +#define PT_REGS_PARM1(x) (((PT_REGS_ARM64 *)(x))->regs[0]) +#define PT_REGS_PARM2(x) (((PT_REGS_ARM64 *)(x))->regs[1]) +#define PT_REGS_PARM3(x) (((PT_REGS_ARM64 *)(x))->regs[2]) +#define PT_REGS_PARM4(x) (((PT_REGS_ARM64 *)(x))->regs[3]) +#define PT_REGS_PARM5(x) (((PT_REGS_ARM64 *)(x))->regs[4]) +#define PT_REGS_RET(x) (((PT_REGS_ARM64 *)(x))->regs[30]) +/* Works only with CONFIG_FRAME_POINTER */ +#define PT_REGS_FP(x) (((PT_REGS_ARM64 *)(x))->regs[29]) +#define PT_REGS_RC(x) (((PT_REGS_ARM64 *)(x))->regs[0]) +#define PT_REGS_SP(x) (((PT_REGS_ARM64 *)(x))->sp) +#define PT_REGS_IP(x) (((PT_REGS_ARM64 *)(x))->pc) + +#elif defined(bpf_target_mips) + +#define PT_REGS_PARM1(x) ((x)->regs[4]) +#define PT_REGS_PARM2(x) ((x)->regs[5]) +#define PT_REGS_PARM3(x) ((x)->regs[6]) +#define PT_REGS_PARM4(x) ((x)->regs[7]) +#define PT_REGS_PARM5(x) ((x)->regs[8]) +#define PT_REGS_RET(x) ((x)->regs[31]) +#define PT_REGS_FP(x) ((x)->regs[30]) /* Works only with CONFIG_FRAME_POINTER */ +#define PT_REGS_RC(x) ((x)->regs[1]) +#define PT_REGS_SP(x) ((x)->regs[29]) +#define PT_REGS_IP(x) ((x)->cp0_epc) + +#elif defined(bpf_target_powerpc) + +#define PT_REGS_PARM1(x) ((x)->gpr[3]) +#define PT_REGS_PARM2(x) ((x)->gpr[4]) +#define PT_REGS_PARM3(x) ((x)->gpr[5]) +#define PT_REGS_PARM4(x) ((x)->gpr[6]) +#define PT_REGS_PARM5(x) ((x)->gpr[7]) +#define PT_REGS_RC(x) ((x)->gpr[3]) +#define PT_REGS_SP(x) ((x)->sp) +#define PT_REGS_IP(x) ((x)->nip) + +#elif defined(bpf_target_sparc) + +#define PT_REGS_PARM1(x) ((x)->u_regs[UREG_I0]) +#define PT_REGS_PARM2(x) ((x)->u_regs[UREG_I1]) +#define PT_REGS_PARM3(x) ((x)->u_regs[UREG_I2]) +#define PT_REGS_PARM4(x) ((x)->u_regs[UREG_I3]) +#define PT_REGS_PARM5(x) ((x)->u_regs[UREG_I4]) +#define PT_REGS_RET(x) ((x)->u_regs[UREG_I7]) +#define PT_REGS_RC(x) ((x)->u_regs[UREG_I0]) +#define PT_REGS_SP(x) ((x)->u_regs[UREG_FP]) + +/* Should this also be a bpf_target check for the sparc case? */ +#if defined(__arch64__) +#define PT_REGS_IP(x) ((x)->tpc) +#else +#define PT_REGS_IP(x) ((x)->pc) +#endif + +#endif + +#if defined(bpf_target_powerpc) +#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = (ctx)->link; }) +#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP +#elif defined(bpf_target_sparc) +#define BPF_KPROBE_READ_RET_IP(ip, ctx) ({ (ip) = PT_REGS_RET(ctx); }) +#define BPF_KRETPROBE_READ_RET_IP BPF_KPROBE_READ_RET_IP +#else +#define BPF_KPROBE_READ_RET_IP(ip, ctx) \ + ({ bpf_probe_read(&(ip), sizeof(ip), (void *)PT_REGS_RET(ctx)); }) +#define BPF_KRETPROBE_READ_RET_IP(ip, ctx) \ + ({ bpf_probe_read(&(ip), sizeof(ip), \ + (void *)(PT_REGS_FP(ctx) + sizeof(ip))); }) +#endif + +#endif diff --git a/tools/testing/selftests/bpf/progs/loop1.c b/tools/testing/selftests/bpf/progs/loop1.c index 7cdb7f878310..40ac722a9da5 100644 --- a/tools/testing/selftests/bpf/progs/loop1.c +++ b/tools/testing/selftests/bpf/progs/loop1.c @@ -7,6 +7,7 @@ #include <stdbool.h> #include <linux/bpf.h> #include "bpf_helpers.h" +#include "bpf_tracing.h" char _license[] SEC("license") = "GPL"; diff --git a/tools/testing/selftests/bpf/progs/loop2.c b/tools/testing/selftests/bpf/progs/loop2.c index 9b2f808a2863..bb80f29aa7f7 100644 --- a/tools/testing/selftests/bpf/progs/loop2.c +++ b/tools/testing/selftests/bpf/progs/loop2.c @@ -7,6 +7,7 @@ #include <stdbool.h> #include <linux/bpf.h> #include "bpf_helpers.h" +#include "bpf_tracing.h" char _license[] SEC("license") = "GPL"; diff --git a/tools/testing/selftests/bpf/progs/loop3.c b/tools/testing/selftests/bpf/progs/loop3.c index d727657d51e2..2b9165a7afe1 100644 --- a/tools/testing/selftests/bpf/progs/loop3.c +++ b/tools/testing/selftests/bpf/progs/loop3.c @@ -7,6 +7,7 @@ #include <stdbool.h> #include <linux/bpf.h> #include "bpf_helpers.h" +#include "bpf_tracing.h" char _license[] SEC("license") = "GPL"; -- 2.17.1
Move bpf_helpers.h, bpf_tracing.h, and bpf_endian.h into libbpf. Ensure they are installed along the other libbpf headers. Also, adjust selftests and samples include path to include libbpf now. Signed-off-by: Andrii Nakryiko <andriin@fb.com> --- samples/bpf/Makefile | 2 +- tools/lib/bpf/Makefile | 5 ++++- tools/{testing/selftests => lib}/bpf/bpf_endian.h | 0 tools/{testing/selftests => lib}/bpf/bpf_helpers.h | 0 tools/{testing/selftests => lib}/bpf/bpf_tracing.h | 0 tools/testing/selftests/bpf/Makefile | 2 +- 6 files changed, 6 insertions(+), 3 deletions(-) rename tools/{testing/selftests => lib}/bpf/bpf_endian.h (100%) rename tools/{testing/selftests => lib}/bpf/bpf_helpers.h (100%) rename tools/{testing/selftests => lib}/bpf/bpf_tracing.h (100%) diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index 42b571cde177..ecb3535d91e3 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -283,7 +283,7 @@ $(obj)/hbm_edt_kern.o: $(src)/hbm.h $(src)/hbm_kern.h $(obj)/%.o: $(src)/%.c @echo " CLANG-bpf " $@ $(Q)$(CLANG) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) $(EXTRA_CFLAGS) -I$(obj) \ - -I$(srctree)/tools/testing/selftests/bpf/ \ + -I$(srctree)/tools/testing/selftests/bpf/ -I$(srctree)/tools/lib/bpf/ \ -D__KERNEL__ -D__BPF_TRACING__ -Wno-unused-value -Wno-pointer-sign \ -D__TARGET_ARCH_$(SRCARCH) -Wno-compare-distinct-pointer-types \ -Wno-gnu-variable-sized-type-not-at-end \ diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile index c6f94cffe06e..20b5b0ff5c73 100644 --- a/tools/lib/bpf/Makefile +++ b/tools/lib/bpf/Makefile @@ -240,7 +240,10 @@ install_headers: $(call do_install,libbpf.h,$(prefix)/include/bpf,644); \ $(call do_install,btf.h,$(prefix)/include/bpf,644); \ $(call do_install,libbpf_util.h,$(prefix)/include/bpf,644); \ - $(call do_install,xsk.h,$(prefix)/include/bpf,644); + $(call do_install,xsk.h,$(prefix)/include/bpf,644); \ + $(call do_install,bpf_helpers.h,$(prefix)/include/bpf,644); \ + $(call do_install,bpf_tracing.h,$(prefix)/include/bpf,644); \ + $(call do_install,bpf_endian.h,$(prefix)/include/bpf,644); install_pkgconfig: $(PC_FILE) $(call QUIET_INSTALL, $(PC_FILE)) \ diff --git a/tools/testing/selftests/bpf/bpf_endian.h b/tools/lib/bpf/bpf_endian.h similarity index 100% rename from tools/testing/selftests/bpf/bpf_endian.h rename to tools/lib/bpf/bpf_endian.h diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/lib/bpf/bpf_helpers.h similarity index 100% rename from tools/testing/selftests/bpf/bpf_helpers.h rename to tools/lib/bpf/bpf_helpers.h diff --git a/tools/testing/selftests/bpf/bpf_tracing.h b/tools/lib/bpf/bpf_tracing.h similarity index 100% rename from tools/testing/selftests/bpf/bpf_tracing.h rename to tools/lib/bpf/bpf_tracing.h diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile index 6889c19a628c..b00a5d8046c7 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -148,7 +148,7 @@ $(shell $(1) -v -E - </dev/null 2>&1 \ endef CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG)) BPF_CFLAGS = -I. -I./include/uapi -I../../../include/uapi \ - -I$(OUTPUT)/../usr/include -D__TARGET_ARCH_$(SRCARCH) + -I$(BPFDIR) -I$(OUTPUT)/../usr/include -D__TARGET_ARCH_$(SRCARCH) CLANG_CFLAGS = $(CLANG_SYS_INCLUDES) \ -Wno-compare-distinct-pointer-types -- 2.17.1
Add few macros simplifying BCC-like multi-level probe reads, while also emitting CO-RE relocations for each read. Acked-by: John Fastabend <john.fastabend@gmail.com> Signed-off-by: Andrii Nakryiko <andriin@fb.com> --- tools/lib/bpf/bpf_helpers.h | 143 ++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/tools/lib/bpf/bpf_helpers.h b/tools/lib/bpf/bpf_helpers.h index cb9d4d2224af..847dfd7125e4 100644 --- a/tools/lib/bpf/bpf_helpers.h +++ b/tools/lib/bpf/bpf_helpers.h @@ -19,6 +19,10 @@ */ #define SEC(NAME) __attribute__((section(NAME), used)) +#ifndef __always_inline +#define __always_inline __attribute__((always_inline)) +#endif + /* helper functions called from eBPF programs written in C */ static void *(*bpf_map_lookup_elem)(void *map, const void *key) = (void *) BPF_FUNC_map_lookup_elem; @@ -312,4 +316,143 @@ struct bpf_map_def { bpf_probe_read(dst, sz, \ (const void *)__builtin_preserve_access_index(src)) +/* + * bpf_core_read_str() is a thin wrapper around bpf_probe_read_str() + * additionally emitting BPF CO-RE field relocation for specified source + * argument. + */ +#define bpf_core_read_str(dst, sz, src) \ + bpf_probe_read_str(dst, sz, \ + (const void *)__builtin_preserve_access_index(src)) + +#define ___concat(a, b) a ## b +#define ___apply(fn, n) ___concat(fn, n) +#define ___nth(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, __11, N, ...) N + +/* return number of provided arguments; used for switch-based variadic macro + * definitions (see ___last, ___arrow, etc below) + */ +#define ___narg(...) ___nth(_, ##__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +/* return 0 if no arguments are passed, N - otherwise; used for + * recursively-defined macros to specify termination (0) case, and generic + * (N) case (e.g., ___read_ptrs, ___core_read) + */ +#define ___empty(...) ___nth(_, ##__VA_ARGS__, N, N, N, N, N, N, N, N, N, N, 0) + +#define ___last1(x) x +#define ___last2(a, x) x +#define ___last3(a, b, x) x +#define ___last4(a, b, c, x) x +#define ___last5(a, b, c, d, x) x +#define ___last6(a, b, c, d, e, x) x +#define ___last7(a, b, c, d, e, f, x) x +#define ___last8(a, b, c, d, e, f, g, x) x +#define ___last9(a, b, c, d, e, f, g, h, x) x +#define ___last10(a, b, c, d, e, f, g, h, i, x) x +#define ___last(...) ___apply(___last, ___narg(__VA_ARGS__))(__VA_ARGS__) + +#define ___nolast2(a, _) a +#define ___nolast3(a, b, _) a, b +#define ___nolast4(a, b, c, _) a, b, c +#define ___nolast5(a, b, c, d, _) a, b, c, d +#define ___nolast6(a, b, c, d, e, _) a, b, c, d, e +#define ___nolast7(a, b, c, d, e, f, _) a, b, c, d, e, f +#define ___nolast8(a, b, c, d, e, f, g, _) a, b, c, d, e, f, g +#define ___nolast9(a, b, c, d, e, f, g, h, _) a, b, c, d, e, f, g, h +#define ___nolast10(a, b, c, d, e, f, g, h, i, _) a, b, c, d, e, f, g, h, i +#define ___nolast(...) ___apply(___nolast, ___narg(__VA_ARGS__))(__VA_ARGS__) + +#define ___arrow1(a) a +#define ___arrow2(a, b) a->b +#define ___arrow3(a, b, c) a->b->c +#define ___arrow4(a, b, c, d) a->b->c->d +#define ___arrow5(a, b, c, d, e) a->b->c->d->e +#define ___arrow6(a, b, c, d, e, f) a->b->c->d->e->f +#define ___arrow7(a, b, c, d, e, f, g) a->b->c->d->e->f->g +#define ___arrow8(a, b, c, d, e, f, g, h) a->b->c->d->e->f->g->h +#define ___arrow9(a, b, c, d, e, f, g, h, i) a->b->c->d->e->f->g->h->i +#define ___arrow10(a, b, c, d, e, f, g, h, i, j) a->b->c->d->e->f->g->h->i->j +#define ___arrow(...) ___apply(___arrow, ___narg(__VA_ARGS__))(__VA_ARGS__) + +#define ___type(...) typeof(___arrow(__VA_ARGS__)) + +#define ___read(read_fn, dst, src_type, src, accessor) \ + read_fn((void *)(dst), sizeof(*(dst)), &((src_type)(src))->accessor) + +/* "recursively" read a sequence of inner pointers using local __t var */ +#define ___rd_last(...) \ + ___read(bpf_core_read, &__t, \ + ___type(___nolast(__VA_ARGS__)), __t, ___last(__VA_ARGS__)); +#define ___rd_p0(src) const void *__t = src; +#define ___rd_p1(...) ___rd_p0(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) +#define ___rd_p2(...) ___rd_p1(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) +#define ___rd_p3(...) ___rd_p2(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) +#define ___rd_p4(...) ___rd_p3(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) +#define ___rd_p5(...) ___rd_p4(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) +#define ___rd_p6(...) ___rd_p5(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) +#define ___rd_p7(...) ___rd_p6(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) +#define ___rd_p8(...) ___rd_p7(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) +#define ___rd_p9(...) ___rd_p8(___nolast(__VA_ARGS__)) ___rd_last(__VA_ARGS__) +#define ___read_ptrs(src, ...) \ + ___apply(___rd_p, ___narg(__VA_ARGS__))(src, __VA_ARGS__) + +#define ___core_read0(fn, dst, src, a) \ + ___read(fn, dst, ___type(src), src, a); +#define ___core_readN(fn, dst, src, ...) \ + ___read_ptrs(src, ___nolast(__VA_ARGS__)) \ + ___read(fn, dst, ___type(src, ___nolast(__VA_ARGS__)), __t, \ + ___last(__VA_ARGS__)); +#define ___core_read(fn, dst, src, a, ...) \ + ___apply(___core_read, ___empty(__VA_ARGS__))(fn, dst, \ + src, a, ##__VA_ARGS__) + +/* + * BPF_CORE_READ_INTO() is a more performance-conscious variant of + * BPF_CORE_READ(), in which final field is read into user-provided storage. + * See BPF_CORE_READ() below for more details on general usage. + */ +#define BPF_CORE_READ_INTO(dst, src, a, ...) \ + ({ \ + ___core_read(bpf_core_read, dst, src, a, ##__VA_ARGS__) \ + }) + +/* + * BPF_CORE_READ_STR_INTO() does same "pointer chasing" as + * BPF_CORE_READ() for intermediate pointers, but then executes (and returns + * corresponding error code) bpf_core_read_str() for final string read. + */ +#define BPF_CORE_READ_STR_INTO(dst, src, a, ...) \ + ({ \ + ___core_read(bpf_core_read_str, dst, src, a, ##__VA_ARGS__) \ + }) + +/* + * BPF_CORE_READ() is used to simplify BPF CO-RE relocatable read, especially + * when there are few pointer chasing steps. + * E.g., what in non-BPF world (or in BPF w/ BCC) would be something like: + * int x = s->a.b.c->d.e->f->g; + * can be succinctly achieved using BPF_CORE_READ as: + * int x = BPF_CORE_READ(s, a.b.c, d.e, f, g); + * + * BPF_CORE_READ will decompose above statement into 4 bpf_core_read (BPF + * CO-RE relocatable bpf_probe_read() wrapper) calls, logically equivalent to: + * 1. const void *__t = s->a.b.c; + * 2. __t = __t->d.e; + * 3. __t = __t->f; + * 4. return __t->g; + * + * Equivalence is logical, because there is a heavy type casting/preservation + * involved, as well as all the reads are happening through bpf_probe_read() + * calls using __builtin_preserve_access_index() to emit CO-RE relocations. + * + * N.B. Only up to 9 "field accessors" are supported, which should be more + * than enough for any practical purpose. + */ +#define BPF_CORE_READ(src, a, ...) \ + ({ \ + ___type(src, a, ##__VA_ARGS__) __r; \ + BPF_CORE_READ_INTO(&__r, src, a, ##__VA_ARGS__); \ + __r; \ + }) + #endif -- 2.17.1
Validate BPF_CORE_READ correctness and handling of up to 9 levels of nestedness using cyclic task->(group_leader->)*->tgid chains. Also add a test of maximum-dpeth BPF_CORE_READ_STR_INTO() macro. Acked-by: John Fastabend <john.fastabend@gmail.com> Acked-by: Song Liu <songliubraving@fb.com> Signed-off-by: Andrii Nakryiko <andriin@fb.com> --- .../selftests/bpf/prog_tests/core_reloc.c | 8 ++- .../selftests/bpf/progs/core_reloc_types.h | 9 ++++ .../bpf/progs/test_core_reloc_kernel.c | 54 ++++++++++++++++++- 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/core_reloc.c b/tools/testing/selftests/bpf/prog_tests/core_reloc.c index f3863f976a48..21a0dff66241 100644 --- a/tools/testing/selftests/bpf/prog_tests/core_reloc.c +++ b/tools/testing/selftests/bpf/prog_tests/core_reloc.c @@ -193,8 +193,12 @@ static struct core_reloc_test_case test_cases[] = { .btf_src_file = NULL, /* load from /lib/modules/$(uname -r) */ .input = "", .input_len = 0, - .output = "\1", /* true */ - .output_len = 1, + .output = STRUCT_TO_CHAR_PTR(core_reloc_kernel_output) { + .valid = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, }, + .comm = "test_progs\0\0\0\0\0", + .comm_len = 11, + }, + .output_len = sizeof(struct core_reloc_kernel_output), }, /* validate BPF program can use multiple flavors to match against diff --git a/tools/testing/selftests/bpf/progs/core_reloc_types.h b/tools/testing/selftests/bpf/progs/core_reloc_types.h index f686a8138d90..9a6bdeb4894c 100644 --- a/tools/testing/selftests/bpf/progs/core_reloc_types.h +++ b/tools/testing/selftests/bpf/progs/core_reloc_types.h @@ -1,5 +1,14 @@ #include <stdint.h> #include <stdbool.h> +/* + * KERNEL + */ + +struct core_reloc_kernel_output { + int valid[10]; + char comm[16]; + int comm_len; +}; /* * FLAVORS diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c b/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c index e5308026cfda..f318d39623b5 100644 --- a/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c @@ -12,9 +12,17 @@ static volatile struct data { char out[256]; } data; +struct core_reloc_kernel_output { + int valid[10]; + char comm[16]; + int comm_len; +}; + struct task_struct { int pid; int tgid; + char comm[16]; + struct task_struct *group_leader; }; #define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) @@ -23,7 +31,9 @@ SEC("raw_tracepoint/sys_enter") int test_core_kernel(void *ctx) { struct task_struct *task = (void *)bpf_get_current_task(); + struct core_reloc_kernel_output *out = (void *)&data.out; uint64_t pid_tgid = bpf_get_current_pid_tgid(); + uint32_t real_tgid = (uint32_t)pid_tgid; int pid, tgid; if (CORE_READ(&pid, &task->pid) || @@ -31,7 +41,49 @@ int test_core_kernel(void *ctx) return 1; /* validate pid + tgid matches */ - data.out[0] = (((uint64_t)pid << 32) | tgid) == pid_tgid; + out->valid[0] = (((uint64_t)pid << 32) | tgid) == pid_tgid; + + /* test variadic BPF_CORE_READ macros */ + out->valid[1] = BPF_CORE_READ(task, + tgid) == real_tgid; + out->valid[2] = BPF_CORE_READ(task, + group_leader, + tgid) == real_tgid; + out->valid[3] = BPF_CORE_READ(task, + group_leader, group_leader, + tgid) == real_tgid; + out->valid[4] = BPF_CORE_READ(task, + group_leader, group_leader, group_leader, + tgid) == real_tgid; + out->valid[5] = BPF_CORE_READ(task, + group_leader, group_leader, group_leader, + group_leader, + tgid) == real_tgid; + out->valid[6] = BPF_CORE_READ(task, + group_leader, group_leader, group_leader, + group_leader, group_leader, + tgid) == real_tgid; + out->valid[7] = BPF_CORE_READ(task, + group_leader, group_leader, group_leader, + group_leader, group_leader, group_leader, + tgid) == real_tgid; + out->valid[8] = BPF_CORE_READ(task, + group_leader, group_leader, group_leader, + group_leader, group_leader, group_leader, + group_leader, + tgid) == real_tgid; + out->valid[9] = BPF_CORE_READ(task, + group_leader, group_leader, group_leader, + group_leader, group_leader, group_leader, + group_leader, group_leader, + tgid) == real_tgid; + + /* test BPF_CORE_READ_STR_INTO() returns correct code and contents */ + out->comm_len = BPF_CORE_READ_STR_INTO( + &out->comm, task, + group_leader, group_leader, group_leader, group_leader, + group_leader, group_leader, group_leader, group_leader, + comm); return 0; } -- 2.17.1
Andrii Nakryiko <andriin@fb.com> writes: > diff --git a/samples/bpf/map_perf_test_kern.c b/samples/bpf/map_perf_test_kern.c > index 2b2ffb97018b..f47ee513cb7c 100644 > --- a/samples/bpf/map_perf_test_kern.c > +++ b/samples/bpf/map_perf_test_kern.c > @@ -9,25 +9,26 @@ > #include <linux/version.h> > #include <uapi/linux/bpf.h> > #include "bpf_helpers.h" > +#include "bpf_legacy.h" > > #define MAX_ENTRIES 1000 > #define MAX_NR_CPUS 1024 > > -struct bpf_map_def SEC("maps") hash_map = { > +struct bpf_map_def_legacy SEC("maps") hash_map = { > .type = BPF_MAP_TYPE_HASH, > .key_size = sizeof(u32), > .value_size = sizeof(long), > .max_entries = MAX_ENTRIES, > }; Why switch these when they're not actually using any of the extra fields in map_def_legacy? > > -struct bpf_map_def SEC("maps") lru_hash_map = { > +struct bpf_map_def_legacy SEC("maps") lru_hash_map = { > .type = BPF_MAP_TYPE_LRU_HASH, > .key_size = sizeof(u32), > .value_size = sizeof(long), > .max_entries = 10000, > }; > > -struct bpf_map_def SEC("maps") nocommon_lru_hash_map = { > +struct bpf_map_def_legacy SEC("maps") nocommon_lru_hash_map = { > .type = BPF_MAP_TYPE_LRU_HASH, > .key_size = sizeof(u32), > .value_size = sizeof(long), > @@ -35,7 +36,7 @@ struct bpf_map_def SEC("maps") nocommon_lru_hash_map = { > .map_flags = BPF_F_NO_COMMON_LRU, > }; > > -struct bpf_map_def SEC("maps") inner_lru_hash_map = { > +struct bpf_map_def_legacy SEC("maps") inner_lru_hash_map = { > .type = BPF_MAP_TYPE_LRU_HASH, > .key_size = sizeof(u32), > .value_size = sizeof(long), > @@ -44,20 +45,20 @@ struct bpf_map_def SEC("maps") inner_lru_hash_map = { > .numa_node = 0, > }; Or are you just switching everything because of this one? -Toke
Andrii Nakryiko <andriin@fb.com> writes:
> +/* a helper structure used by eBPF C program
> + * to describe BPF map attributes to libbpf loader
> + */
> +struct bpf_map_def {
> + unsigned int type;
> + unsigned int key_size;
> + unsigned int value_size;
> + unsigned int max_entries;
> + unsigned int map_flags;
> +};
Why is this still here? There's already an identical definition in libbpf.h...
-Toke
On Thu, Oct 3, 2019 at 12:35 AM Toke Høiland-Jørgensen <toke@redhat.com> wrote: > > Andrii Nakryiko <andriin@fb.com> writes: > > > diff --git a/samples/bpf/map_perf_test_kern.c b/samples/bpf/map_perf_test_kern.c > > index 2b2ffb97018b..f47ee513cb7c 100644 > > --- a/samples/bpf/map_perf_test_kern.c > > +++ b/samples/bpf/map_perf_test_kern.c > > @@ -9,25 +9,26 @@ > > #include <linux/version.h> > > #include <uapi/linux/bpf.h> > > #include "bpf_helpers.h" > > +#include "bpf_legacy.h" > > > > #define MAX_ENTRIES 1000 > > #define MAX_NR_CPUS 1024 > > > > -struct bpf_map_def SEC("maps") hash_map = { > > +struct bpf_map_def_legacy SEC("maps") hash_map = { > > .type = BPF_MAP_TYPE_HASH, > > .key_size = sizeof(u32), > > .value_size = sizeof(long), > > .max_entries = MAX_ENTRIES, > > }; > > Why switch these when they're not actually using any of the extra fields > in map_def_legacy? See below, they have to be uniform-sized. > > > > -struct bpf_map_def SEC("maps") lru_hash_map = { > > +struct bpf_map_def_legacy SEC("maps") lru_hash_map = { > > .type = BPF_MAP_TYPE_LRU_HASH, > > .key_size = sizeof(u32), > > .value_size = sizeof(long), > > .max_entries = 10000, > > }; > > > > -struct bpf_map_def SEC("maps") nocommon_lru_hash_map = { > > +struct bpf_map_def_legacy SEC("maps") nocommon_lru_hash_map = { > > .type = BPF_MAP_TYPE_LRU_HASH, > > .key_size = sizeof(u32), > > .value_size = sizeof(long), > > @@ -35,7 +36,7 @@ struct bpf_map_def SEC("maps") nocommon_lru_hash_map = { > > .map_flags = BPF_F_NO_COMMON_LRU, > > }; > > > > -struct bpf_map_def SEC("maps") inner_lru_hash_map = { > > +struct bpf_map_def_legacy SEC("maps") inner_lru_hash_map = { > > .type = BPF_MAP_TYPE_LRU_HASH, > > .key_size = sizeof(u32), > > .value_size = sizeof(long), > > @@ -44,20 +45,20 @@ struct bpf_map_def SEC("maps") inner_lru_hash_map = { > > .numa_node = 0, > > }; > > Or are you just switching everything because of this one? Exactly. Another way would be to switch all but this to BTF-based one, but I didn't want to make this patch set even bigger, we can always do that later . > > > -Toke >
On Thu, Oct 3, 2019 at 12:35 AM Toke Høiland-Jørgensen <toke@redhat.com> wrote: > > Andrii Nakryiko <andriin@fb.com> writes: > > > +/* a helper structure used by eBPF C program > > + * to describe BPF map attributes to libbpf loader > > + */ > > +struct bpf_map_def { > > + unsigned int type; > > + unsigned int key_size; > > + unsigned int value_size; > > + unsigned int max_entries; > > + unsigned int map_flags; > > +}; > > Why is this still here? There's already an identical definition in libbpf.h... > It's a BPF (kernel) side vs userspace side difference. bpf_helpers.h are included from BPF program, while libbpf.h won't work on kernel side. So we have to have a duplicate of bpf_map_def. > -Toke >
Andrii Nakryiko <andrii.nakryiko@gmail.com> writes:
> On Thu, Oct 3, 2019 at 12:35 AM Toke Høiland-Jørgensen <toke@redhat.com> wrote:
>>
>> Andrii Nakryiko <andriin@fb.com> writes:
>>
>> > diff --git a/samples/bpf/map_perf_test_kern.c b/samples/bpf/map_perf_test_kern.c
>> > index 2b2ffb97018b..f47ee513cb7c 100644
>> > --- a/samples/bpf/map_perf_test_kern.c
>> > +++ b/samples/bpf/map_perf_test_kern.c
>> > @@ -9,25 +9,26 @@
>> > #include <linux/version.h>
>> > #include <uapi/linux/bpf.h>
>> > #include "bpf_helpers.h"
>> > +#include "bpf_legacy.h"
>> >
>> > #define MAX_ENTRIES 1000
>> > #define MAX_NR_CPUS 1024
>> >
>> > -struct bpf_map_def SEC("maps") hash_map = {
>> > +struct bpf_map_def_legacy SEC("maps") hash_map = {
>> > .type = BPF_MAP_TYPE_HASH,
>> > .key_size = sizeof(u32),
>> > .value_size = sizeof(long),
>> > .max_entries = MAX_ENTRIES,
>> > };
>>
>> Why switch these when they're not actually using any of the extra fields
>> in map_def_legacy?
>
> See below, they have to be uniform-sized.
>
>> >
>> > -struct bpf_map_def SEC("maps") lru_hash_map = {
>> > +struct bpf_map_def_legacy SEC("maps") lru_hash_map = {
>> > .type = BPF_MAP_TYPE_LRU_HASH,
>> > .key_size = sizeof(u32),
>> > .value_size = sizeof(long),
>> > .max_entries = 10000,
>> > };
>> >
>> > -struct bpf_map_def SEC("maps") nocommon_lru_hash_map = {
>> > +struct bpf_map_def_legacy SEC("maps") nocommon_lru_hash_map = {
>> > .type = BPF_MAP_TYPE_LRU_HASH,
>> > .key_size = sizeof(u32),
>> > .value_size = sizeof(long),
>> > @@ -35,7 +36,7 @@ struct bpf_map_def SEC("maps") nocommon_lru_hash_map = {
>> > .map_flags = BPF_F_NO_COMMON_LRU,
>> > };
>> >
>> > -struct bpf_map_def SEC("maps") inner_lru_hash_map = {
>> > +struct bpf_map_def_legacy SEC("maps") inner_lru_hash_map = {
>> > .type = BPF_MAP_TYPE_LRU_HASH,
>> > .key_size = sizeof(u32),
>> > .value_size = sizeof(long),
>> > @@ -44,20 +45,20 @@ struct bpf_map_def SEC("maps") inner_lru_hash_map = {
>> > .numa_node = 0,
>> > };
>>
>> Or are you just switching everything because of this one?
>
> Exactly. Another way would be to switch all but this to BTF-based one,
> but I didn't want to make this patch set even bigger, we can always do
> that later
Right, fair enough :)
-Toke
Andrii Nakryiko <andrii.nakryiko@gmail.com> writes:
> On Thu, Oct 3, 2019 at 12:35 AM Toke Høiland-Jørgensen <toke@redhat.com> wrote:
>>
>> Andrii Nakryiko <andriin@fb.com> writes:
>>
>> > +/* a helper structure used by eBPF C program
>> > + * to describe BPF map attributes to libbpf loader
>> > + */
>> > +struct bpf_map_def {
>> > + unsigned int type;
>> > + unsigned int key_size;
>> > + unsigned int value_size;
>> > + unsigned int max_entries;
>> > + unsigned int map_flags;
>> > +};
>>
>> Why is this still here? There's already an identical definition in libbpf.h...
>>
>
> It's a BPF (kernel) side vs userspace side difference. bpf_helpers.h
> are included from BPF program, while libbpf.h won't work on kernel
> side. So we have to have a duplicate of bpf_map_def.
Ah, yes, of course. Silly me :)
-Toke
Andrii Nakryiko wrote:
> Split off few legacy things from bpf_helpers.h into separate
> bpf_legacy.h file:
> - load_{byte|half|word};
> - remove extra inner_idx and numa_node fields from bpf_map_def and
> introduce bpf_map_def_legacy for use in samples;
> - move BPF_ANNOTATE_KV_PAIR into bpf_legacy.h.
>
> Adjust samples and selftests accordingly by either including
> bpf_legacy.h and using bpf_map_def_legacy, or switching to BTF-defined
> maps altogether.
>
> Signed-off-by: Andrii Nakryiko <andriin@fb.com>
> ---
Eventually we convert tests to use bpf_create_map_in_map() and friends
so we can drop legacy. Assuming this is what you have in mind but agree
thats a next step.
Acked-by: John Fastabend <john.fastabend@gmail.com>
Andrii Nakryiko wrote:
> Split-off PT_REGS-related helpers into bpf_tracing.h header. Adjust
> selftests and samples to include it where necessary.
>
> Signed-off-by: Andrii Nakryiko <andriin@fb.com>
> ---
Acked-by: John Fastabend <john.fastabend@gmail.com>
On Wed, Oct 2, 2019 at 3:01 PM Andrii Nakryiko <andriin@fb.com> wrote: > > Split off few legacy things from bpf_helpers.h into separate > bpf_legacy.h file: > - load_{byte|half|word}; > - remove extra inner_idx and numa_node fields from bpf_map_def and > introduce bpf_map_def_legacy for use in samples; > - move BPF_ANNOTATE_KV_PAIR into bpf_legacy.h. > > Adjust samples and selftests accordingly by either including > bpf_legacy.h and using bpf_map_def_legacy, or switching to BTF-defined > maps altogether. > > Signed-off-by: Andrii Nakryiko <andriin@fb.com> Acked-by: Song Liu <songliubraving@fb.com> with a nit below > --- > samples/bpf/hbm_kern.h | 28 +++++++------ > samples/bpf/map_perf_test_kern.c | 23 +++++------ > samples/bpf/parse_ldabs.c | 1 + > samples/bpf/sockex1_kern.c | 1 + > samples/bpf/sockex2_kern.c | 1 + > samples/bpf/sockex3_kern.c | 1 + > samples/bpf/tcbpf1_kern.c | 1 + > samples/bpf/test_map_in_map_kern.c | 15 +++---- > tools/testing/selftests/bpf/bpf_helpers.h | 24 +----------- > tools/testing/selftests/bpf/bpf_legacy.h | 39 +++++++++++++++++++ > .../testing/selftests/bpf/progs/sockopt_sk.c | 13 +++---- > tools/testing/selftests/bpf/progs/tcp_rtt.c | 13 +++---- > .../selftests/bpf/progs/test_btf_haskv.c | 1 + > .../selftests/bpf/progs/test_btf_newkv.c | 1 + > 14 files changed, 92 insertions(+), 70 deletions(-) > create mode 100644 tools/testing/selftests/bpf/bpf_legacy.h > > diff --git a/samples/bpf/hbm_kern.h b/samples/bpf/hbm_kern.h > index aa207a2eebbd..91880a0e9c2f 100644 > --- a/samples/bpf/hbm_kern.h > +++ b/samples/bpf/hbm_kern.h > @@ -24,6 +24,7 @@ > #include <net/inet_ecn.h> > #include "bpf_endian.h" > #include "bpf_helpers.h" > +#include "bpf_legacy.h" nit: I guess we don't need bpf_legacy.h here?
On Wed, Oct 2, 2019 at 3:01 PM Andrii Nakryiko <andriin@fb.com> wrote: > > To allow adding a variadic BPF_CORE_READ macro with slightly different > syntax and semantics, define CORE_READ in CO-RE reloc tests, which is > a thin wrapper around low-level bpf_core_read() macro, which in turn is > just a wrapper around bpf_probe_read(). > > Acked-by: John Fastabend <john.fastabend@gmail.com> > Acked-by: Song Liu <songliubraving@fb.com> > Signed-off-by: Andrii Nakryiko <andriin@fb.com> > --- > tools/testing/selftests/bpf/bpf_helpers.h | 8 ++++---- > .../bpf/progs/test_core_reloc_arrays.c | 10 ++++++---- > .../bpf/progs/test_core_reloc_flavors.c | 8 +++++--- > .../selftests/bpf/progs/test_core_reloc_ints.c | 18 ++++++++++-------- > .../bpf/progs/test_core_reloc_kernel.c | 6 ++++-- > .../selftests/bpf/progs/test_core_reloc_misc.c | 8 +++++--- > .../selftests/bpf/progs/test_core_reloc_mods.c | 18 ++++++++++-------- > .../bpf/progs/test_core_reloc_nesting.c | 6 ++++-- > .../bpf/progs/test_core_reloc_primitives.c | 12 +++++++----- > .../bpf/progs/test_core_reloc_ptr_as_arr.c | 4 +++- > 10 files changed, 58 insertions(+), 40 deletions(-) > > diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h > index 7b75c38238e4..5210cc7d7c5c 100644 > --- a/tools/testing/selftests/bpf/bpf_helpers.h > +++ b/tools/testing/selftests/bpf/bpf_helpers.h > @@ -483,7 +483,7 @@ struct pt_regs; > #endif > > /* > - * BPF_CORE_READ abstracts away bpf_probe_read() call and captures offset > + * bpf_core_read() abstracts away bpf_probe_read() call and captures offset > * relocation for source address using __builtin_preserve_access_index() > * built-in, provided by Clang. > * > @@ -498,8 +498,8 @@ struct pt_regs; > * actual field offset, based on target kernel BTF type that matches original > * (local) BTF, used to record relocation. > */ > -#define BPF_CORE_READ(dst, src) \ > - bpf_probe_read((dst), sizeof(*(src)), \ > - __builtin_preserve_access_index(src)) > +#define bpf_core_read(dst, sz, src) \ > + bpf_probe_read(dst, sz, \ > + (const void *)__builtin_preserve_access_index(src)) > > #endif > diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c b/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c > index bf67f0fdf743..58efe4944594 100644 > --- a/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c > +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c > @@ -31,6 +31,8 @@ struct core_reloc_arrays { > struct core_reloc_arrays_substruct d[1][2]; > }; > > +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) We are using sizeof(*dst) now, but I guess sizeof(*src) is better? And it should be sizeof(*(src)). > + > SEC("raw_tracepoint/sys_enter") > int test_core_arrays(void *ctx) > { > @@ -38,16 +40,16 @@ int test_core_arrays(void *ctx) > struct core_reloc_arrays_output *out = (void *)&data.out; > > /* in->a[2] */ > - if (BPF_CORE_READ(&out->a2, &in->a[2])) > + if (CORE_READ(&out->a2, &in->a[2])) > return 1; > /* in->b[1][2][3] */ > - if (BPF_CORE_READ(&out->b123, &in->b[1][2][3])) > + if (CORE_READ(&out->b123, &in->b[1][2][3])) > return 1; > /* in->c[1].c */ > - if (BPF_CORE_READ(&out->c1c, &in->c[1].c)) > + if (CORE_READ(&out->c1c, &in->c[1].c)) > return 1; > /* in->d[0][0].d */ > - if (BPF_CORE_READ(&out->d00d, &in->d[0][0].d)) > + if (CORE_READ(&out->d00d, &in->d[0][0].d)) > return 1; > > return 0; > diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_flavors.c b/tools/testing/selftests/bpf/progs/test_core_reloc_flavors.c > index 9fda73e87972..3348acc7e50b 100644 > --- a/tools/testing/selftests/bpf/progs/test_core_reloc_flavors.c > +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_flavors.c > @@ -39,6 +39,8 @@ struct core_reloc_flavors___weird { > }; > }; > > +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) > + > SEC("raw_tracepoint/sys_enter") > int test_core_flavors(void *ctx) > { > @@ -48,13 +50,13 @@ int test_core_flavors(void *ctx) > struct core_reloc_flavors *out = (void *)&data.out; > > /* read a using weird layout */ > - if (BPF_CORE_READ(&out->a, &in_weird->a)) > + if (CORE_READ(&out->a, &in_weird->a)) > return 1; > /* read b using reversed layout */ > - if (BPF_CORE_READ(&out->b, &in_rev->b)) > + if (CORE_READ(&out->b, &in_rev->b)) > return 1; > /* read c using original layout */ > - if (BPF_CORE_READ(&out->c, &in_orig->c)) > + if (CORE_READ(&out->c, &in_orig->c)) > return 1; > > return 0; > diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_ints.c b/tools/testing/selftests/bpf/progs/test_core_reloc_ints.c > index d99233c8008a..cfe16ede48dd 100644 > --- a/tools/testing/selftests/bpf/progs/test_core_reloc_ints.c > +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_ints.c > @@ -23,20 +23,22 @@ struct core_reloc_ints { > int64_t s64_field; > }; > > +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) ditto. > + > SEC("raw_tracepoint/sys_enter") > int test_core_ints(void *ctx) > { > struct core_reloc_ints *in = (void *)&data.in; > struct core_reloc_ints *out = (void *)&data.out; > > - if (BPF_CORE_READ(&out->u8_field, &in->u8_field) || > - BPF_CORE_READ(&out->s8_field, &in->s8_field) || > - BPF_CORE_READ(&out->u16_field, &in->u16_field) || > - BPF_CORE_READ(&out->s16_field, &in->s16_field) || > - BPF_CORE_READ(&out->u32_field, &in->u32_field) || > - BPF_CORE_READ(&out->s32_field, &in->s32_field) || > - BPF_CORE_READ(&out->u64_field, &in->u64_field) || > - BPF_CORE_READ(&out->s64_field, &in->s64_field)) > + if (CORE_READ(&out->u8_field, &in->u8_field) || > + CORE_READ(&out->s8_field, &in->s8_field) || > + CORE_READ(&out->u16_field, &in->u16_field) || > + CORE_READ(&out->s16_field, &in->s16_field) || > + CORE_READ(&out->u32_field, &in->u32_field) || > + CORE_READ(&out->s32_field, &in->s32_field) || > + CORE_READ(&out->u64_field, &in->u64_field) || > + CORE_READ(&out->s64_field, &in->s64_field)) > return 1; > > return 0; > diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c b/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c > index 37e02aa3f0c8..e5308026cfda 100644 > --- a/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c > +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c > @@ -17,6 +17,8 @@ struct task_struct { > int tgid; > }; > > +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) ditto again, and more below. Thanks, Song
On Thu, Oct 3, 2019 at 11:10 AM John Fastabend <john.fastabend@gmail.com> wrote:
>
> Andrii Nakryiko wrote:
> > Split-off PT_REGS-related helpers into bpf_tracing.h header. Adjust
> > selftests and samples to include it where necessary.
> >
> > Signed-off-by: Andrii Nakryiko <andriin@fb.com>
> > ---
>
> Acked-by: John Fastabend <john.fastabend@gmail.com>
Acked-by: Song Liu <songliubraving@fb.com>
On Wed, Oct 2, 2019 at 3:03 PM Andrii Nakryiko <andriin@fb.com> wrote: > > Move bpf_helpers.h, bpf_tracing.h, and bpf_endian.h into libbpf. Ensure > they are installed along the other libbpf headers. Also, adjust > selftests and samples include path to include libbpf now. > > Signed-off-by: Andrii Nakryiko <andriin@fb.com> Acked-by: Song Liu <songliubraving@fb.com> > --- > samples/bpf/Makefile | 2 +- > tools/lib/bpf/Makefile | 5 ++++- > tools/{testing/selftests => lib}/bpf/bpf_endian.h | 0 > tools/{testing/selftests => lib}/bpf/bpf_helpers.h | 0 > tools/{testing/selftests => lib}/bpf/bpf_tracing.h | 0 > tools/testing/selftests/bpf/Makefile | 2 +- > 6 files changed, 6 insertions(+), 3 deletions(-) > rename tools/{testing/selftests => lib}/bpf/bpf_endian.h (100%) > rename tools/{testing/selftests => lib}/bpf/bpf_helpers.h (100%) > rename tools/{testing/selftests => lib}/bpf/bpf_tracing.h (100%) ^^^^^ nice! :)
On Thu, Oct 3, 2019 at 1:17 PM Song Liu <liu.song.a23@gmail.com> wrote: > > On Wed, Oct 2, 2019 at 3:01 PM Andrii Nakryiko <andriin@fb.com> wrote: > > > > To allow adding a variadic BPF_CORE_READ macro with slightly different > > syntax and semantics, define CORE_READ in CO-RE reloc tests, which is > > a thin wrapper around low-level bpf_core_read() macro, which in turn is > > just a wrapper around bpf_probe_read(). > > > > Acked-by: John Fastabend <john.fastabend@gmail.com> > > Acked-by: Song Liu <songliubraving@fb.com> > > Signed-off-by: Andrii Nakryiko <andriin@fb.com> > > --- > > tools/testing/selftests/bpf/bpf_helpers.h | 8 ++++---- > > .../bpf/progs/test_core_reloc_arrays.c | 10 ++++++---- > > .../bpf/progs/test_core_reloc_flavors.c | 8 +++++--- > > .../selftests/bpf/progs/test_core_reloc_ints.c | 18 ++++++++++-------- > > .../bpf/progs/test_core_reloc_kernel.c | 6 ++++-- > > .../selftests/bpf/progs/test_core_reloc_misc.c | 8 +++++--- > > .../selftests/bpf/progs/test_core_reloc_mods.c | 18 ++++++++++-------- > > .../bpf/progs/test_core_reloc_nesting.c | 6 ++++-- > > .../bpf/progs/test_core_reloc_primitives.c | 12 +++++++----- > > .../bpf/progs/test_core_reloc_ptr_as_arr.c | 4 +++- > > 10 files changed, 58 insertions(+), 40 deletions(-) > > > > diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h > > index 7b75c38238e4..5210cc7d7c5c 100644 > > --- a/tools/testing/selftests/bpf/bpf_helpers.h > > +++ b/tools/testing/selftests/bpf/bpf_helpers.h > > @@ -483,7 +483,7 @@ struct pt_regs; > > #endif > > > > /* > > - * BPF_CORE_READ abstracts away bpf_probe_read() call and captures offset > > + * bpf_core_read() abstracts away bpf_probe_read() call and captures offset > > * relocation for source address using __builtin_preserve_access_index() > > * built-in, provided by Clang. > > * > > @@ -498,8 +498,8 @@ struct pt_regs; > > * actual field offset, based on target kernel BTF type that matches original > > * (local) BTF, used to record relocation. > > */ > > -#define BPF_CORE_READ(dst, src) \ > > - bpf_probe_read((dst), sizeof(*(src)), \ > > - __builtin_preserve_access_index(src)) > > +#define bpf_core_read(dst, sz, src) \ > > + bpf_probe_read(dst, sz, \ > > + (const void *)__builtin_preserve_access_index(src)) > > > > #endif > > diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c b/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c > > index bf67f0fdf743..58efe4944594 100644 > > --- a/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c > > +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c > > @@ -31,6 +31,8 @@ struct core_reloc_arrays { > > struct core_reloc_arrays_substruct d[1][2]; > > }; > > > > +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) > > We are using sizeof(*dst) now, but I guess sizeof(*src) is better? > And it should be sizeof(*(src)). There is no clear winner and I've debated which one I should go with, but I'm leaning towards using destination for the following reason. Size of destination doesn't change, it's not relocatable and whatnot, so this represents actual amount of storage we can safely read into (if the program logic is correct, of course). On the other hand, size of source might be different between kernels and we don't support relocating it when it's passed into bpf_probe_read() as second arg. There is at least one valid case where we should use destination size, not source size: if we have an array of something (e.g, chars) and we want to read only up to first N elements. In this case sizeof(*dst) is what you really want: program will pre-allocate exact amount of data and we'll do, say, char comm[16]; bpf_core_read(dst, task_struct->comm). If task_struct->comm ever increases, this all will work: we'll read first 16 characters only. In almost every other case it doesn't matter whether its dst or src, they have to match (i.e., we don't support relocation from int32 to int64 right now). > > > + > > SEC("raw_tracepoint/sys_enter") > > int test_core_arrays(void *ctx) > > { > > @@ -38,16 +40,16 @@ int test_core_arrays(void *ctx) > > struct core_reloc_arrays_output *out = (void *)&data.out; > > > > /* in->a[2] */ > > - if (BPF_CORE_READ(&out->a2, &in->a[2])) > > + if (CORE_READ(&out->a2, &in->a[2])) > > return 1; > > /* in->b[1][2][3] */ > > - if (BPF_CORE_READ(&out->b123, &in->b[1][2][3])) > > + if (CORE_READ(&out->b123, &in->b[1][2][3])) > > return 1; > > /* in->c[1].c */ > > - if (BPF_CORE_READ(&out->c1c, &in->c[1].c)) > > + if (CORE_READ(&out->c1c, &in->c[1].c)) > > return 1; > > /* in->d[0][0].d */ > > - if (BPF_CORE_READ(&out->d00d, &in->d[0][0].d)) > > + if (CORE_READ(&out->d00d, &in->d[0][0].d)) > > return 1; > > > > return 0; > > diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_flavors.c b/tools/testing/selftests/bpf/progs/test_core_reloc_flavors.c > > index 9fda73e87972..3348acc7e50b 100644 > > --- a/tools/testing/selftests/bpf/progs/test_core_reloc_flavors.c > > +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_flavors.c > > @@ -39,6 +39,8 @@ struct core_reloc_flavors___weird { > > }; > > }; > > > > +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) > > + > > SEC("raw_tracepoint/sys_enter") > > int test_core_flavors(void *ctx) > > { > > @@ -48,13 +50,13 @@ int test_core_flavors(void *ctx) > > struct core_reloc_flavors *out = (void *)&data.out; > > > > /* read a using weird layout */ > > - if (BPF_CORE_READ(&out->a, &in_weird->a)) > > + if (CORE_READ(&out->a, &in_weird->a)) > > return 1; > > /* read b using reversed layout */ > > - if (BPF_CORE_READ(&out->b, &in_rev->b)) > > + if (CORE_READ(&out->b, &in_rev->b)) > > return 1; > > /* read c using original layout */ > > - if (BPF_CORE_READ(&out->c, &in_orig->c)) > > + if (CORE_READ(&out->c, &in_orig->c)) > > return 1; > > > > return 0; > > diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_ints.c b/tools/testing/selftests/bpf/progs/test_core_reloc_ints.c > > index d99233c8008a..cfe16ede48dd 100644 > > --- a/tools/testing/selftests/bpf/progs/test_core_reloc_ints.c > > +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_ints.c > > @@ -23,20 +23,22 @@ struct core_reloc_ints { > > int64_t s64_field; > > }; > > > > +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) > > ditto. > > > + > > SEC("raw_tracepoint/sys_enter") > > int test_core_ints(void *ctx) > > { > > struct core_reloc_ints *in = (void *)&data.in; > > struct core_reloc_ints *out = (void *)&data.out; > > > > - if (BPF_CORE_READ(&out->u8_field, &in->u8_field) || > > - BPF_CORE_READ(&out->s8_field, &in->s8_field) || > > - BPF_CORE_READ(&out->u16_field, &in->u16_field) || > > - BPF_CORE_READ(&out->s16_field, &in->s16_field) || > > - BPF_CORE_READ(&out->u32_field, &in->u32_field) || > > - BPF_CORE_READ(&out->s32_field, &in->s32_field) || > > - BPF_CORE_READ(&out->u64_field, &in->u64_field) || > > - BPF_CORE_READ(&out->s64_field, &in->s64_field)) > > + if (CORE_READ(&out->u8_field, &in->u8_field) || > > + CORE_READ(&out->s8_field, &in->s8_field) || > > + CORE_READ(&out->u16_field, &in->u16_field) || > > + CORE_READ(&out->s16_field, &in->s16_field) || > > + CORE_READ(&out->u32_field, &in->u32_field) || > > + CORE_READ(&out->s32_field, &in->s32_field) || > > + CORE_READ(&out->u64_field, &in->u64_field) || > > + CORE_READ(&out->s64_field, &in->s64_field)) > > return 1; > > > > return 0; > > diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c b/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c > > index 37e02aa3f0c8..e5308026cfda 100644 > > --- a/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c > > +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_kernel.c > > @@ -17,6 +17,8 @@ struct task_struct { > > int tgid; > > }; > > > > +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) > ditto again, and more below. > > Thanks, > Song
On Wed, Oct 2, 2019 at 3:02 PM Andrii Nakryiko <andriin@fb.com> wrote:
>
> Add few macros simplifying BCC-like multi-level probe reads, while also
> emitting CO-RE relocations for each read.
>
> Acked-by: John Fastabend <john.fastabend@gmail.com>
> Signed-off-by: Andrii Nakryiko <andriin@fb.com>
> ---
> tools/lib/bpf/bpf_helpers.h | 143 ++++++++++++++++++++++++++++++++++++
> 1 file changed, 143 insertions(+)
>
> diff --git a/tools/lib/bpf/bpf_helpers.h b/tools/lib/bpf/bpf_helpers.h
> index cb9d4d2224af..847dfd7125e4 100644
> --- a/tools/lib/bpf/bpf_helpers.h
> +++ b/tools/lib/bpf/bpf_helpers.h
> @@ -19,6 +19,10 @@
> */
> #define SEC(NAME) __attribute__((section(NAME), used))
>
> +#ifndef __always_inline
> +#define __always_inline __attribute__((always_inline))
> +#endif
> +
> /* helper functions called from eBPF programs written in C */
> static void *(*bpf_map_lookup_elem)(void *map, const void *key) =
> (void *) BPF_FUNC_map_lookup_elem;
> @@ -312,4 +316,143 @@ struct bpf_map_def {
> bpf_probe_read(dst, sz, \
> (const void *)__builtin_preserve_access_index(src))
>
> +/*
nit: extra /*.
Well, I actually don't have a strong preference with this. Just to highlight
we are mixing two styles, which we already do in current bpf_helpers.h.
There are multiple other instances below.
Besides these.
Acked-by: Song Liu <songliubraving@fb.com>
On Thu, Oct 3, 2019 at 1:29 PM Andrii Nakryiko
<andrii.nakryiko@gmail.com> wrote:
>
> On Thu, Oct 3, 2019 at 1:17 PM Song Liu <liu.song.a23@gmail.com> wrote:
> >
> > On Wed, Oct 2, 2019 at 3:01 PM Andrii Nakryiko <andriin@fb.com> wrote:
> > >
> > > To allow adding a variadic BPF_CORE_READ macro with slightly different
> > > syntax and semantics, define CORE_READ in CO-RE reloc tests, which is
> > > a thin wrapper around low-level bpf_core_read() macro, which in turn is
> > > just a wrapper around bpf_probe_read().
> > >
> > > Acked-by: John Fastabend <john.fastabend@gmail.com>
> > > Acked-by: Song Liu <songliubraving@fb.com>
> > > Signed-off-by: Andrii Nakryiko <andriin@fb.com>
> > > ---
> > > tools/testing/selftests/bpf/bpf_helpers.h | 8 ++++----
> > > .../bpf/progs/test_core_reloc_arrays.c | 10 ++++++----
> > > .../bpf/progs/test_core_reloc_flavors.c | 8 +++++---
> > > .../selftests/bpf/progs/test_core_reloc_ints.c | 18 ++++++++++--------
> > > .../bpf/progs/test_core_reloc_kernel.c | 6 ++++--
> > > .../selftests/bpf/progs/test_core_reloc_misc.c | 8 +++++---
> > > .../selftests/bpf/progs/test_core_reloc_mods.c | 18 ++++++++++--------
> > > .../bpf/progs/test_core_reloc_nesting.c | 6 ++++--
> > > .../bpf/progs/test_core_reloc_primitives.c | 12 +++++++-----
> > > .../bpf/progs/test_core_reloc_ptr_as_arr.c | 4 +++-
> > > 10 files changed, 58 insertions(+), 40 deletions(-)
> > >
> > > diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
> > > index 7b75c38238e4..5210cc7d7c5c 100644
> > > --- a/tools/testing/selftests/bpf/bpf_helpers.h
> > > +++ b/tools/testing/selftests/bpf/bpf_helpers.h
> > > @@ -483,7 +483,7 @@ struct pt_regs;
> > > #endif
> > >
> > > /*
> > > - * BPF_CORE_READ abstracts away bpf_probe_read() call and captures offset
> > > + * bpf_core_read() abstracts away bpf_probe_read() call and captures offset
> > > * relocation for source address using __builtin_preserve_access_index()
> > > * built-in, provided by Clang.
> > > *
> > > @@ -498,8 +498,8 @@ struct pt_regs;
> > > * actual field offset, based on target kernel BTF type that matches original
> > > * (local) BTF, used to record relocation.
> > > */
> > > -#define BPF_CORE_READ(dst, src) \
> > > - bpf_probe_read((dst), sizeof(*(src)), \
> > > - __builtin_preserve_access_index(src))
> > > +#define bpf_core_read(dst, sz, src) \
> > > + bpf_probe_read(dst, sz, \
> > > + (const void *)__builtin_preserve_access_index(src))
> > >
> > > #endif
> > > diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c b/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c
> > > index bf67f0fdf743..58efe4944594 100644
> > > --- a/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c
> > > +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c
> > > @@ -31,6 +31,8 @@ struct core_reloc_arrays {
> > > struct core_reloc_arrays_substruct d[1][2];
> > > };
> > >
> > > +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src)
> >
> > We are using sizeof(*dst) now, but I guess sizeof(*src) is better?
> > And it should be sizeof(*(src)).
>
> There is no clear winner and I've debated which one I should go with,
> but I'm leaning towards using destination for the following reason.
> Size of destination doesn't change, it's not relocatable and whatnot,
> so this represents actual amount of storage we can safely read into
> (if the program logic is correct, of course). On the other hand, size
> of source might be different between kernels and we don't support
> relocating it when it's passed into bpf_probe_read() as second arg.
>
> There is at least one valid case where we should use destination size,
> not source size: if we have an array of something (e.g, chars) and we
> want to read only up to first N elements. In this case sizeof(*dst) is
> what you really want: program will pre-allocate exact amount of data
> and we'll do, say, char comm[16]; bpf_core_read(dst,
> task_struct->comm). If task_struct->comm ever increases, this all will
> work: we'll read first 16 characters only.
>
> In almost every other case it doesn't matter whether its dst or src,
> they have to match (i.e., we don't support relocation from int32 to
> int64 right now).
Hmm.. We could also reading multiple items into the same array, no?
Maybe we need another marco that takes size as an third parameter?
Also, for dst, it needs to be sizeof(*(dst)).
Thanks,
Song
On Thu, Oct 3, 2019 at 1:42 PM Song Liu <liu.song.a23@gmail.com> wrote: > > On Thu, Oct 3, 2019 at 1:29 PM Andrii Nakryiko > <andrii.nakryiko@gmail.com> wrote: > > > > On Thu, Oct 3, 2019 at 1:17 PM Song Liu <liu.song.a23@gmail.com> wrote: > > > > > > On Wed, Oct 2, 2019 at 3:01 PM Andrii Nakryiko <andriin@fb.com> wrote: > > > > > > > > To allow adding a variadic BPF_CORE_READ macro with slightly different > > > > syntax and semantics, define CORE_READ in CO-RE reloc tests, which is > > > > a thin wrapper around low-level bpf_core_read() macro, which in turn is > > > > just a wrapper around bpf_probe_read(). > > > > > > > > Acked-by: John Fastabend <john.fastabend@gmail.com> > > > > Acked-by: Song Liu <songliubraving@fb.com> > > > > Signed-off-by: Andrii Nakryiko <andriin@fb.com> > > > > --- > > > > tools/testing/selftests/bpf/bpf_helpers.h | 8 ++++---- > > > > .../bpf/progs/test_core_reloc_arrays.c | 10 ++++++---- > > > > .../bpf/progs/test_core_reloc_flavors.c | 8 +++++--- > > > > .../selftests/bpf/progs/test_core_reloc_ints.c | 18 ++++++++++-------- > > > > .../bpf/progs/test_core_reloc_kernel.c | 6 ++++-- > > > > .../selftests/bpf/progs/test_core_reloc_misc.c | 8 +++++--- > > > > .../selftests/bpf/progs/test_core_reloc_mods.c | 18 ++++++++++-------- > > > > .../bpf/progs/test_core_reloc_nesting.c | 6 ++++-- > > > > .../bpf/progs/test_core_reloc_primitives.c | 12 +++++++----- > > > > .../bpf/progs/test_core_reloc_ptr_as_arr.c | 4 +++- > > > > 10 files changed, 58 insertions(+), 40 deletions(-) > > > > > > > > diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h > > > > index 7b75c38238e4..5210cc7d7c5c 100644 > > > > --- a/tools/testing/selftests/bpf/bpf_helpers.h > > > > +++ b/tools/testing/selftests/bpf/bpf_helpers.h > > > > @@ -483,7 +483,7 @@ struct pt_regs; > > > > #endif > > > > > > > > /* > > > > - * BPF_CORE_READ abstracts away bpf_probe_read() call and captures offset > > > > + * bpf_core_read() abstracts away bpf_probe_read() call and captures offset > > > > * relocation for source address using __builtin_preserve_access_index() > > > > * built-in, provided by Clang. > > > > * > > > > @@ -498,8 +498,8 @@ struct pt_regs; > > > > * actual field offset, based on target kernel BTF type that matches original > > > > * (local) BTF, used to record relocation. > > > > */ > > > > -#define BPF_CORE_READ(dst, src) \ > > > > - bpf_probe_read((dst), sizeof(*(src)), \ > > > > - __builtin_preserve_access_index(src)) > > > > +#define bpf_core_read(dst, sz, src) \ > > > > + bpf_probe_read(dst, sz, \ > > > > + (const void *)__builtin_preserve_access_index(src)) > > > > > > > > #endif > > > > diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c b/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c > > > > index bf67f0fdf743..58efe4944594 100644 > > > > --- a/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c > > > > +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_arrays.c > > > > @@ -31,6 +31,8 @@ struct core_reloc_arrays { > > > > struct core_reloc_arrays_substruct d[1][2]; > > > > }; > > > > > > > > +#define CORE_READ(dst, src) bpf_core_read(dst, sizeof(*dst), src) > > > > > > We are using sizeof(*dst) now, but I guess sizeof(*src) is better? > > > And it should be sizeof(*(src)). > > > > There is no clear winner and I've debated which one I should go with, > > but I'm leaning towards using destination for the following reason. > > Size of destination doesn't change, it's not relocatable and whatnot, > > so this represents actual amount of storage we can safely read into > > (if the program logic is correct, of course). On the other hand, size > > of source might be different between kernels and we don't support > > relocating it when it's passed into bpf_probe_read() as second arg. > > > > There is at least one valid case where we should use destination size, > > not source size: if we have an array of something (e.g, chars) and we > > want to read only up to first N elements. In this case sizeof(*dst) is > > what you really want: program will pre-allocate exact amount of data > > and we'll do, say, char comm[16]; bpf_core_read(dst, > > task_struct->comm). If task_struct->comm ever increases, this all will > > work: we'll read first 16 characters only. > > > > In almost every other case it doesn't matter whether its dst or src, > > they have to match (i.e., we don't support relocation from int32 to > > int64 right now). > > Hmm.. We could also reading multiple items into the same array, no? Yeah, absolutely, there are cases in which BPF_CORE_READ won't work, unfortunately. That's why it was an internal debate, because there is no perfect answer :) > Maybe we need another marco that takes size as an third parameter? So my thinking for cases that are not compatible with BPF_CORE_READ intended use cases was that users will just do bpf_core_read(), which accepts same params as bpf_probe_read(), so they can do whatever they need to do. > > Also, for dst, it needs to be sizeof(*(dst)). You mean extra () around dst? Sure, will add. > > Thanks, > Song
On Thu, Oct 3, 2019 at 1:09 PM Song Liu <liu.song.a23@gmail.com> wrote:
>
> On Wed, Oct 2, 2019 at 3:01 PM Andrii Nakryiko <andriin@fb.com> wrote:
> >
> > Split off few legacy things from bpf_helpers.h into separate
> > bpf_legacy.h file:
> > - load_{byte|half|word};
> > - remove extra inner_idx and numa_node fields from bpf_map_def and
> > introduce bpf_map_def_legacy for use in samples;
> > - move BPF_ANNOTATE_KV_PAIR into bpf_legacy.h.
> >
> > Adjust samples and selftests accordingly by either including
> > bpf_legacy.h and using bpf_map_def_legacy, or switching to BTF-defined
> > maps altogether.
> >
> > Signed-off-by: Andrii Nakryiko <andriin@fb.com>
>
> Acked-by: Song Liu <songliubraving@fb.com>
>
> with a nit below
>
> > ---
> > samples/bpf/hbm_kern.h | 28 +++++++------
> > samples/bpf/map_perf_test_kern.c | 23 +++++------
> > samples/bpf/parse_ldabs.c | 1 +
> > samples/bpf/sockex1_kern.c | 1 +
> > samples/bpf/sockex2_kern.c | 1 +
> > samples/bpf/sockex3_kern.c | 1 +
> > samples/bpf/tcbpf1_kern.c | 1 +
> > samples/bpf/test_map_in_map_kern.c | 15 +++----
> > tools/testing/selftests/bpf/bpf_helpers.h | 24 +-----------
> > tools/testing/selftests/bpf/bpf_legacy.h | 39 +++++++++++++++++++
> > .../testing/selftests/bpf/progs/sockopt_sk.c | 13 +++----
> > tools/testing/selftests/bpf/progs/tcp_rtt.c | 13 +++----
> > .../selftests/bpf/progs/test_btf_haskv.c | 1 +
> > .../selftests/bpf/progs/test_btf_newkv.c | 1 +
> > 14 files changed, 92 insertions(+), 70 deletions(-)
> > create mode 100644 tools/testing/selftests/bpf/bpf_legacy.h
> >
> > diff --git a/samples/bpf/hbm_kern.h b/samples/bpf/hbm_kern.h
> > index aa207a2eebbd..91880a0e9c2f 100644
> > --- a/samples/bpf/hbm_kern.h
> > +++ b/samples/bpf/hbm_kern.h
> > @@ -24,6 +24,7 @@
> > #include <net/inet_ecn.h>
> > #include "bpf_endian.h"
> > #include "bpf_helpers.h"
> > +#include "bpf_legacy.h"
>
> nit: I guess we don't need bpf_legacy.h here?
You are right, I converted maps to BTF-defined ones, dropping bpf_legacy.h.
On Thu, Oct 3, 2019 at 1:35 PM Song Liu <liu.song.a23@gmail.com> wrote: > > On Wed, Oct 2, 2019 at 3:02 PM Andrii Nakryiko <andriin@fb.com> wrote: > > > > Add few macros simplifying BCC-like multi-level probe reads, while also > > emitting CO-RE relocations for each read. > > > > Acked-by: John Fastabend <john.fastabend@gmail.com> > > Signed-off-by: Andrii Nakryiko <andriin@fb.com> > > --- > > tools/lib/bpf/bpf_helpers.h | 143 ++++++++++++++++++++++++++++++++++++ > > 1 file changed, 143 insertions(+) > > > > diff --git a/tools/lib/bpf/bpf_helpers.h b/tools/lib/bpf/bpf_helpers.h > > index cb9d4d2224af..847dfd7125e4 100644 > > --- a/tools/lib/bpf/bpf_helpers.h > > +++ b/tools/lib/bpf/bpf_helpers.h > > @@ -19,6 +19,10 @@ > > */ > > #define SEC(NAME) __attribute__((section(NAME), used)) > > > > +#ifndef __always_inline > > +#define __always_inline __attribute__((always_inline)) > > +#endif > > + > > /* helper functions called from eBPF programs written in C */ > > static void *(*bpf_map_lookup_elem)(void *map, const void *key) = > > (void *) BPF_FUNC_map_lookup_elem; > > @@ -312,4 +316,143 @@ struct bpf_map_def { > > bpf_probe_read(dst, sz, \ > > (const void *)__builtin_preserve_access_index(src)) > > > > +/* > > nit: extra /*. > > Well, I actually don't have a strong preference with this. Just to highlight > we are mixing two styles, which we already do in current bpf_helpers.h. I made it consistent, thanks. > > There are multiple other instances below. > > Besides these. > > Acked-by: Song Liu <songliubraving@fb.com>