1

I am using ebpf to capture process creation. I am using ringbuf for kernel 5.8 and above and would like to use perfbuf for older kernels in the same ebpf kernel file. There is a great blog about it https://nakryiko.com/posts/bpf-core-reference-guide/#linux-kernel-version, according to it I can use a code like:

if (LINUX_KERNEL_VERSION < KERNEL_VERSION(5, 8, 0))
{
    // use the perfbuf
}
else
{
    // use the ringbuf
}

and the loader ignores the dead code. The issue is how to declare the ring buffer map under such a condition, because it is declared in a global scope and not inside a function:

struct {
    __uint(type, BPF_MAP_TYPE_RINGBUF);
    __uint(max_entries, 64 * 4096);
} rb SEC(".maps");

In kernels before 5.8 BPF_MAP_TYPE_RINGBUF is not defined and the load fails. Is there some Initialization function that is called that I can define and add the map in there according to the kernel version?

Ido Kelson
  • 13
  • 2

1 Answers1

1

The creation of maps like this is always performed by the loader. So you can declare both a ring buffer and perf buffer and write your userspace program in such a way as to only load one of the two.

In general it isn't recommended to use kernel versions to detect feature support since some distros will backport certain features to older kernel versions (RedHat enterprise for example).

So if at all possible, its recommended to use feature probes provided by bpftool or cilium/ebpf.

In the case of bpftool it is also possible to ask the command to output C macros which allow you to use #ifdef pre-processor statements in your eBPF code (though this will require compiling on the target).

Dylan Reimerink
  • 5,874
  • 2
  • 15
  • 21
  • Thanks for the answer. This is exactly what I am trying to do, but it seems just the declaration of the ringbuf map causes the error, even if I comment out all the ringbuf code in kernel and user – Ido Kelson Jan 02 '23 at 09:38
  • What error are you getting? – Dylan Reimerink Jan 02 '23 at 10:54
  • libbpf: map 'rb': failed to create: Invalid argument(-22) It works on newer kernels where rinbuf is supported – Ido Kelson Jan 02 '23 at 16:08
  • 1
    Seems like you are always trying to load the map. You should disable the map autocreation https://github.com/libbpf/libbpf/blob/master/src/libbpf.h#L773. Then load whichever map you are planning on using manually – Dylan Reimerink Jan 03 '23 at 12:39
  • I have a follow up question. 1) Without using the kernel version, I see how I can find if ringbuf is supported in the kernel part, but not in the user space part? 2) I could not find an example on how to load a specific map after disabling the autocreate – Ido Kelson Jan 11 '23 at 15:42
  • It would be easiest if you would just disable autocreate on one of the two maps depending on which you decided to load. The alternative is to use the `bpf_map_create` function, you have to extract all of the required info using the `bpf_map__*` calls. After creating, you need to pin that map with `bpf_obj_pin` and set the same path on the `struct bpf_map` with `bpf_map__set_pin_path`. This will cause libbpf to reuse the pinned map properly – Dylan Reimerink Jan 12 '23 at 08:59