TIL: Pinning eBPF maps
2024-11-18 00:00:00 +0000 UTCSometimes, you want two eBPF programs to share one map for inter-eBPF communication, or access to some pooled collection from your userspace program. In order to do this, eBPF provides a “pinning” mechanism.
To use this mechanism when loading the eBPF program using ebpf-go, you must first mark your maps pinned in your eBPF C files. In my case, I want to apply uprobe and uretprobe eBPF programs to the same function, and push their messages to the same BPF perf event array. So I define my struct like this:
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
__uint(pinning, LIBBPF_PIN_BY_NAME);
} bash_uprobe_events SEC(".maps");
Next, in our Go program, we need to load our programs using a pinning option:
if err := os.MkdirAll("/sys/fs/bpf/uprobe_bash_pin", os.ModePerm); err != nil {
log.Fatalf("failed to create bpf path: %+v", err)
}
options := ebpf.CollectionOptions{
Maps: ebpf.MapOptions{
PinPath: "/sys/fs/bpf/uprobe_bash_pin",
},
}
This ebpf.CollectionOptions
struct is accepted by the bpf2go
generated load*Objects()
functions as well as the underlying ebpf.LoadAndAssign
function.
Sources: * eBPF.io: Pinning * ebpf-go pinning example