bpf2go: ship common C headers
Once a user has discovered bpf2go they usually need to figure out where to get headers from. We can remove this pain point by shipping common headers via a go:embed directive. When invoking the binary we could extract those headers to a temporary directory and then add the directory as an include path to the clang invocation.
We can categorize headers as such:
- Linux BPF UAPI:
linux/bpf.h,linux/bpf_common.h, etc. Available asGPL-2.0 WITH Linux-syscall-note. - libbpf API:
bpf/bpf_helpers.h,bpf/bpf_endian.h, etc. Available asLGPL-2.1 OR BSD-2-Clause. - Linux "library" headers: definitions of
struct iphdretc. Various licenses, some GPL-only. - libc headers:
stdint.h,stdbool.h, etc. License depends on which libc you use, I've used musl in the past which is MIT. Suffers from the problem that BPF isn't a supported libc target so hacks are necessary. - vmlinux.h: "the big one". Probably only compatible with GPLv2.
I think we can easily ship 1-2 based on https://github.com/cloudflare/rakelimit/tree/master/include (note linux/types.h which avoids pulling in a bunch of other Linux headers). 3-5 are difficult either because of licensing or because they are too big to ship.
Steps:
- Extend https://github.com/cilium/ebpf/blob/2113a5f7979dfd878db4e2fac2421565af45df41/examples/headers/update.sh to include (1) from above or adapt https://github.com/cloudflare/rakelimit/blob/master/include/Makefile
- Add a subdirectory to bpf2go which contains headers, and include them via go:embed
- Unpack headers at build time and add a
-Ito the clang invocation
Open questions:
- Should headers be available by default, or only when a user passes a
-with-headersflag? The former has better UX, but we then have to make sure that user provided include paths take precedence. It's also problematic if the user tries to compile against system installed kernel headers (not recommended, but does happen). We might have to start passing-nostdincto clang by default, which could break builds.
We could always relicense bpf2go under the GPL. Since it's a CLI tool and not part of the build artifact, it should not be subject to the same linking restrictions as libraries are. Not a lawyer, though. :sweat_smile:
The problem isn't bpf2go, it's the user code using the headers.
Since vmlinux.h is huge, shipping the whole header produces larger binaries. In libbpf-tools llvm-strip is used to removed unused objects https://github.com/iovisor/bcc/blob/master/libbpf-tools/Makefile#L4
I think bpf2go should support stripping too with flag. eg -strip which may require to have llvm-strip installed.
Good point, I think that is #429