aboutsummaryrefslogtreecommitdiff
path: root/tools/lib/bpf/bpf_endian.h
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2019-10-08 23:16:04 +0200
committerDaniel Borkmann <daniel@iogearbox.net>2019-10-08 23:18:19 +0200
commitf05c2001ecc98629cecd47728e4db11e5a17e58d (patch)
treeb0b3c485a950387adf3d4eff04a21b41e11620fe /tools/lib/bpf/bpf_endian.h
parent8fdf5b780a148c4a7490c211acad3c01b4dde6ac (diff)
parentee2eb063d330dc8dbe71041a1dae3cea889fdcb5 (diff)
downloadlinux-f05c2001ecc98629cecd47728e4db11e5a17e58d.tar.gz
linux-f05c2001ecc98629cecd47728e4db11e5a17e58d.tar.bz2
linux-f05c2001ecc98629cecd47728e4db11e5a17e58d.zip
Merge branch 'bpf-libbpf-helpers'
Andrii Nakryiko says: ==================== 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 and bpf_helper_defs.h generation 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(). v4->v5: - move BPF_CORE_READ() stuff into bpf_core_read.h header (Alexei); v3->v4: - rebase on latest bpf-next master; - bpf_helper_defs.h generation is moved into libbpf's Makefile; v2->v3: - small formatting fixes and macro () fixes (Song); 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; ==================== Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'tools/lib/bpf/bpf_endian.h')
-rw-r--r--tools/lib/bpf/bpf_endian.h72
1 files changed, 72 insertions, 0 deletions
diff --git a/tools/lib/bpf/bpf_endian.h b/tools/lib/bpf/bpf_endian.h
new file mode 100644
index 000000000000..fbe28008450f
--- /dev/null
+++ b/tools/lib/bpf/bpf_endian.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
+#ifndef __BPF_ENDIAN__
+#define __BPF_ENDIAN__
+
+#include <linux/stddef.h>
+#include <linux/swab.h>
+
+/* LLVM's BPF target selects the endianness of the CPU
+ * it compiles on, or the user specifies (bpfel/bpfeb),
+ * respectively. The used __BYTE_ORDER__ is defined by
+ * the compiler, we cannot rely on __BYTE_ORDER from
+ * libc headers, since it doesn't reflect the actual
+ * requested byte order.
+ *
+ * Note, LLVM's BPF target has different __builtin_bswapX()
+ * semantics. It does map to BPF_ALU | BPF_END | BPF_TO_BE
+ * in bpfel and bpfeb case, which means below, that we map
+ * to cpu_to_be16(). We could use it unconditionally in BPF
+ * case, but better not rely on it, so that this header here
+ * can be used from application and BPF program side, which
+ * use different targets.
+ */
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+# define __bpf_ntohs(x) __builtin_bswap16(x)
+# define __bpf_htons(x) __builtin_bswap16(x)
+# define __bpf_constant_ntohs(x) ___constant_swab16(x)
+# define __bpf_constant_htons(x) ___constant_swab16(x)
+# define __bpf_ntohl(x) __builtin_bswap32(x)
+# define __bpf_htonl(x) __builtin_bswap32(x)
+# define __bpf_constant_ntohl(x) ___constant_swab32(x)
+# define __bpf_constant_htonl(x) ___constant_swab32(x)
+# define __bpf_be64_to_cpu(x) __builtin_bswap64(x)
+# define __bpf_cpu_to_be64(x) __builtin_bswap64(x)
+# define __bpf_constant_be64_to_cpu(x) ___constant_swab64(x)
+# define __bpf_constant_cpu_to_be64(x) ___constant_swab64(x)
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+# define __bpf_ntohs(x) (x)
+# define __bpf_htons(x) (x)
+# define __bpf_constant_ntohs(x) (x)
+# define __bpf_constant_htons(x) (x)
+# define __bpf_ntohl(x) (x)
+# define __bpf_htonl(x) (x)
+# define __bpf_constant_ntohl(x) (x)
+# define __bpf_constant_htonl(x) (x)
+# define __bpf_be64_to_cpu(x) (x)
+# define __bpf_cpu_to_be64(x) (x)
+# define __bpf_constant_be64_to_cpu(x) (x)
+# define __bpf_constant_cpu_to_be64(x) (x)
+#else
+# error "Fix your compiler's __BYTE_ORDER__?!"
+#endif
+
+#define bpf_htons(x) \
+ (__builtin_constant_p(x) ? \
+ __bpf_constant_htons(x) : __bpf_htons(x))
+#define bpf_ntohs(x) \
+ (__builtin_constant_p(x) ? \
+ __bpf_constant_ntohs(x) : __bpf_ntohs(x))
+#define bpf_htonl(x) \
+ (__builtin_constant_p(x) ? \
+ __bpf_constant_htonl(x) : __bpf_htonl(x))
+#define bpf_ntohl(x) \
+ (__builtin_constant_p(x) ? \
+ __bpf_constant_ntohl(x) : __bpf_ntohl(x))
+#define bpf_cpu_to_be64(x) \
+ (__builtin_constant_p(x) ? \
+ __bpf_constant_cpu_to_be64(x) : __bpf_cpu_to_be64(x))
+#define bpf_be64_to_cpu(x) \
+ (__builtin_constant_p(x) ? \
+ __bpf_constant_be64_to_cpu(x) : __bpf_be64_to_cpu(x))
+
+#endif /* __BPF_ENDIAN__ */