introduction
eunomia-bpf is a dynamic loading library/runtime and a compile toolchain framework, aim at helping you build and distribute eBPF programs easier.
Simplify building CO-RE libbpf eBPF applications
Just Write libbpf eBPF kernel code only, auto config the userspace part!
Automatically exposing your data from kernel
-
Get data automatically from
perf eventorring bufferto userspace:struct { __uint(type, BPF_MAP_TYPE_RINGBUF); __uint(max_entries, 256 * 1024); } rb SEC(".maps"); SEC("tp/sched/sched_process_exec") int handle_exec(struct trace_event_raw_sched_process_exec *ctx) { .... e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); .... bpf_ringbuf_submit(e, 0); return 0; }Compile and Run the program:
$ ecc bootstrap.bpf.c bootstrap.h Compiling bpf object... Generating export types... Packing ebpf object and config into package.json... $ sudo ./ecli examples/bpftools/bootstrap/package.json TIME PID PPID EXIT_CODE DURATION_NS COMM FILENAME EXIT_EVENT 22:01:04 46310 2915 0 0 sh /bin/sh 0 22:01:04 46311 46310 0 0 which /usr/bin/which 0 22:01:04 46311 46310 0 2823776 which 1 22:01:04 46310 2915 0 6288891 sh 1 22:01:04 46312 2915 0 0 sh /bin/sh 0 22:01:04 46313 46312 0 0 ps /usr/bin/ps 0see bootstrap for example. This is exactly the same as bootstrap.bpf.c in libbpf-bootstrap project, but only kernel code is needed.
Automatically sample the data and print hists in userspace
-
Sample the data from hash maps and print them in human readable format with comments:
/// @sample {"interval": 1000, "type" : "log2_hist"} struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(max_entries, MAX_ENTRIES); __type(key, u32); __type(value, struct hist); } hists SEC(".maps");and Get
histdata fromhistsmap and print them in human readable format:$ sudo ecli examples/bpftools/runqlat/package.json --targ_per_process key = 8326 comm = containerd usec : count distribution 0 -> 1 : 0 | | 2 -> 3 : 0 | | 4 -> 7 : 0 | | 8 -> 15 : 0 | | 16 -> 31 : 2 |************* | 32 -> 63 : 2 |************* | 64 -> 127 : 6 |****************************************| 128 -> 255 : 0 | | 256 -> 511 : 2 |************* |see examples/bpftools/mdflush.bpf.c for example.
Automatically generate and config command line arguments
-
Automatically generate and config command line arguments for your eBPF program from the comments in your kernel code:
/// Process ID to trace const volatile pid_t pid_target = 0; /// Thread ID to trace const volatile pid_t tgid_target = 0; /// @description User ID to trace const volatile uid_t uid_target = 0; /// @cmdarg {"default": false, "short": "f", "long": "failed"} /// @description target pid to trace const volatile bool targ_failed = false;and Get:
$ sudo ecli examples/bpftools/opensnoop/package.json -h Usage: opensnoop_bpf [--help] [--version] [--verbose] [--pid_target VAR] [--tgid_target VAR] [--uid_target VAR] [--failed] Trace open family syscalls. Optional arguments: -h, --help shows help message and exits -v, --version prints version information and exits --verbose prints libbpf debug information --pid_target Process ID to trace --tgid_target Thread ID to tracesee examples/bpftools/opensnoop/opensnoop.bpf.c for example.
-
100%compatible withlibbpf, libbpf-bootstrap andlibbpf-rs, etc: you can compile libbpf-tools kernel code witheunomia-bpfand run them without many modification! - Not limited to tracing: support
tracepoints,kprobe,uprobe,lsm,xdp,tcetc...
Compile and pack CO-RE eBPF kernel code to a config file
-
Compile and pack CO-RE eBPF kernel code to a
JSONorYAMLconfig file:$ ecc cmd/test/opensnoop.bpf.c opensnoop.h Compiling bpf object... Generating export types... Packing ebpf object and config into package.json... $ docker run -it -v `pwd`/:/src/ ghcr.io/eunomia-bpf/ecc-`uname -m`:latest # build with docker for x86_64 and aarch64 Packing ebpf object and config into package.json...You can modify the config file and config the eBPF program behavior to your need.
Dynamic load and run CO-RE eBPF kernel code from the cloud with URL or OCI image
-
you can dynamically load it on different kernel version without recompile, and without clang/llvm dependency:
$ sudo ecli opensnoop.json TIME PID TPID SIG RET COMM 22:58:28 77121 3168 0 0 cpptools-srv 22:58:29 69044 3168 0 0 cpptools-srv 22:58:29 3014 2906 0 0 code 22:58:29 6952 4061 0 0 node 22:58:29 4061 3937 0 0 node 22:58:29 75263 3168 0 0 cpptools-srv 22:58:29 2906 2488 0 0 code 22:58:29 69149 3168 0 0 cpptools-srv 22:58:29 73541 3168 0 0 cpptools-srv 22:58:29 73468 3168 0 0 cpptools-srv 22:58:29 2906 2488 0 0 code 22:58:29 69094 3168 0 0 cpptools-srv -
Get pre-compiled eBPF programs running from the cloud to the kernel in
1line of bash, kernel version and architecture independent:# download the release from https://github.com/eunomia-bpf/eunomia-bpf/releases/latest/download/ecli $ wget https://aka.pw/bpf-ecli -O ecli && chmod +x ./ecli $ sudo ./ecli https://eunomia-bpf.github.io/eunomia-bpf/sigsnoop/package.json # simply run a pre-compiled ebpf code from a url $ sudo ./ecli sigsnoop:latest # run with a name and download the latest version bpf tool from our repo -
very small and simple! The library itself
<1MBand noLLVM/Clangdependence, can be embedded easily in you project - as fast as
<100msand little resource need to dynamically load and run eBPF program
Base on eunomia-bpf, we have an eBPF pacakge manager in LMP project, with OCI images and ORAS for distribution.
wasm-bpf: Write user space code for your eBPF program in WebAssembly
see wasm-bpf project:
A WebAssembly eBPF library, toolchain and runtime powered by CO-RE(Compile Once – Run Everywhere) libbpf and WAMR.
General purpose: provide most abilities from eBPF to Wasm,pollingfrom the ring buffer or perf buffer, bidirectional communications betweenkerneleBPF anduserspaceWasm usingmaps, dynamicallyloading,attachingordetaching, etc. Supports a large number of eBPF program types and map types, covering the use cases fromtracing,networking,security.High performance: Noserializationoverhead for complex data types, usingshared memoryto avoid copy overhead between host and Wasm.Easy to use: provide a similar developing experience as the libbpf-bootstrap,auto generatethe Wasm-eBPF skeleton headers and type definitions for bindings.Ultralightweight: the sample runtime has only300+lines of code, binary only1.5 MBin size. Compiled Wasm module would be only~90K. With the same toolchain, you can easily build your own Wasm-eBPF runtime in any languages and platforms!
Project Architecture
we have a loader library, a compile toolchain, and some additional tools like cli and a custom metrics exporter.

An bpf-loader-rs library
A wrapper of main functions of libbpf-rs, provide the ability to dynamically load eBPF code to the kernel and run it with a simple JSON and a few API.
A simple cli interface is provided for bpf-loader library, which you can use it to start any eBPF program from a url in a command. You can download it from release.
see examples for more examples.
A library to load and operate eBPF program from a WASM module
Use the eunomia-bpf library to load eBPF program from a WASM module, you can write a WASM module to operate the eBPF program or process the data in user space WASM runtime. The idea is simple:
- compile the kernel eBPF code skeleton to the
JSONformat witheunomia-cctoolchain - embed the
JSONdata in theWASMmodule, and provide some API for operating the eBPF program skeleton - load the
JSONdata from theWASMmodule and run the eBPF program skeleton witheunomia-bpflibrary
You can have multiple eBPF program in a single WASM module.
See wasm-runtime for details. In fact, ewasm library only exports a few functions from bpf-loader library to the VM, so you can replace the WASM runtime with your own easily.
For example, you can run an eBPF program with a WASM module for an URL:
You can also generate a WASM program template for eBPF or build WASM module with compiler container:
# for x86_64 and aarch64
docker run -it -v `pwd`/:/src/ ghcr.io/eunomia-bpf/ecc-`uname -m`:latest gen-wasm-skel # generate WASM app template for eBPF
docker run -it -v `pwd`/:/src/ ghcr.io/eunomia-bpf/ecc-`uname -m`:latest build-wasm # Build WASM module
see sigsnoop example for more detail.
A compile toolchain to help you generate pre compiled eBPF data
The toolchain can be used as a docker to generate pre-compiled eBPF data in one command:
see the compile toolchains compiler for details.
you can also simply use the ebpm-template repo as a template in github, just push to it and github action can help you compile CO-RE ebpf code!
other related projects
-
LMP eBPF Hub: github.com/linuxkerneltravel/lmp
a package manager for eBPF based on wasm modules
-
bolipi online compiler & runner: https://bolipi.com/ebpf/home/online
an online compiler and runner for eBPF program newbies
-
An Observability tool
An prometheus and OpenTelemetry exporter for custom eBPF metrics, written in async rust: eunomia-exporter. You can compile it or download from release
build the project
see build for details.