microsoft / ebpf-for-windows

eBPF implementation that runs on top of Windows
MIT License
2.95k stars 240 forks source link

Make `bpf()` wrapper ABI compatible with Linux #3729

Open lmb opened 4 months ago

lmb commented 4 months ago

Describe the feature you'd like supported

This is an alternative proposal to https://github.com/microsoft/ebpf-for-windows/issues/3700. Based on feedback by my colleague Timo I had a look at invoking the bpf() syscall wrapper via LoadLibrary (this was mentioned by @shankarseal during the last triage). It turns out this works, and would make it easier to port cilium/ebpf.

The problem is that at efW is currently API compatible with bpf(), but does not follow the Linux ABI. This means we can't use our existing syscall wrappers to call into ebpfabi.dll. As I mentioned earlier we can't make use of API compatibility since that forces use of CGO.

Proposed solution

Guarantee that the exposed bpf() function follows the Linux ABI. Figure out a way to reuse bpf_attr, etc. from upstream as much as possible.

Additional context

Here is a non-exhaustive list of things that would need to be fixed:

We'd also need some new API (these don't have to go via bpf()):

shankarseal commented 4 months ago

Linux headers can be used as long as it has BSD clause.

shankarseal commented 4 months ago

This proposal (#3729) is preferred over #3700. In principle this is what the eBPF for Windows team had wanted all along.

jrfastab commented 4 months ago

@Alan-Jowett would it be possible to use BTF from Linux to generate/test/create ABI compat? You should have enough information there to understand structure layout for example.

lmb commented 4 months ago

Also discussed during triage: we can run ebpf-go unit tests during efW CI as integration tests.

Alan-Jowett commented 3 months ago

Adding myself as an assignee to track the BTF related suggestion. I agree this makes sense and we should do something like this.

Ideally we would be able to just grab the BTF data from the eBPF for Windows build and from the Linux kernel symbols and then diff the BTF types.

Unfortunately, this won't work as MSVC doesn't emit BTF data.

What I think we can do is: 1) Write a trivial C file that pulls in and references the various structs being passed the BPF syscall. 2) Compile this C file as BPF 3) Extract the BTF data for the types passed to this syscall

It should then be possible to validate alignment etc.

lmb commented 3 months ago

Another problem is that Windows errno.h defines constants for errno which have the same names as on Linux but do not always have the same value. See https://learn.microsoft.com/en-us/cpp/c-runtime-library/errno-constants?view=msvc-170

For example, ENOBUFS is 119 on Windows, while on Linux it is 105.

lmb commented 3 months ago

BPF_OBJ_NAME_LEN is 64 but Linux expects 16.

lmb commented 3 months ago

struct bpf_map_info and struct bpf_prog_info don't follow Linux ABI by having fields in the wrong order, and by defining Windows specific fields.

dthaler commented 3 months ago

The original goal was to be source compatible rather than binary compatible with Linux, so that is not surprising.