Releases: eunomia-bpf/eunomia-bpf
v0.3.6
v0.3.5
v0.3.4
What's Changed
- Fix analysis issues in shell and Rust by @ocfox in #133
- ecli image by @try-agaaain in #129
- Create auto_assign.yml by @yunwei37 in #123
- build ecc image by @try-agaaain in #135
- wasm-runtime: switch to wasm-bpf by @ocfox in #134
- fix-handler by @try-agaaain in #136
- move ecli (cpp version) to ecli/minimal by @try-agaaain in #137
- fix ecli-rs and move ecli/ecli-rs to ecli by @try-agaaain in #139
- update submodule wasm-runtime by @ocfox in #140
- fix the runqlat example by @try-agaaain in #149
- Fix ecli-rs link fail on aarch64 by @oluceps in #148
- Add RISC-V and MIPS support for eunomia-bpf by @oluceps in #152
- Fix minimal ecli build fail by @oluceps in #153
- ecc: add btfhub support by @ocfox in #156
- Add auto release to CI by @saivian1 in #127
New Contributors
Full Changelog: v0.3.3...v0.3.4
v0.3.3
v0.3.2
v0.3.1
v0.3.0
新的版本: 0.3.0
这个版本基本上把运行时和编译工具链的代码重写了一遍,带来了非常大的改动,同时配置文件的格式也和前几个版本并不兼容。
运行时优化:大幅度增强功能性
- 支持根据代码中的注释信息自动生成用户态命令行参数。
比如需要实现一个 ebpf 程序里面的 pid 过滤器,只需要编写内核态代码,在 eBPF 中声明全局变量,即可自动生成命令行参数:
/// 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;
(inspired by doxygen)
我们会将注释文档的描述信息提取,放在配置文件里面,并且变成 eBPF 应用的命令行参数:
使用方式以跟踪所有 open 系统调用的 opensnoop 为例:
$ 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 trace
$ sudo ecli examples/bpftools/opensnoop/package.json --pid_target 754
TIME TS PID UID RET FLAGS COMM FNAME
20:34:13 0 754 0 6 0 irqbalance /proc/interrupts
20:34:13 0 754 0 6 0 irqbalance /proc/stat
20:34:23 0 754 0 6 0 irqbalance /proc/interrupts
20:34:23 0 754 0 6 0 irqbalance /proc/stat
- 支持自动采集和综合非 ring buffer 和 perf event 的 map,比如 hash map,打印出信息或生成直方图。
之前使用 ring buffer 和 perf event 的场景会稍微受限,因此需要有一种方法可以自动从 maps 里面采集数据,在源代码里面添加注释即可:
/// @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");
就会每隔一秒去采集一次 counters 里面的内容(print_map),以 runqlat 为例:
$ sudo ecli examples/bpftools/runqlat/package.json -h
Usage: runqlat_bpf [--help] [--version] [--verbose] [--filter_cg] [--targ_per_process] [--targ_per_thread] [--targ_per_pidns] [--targ_ms] [--targ_tgid VAR]
Summarize run queue (scheduler) latency as a histogram.
Optional arguments:
-h, --help shows help message and exits
-v, --version prints version information and exits
--verbose prints libbpf debug information
--filter_cg set value of bool variable filter_cg
--targ_per_process set value of bool variable targ_per_process
--targ_per_thread set value of bool variable targ_per_thread
--targ_per_pidns set value of bool variable targ_per_pidns
--targ_ms set value of bool variable targ_ms
--targ_tgid set value of pid_t variable targ_tgid
Built with eunomia-bpf framework.
See https://github.com/eunomia-bpf/eunomia-bpf for more information.
$ sudo ecli examples/bpftools/runqlat/package.json
key = 4294967295
comm = rcu_preempt
(unit) : count distribution
0 -> 1 : 9 |**** |
2 -> 3 : 6 |** |
4 -> 7 : 12 |***** |
8 -> 15 : 28 |************* |
16 -> 31 : 40 |******************* |
32 -> 63 : 83 |****************************************|
64 -> 127 : 57 |*************************** |
128 -> 255 : 19 |********* |
256 -> 511 : 11 |***** |
512 -> 1023 : 2 | |
1024 -> 2047 : 2 | |
2048 -> 4095 : 0 | |
4096 -> 8191 : 0 | |
8192 -> 16383 : 0 | |
16384 -> 32767 : 1 | |
$ sudo ecli examples/bpftools/runqlat/package.json --targ_per_process
key = 3189
comm = cpptools
(unit) : count distribution
0 -> 1 : 0 | |
2 -> 3 : 0 | |
4 -> 7 : 0 | |
8 -> 15 : 1 |*** |
16 -> 31 : 2 |******* |
32 -> 63 : 11 |****************************************|
64 -> 127 : 8 |***************************** |
128 -> 255 : 3 |********** |
- 输出优化
- 输出格式规整
- 提高可读性
$ sudo ecli examples/bpftools/opensnoop/package.json
TIME TS PID UID RET FLAGS COMM FNAME
20:31:50 0 1 0 51 524288 systemd /proc/614/cgroup
20:31:50 0 33182 0 25 524288 ecli /etc/localtime
20:31:53 0 754 0 6 0 irqbalance /proc/interrupts
20:31:53 0 754 0 6 0 irqbalance /proc/stat
20:32:03 0 754 0 6 0 irqbalance /proc/interrupts
20:32:03 0 754 0 6 0 irqbalance /proc/stat
20:32:03 0 632 0 7 524288 vmtoolsd /etc/mtab
20:32:03 0 632 0 9 0 vmtoolsd /proc/devices
$ sudo ecli examples/bpftools/opensnoop/package.json --pid_target 754
TIME TS PID UID RET FLAGS COMM FNAME
20:34:13 0 754 0 6 0 irqbalance /proc/interrupts
20:34:13 0 754 0 6 0 irqbalance /proc/stat
20:34:23 0 754 0 6 0 irqbalance /proc/interrupts
20:34:23 0 754 0 6 0 irqbalance /proc/stat
编译方面:编译体验优化、格式改进
- 完全重构了编译工具链和配置文件格式,回归本质的配置文件 + ebpf 字节码 .o 的形式,不强制打包成一个大 JSON(现在编译后生成 xxx.bpf.o 和 xxx.skel.json),对分发使用和人类编辑配置文件更友好,当然也可以编译为 package.json
- 支持 JSON 和 YAML 两种形式的配置文件(xxx.skel.yaml 和 xxx.skel.json),或者打包成 package.json 和 package.yaml
- 剔除了一大堆没用的 llvm 信息,尽可能使用 BTF 信息表达符号类型,并且把 BTF 信息隐藏在二进制文件中,让配置文件更可读和可编辑,同时复用 libbpf 提供的 BTF 处理机制,完善对于类型的处理;
- 支持更多的数据导出类型:enum、struct、bool 等等
- 编译部分可以不依赖于 docker 运行,可以安装二进制到 ~/.eunomia(对嵌入式或者国内网络更友好,有时也更方便使用),原本 docker 的使用方式还是可以继续使用;
- 指定源文件和头文件变得更方便,除了和源文件在同一目录的头文件(maps.bpf.h这样的 helper)会被自动包含以外,可以指定任意别的 include 路径、添加任何 clang 编译参数(就和正常调用编译器差不多),文件名没有特定限制,不需要一定是 xxx.bpf.h 和 xxx.bpf.c,可以通过 ecc 指定需要编译的文件
- 把 example 中旧的 xxx.bpf.h 头文件修改为 xxx.h,和 libbpf-tools 和 libbpf-boostrap 保持一致,确保 0 代码修改即可复用旧代码;
- 大幅度优化编译速度和减少编译依赖,使用 Rust 重构了编译工具链,替换原先的 python 脚本
ecc 的帮助信息:
$ ecc -h
eunomia-bpf compiler
Usage: ecc [OPTIONS] <SOURCE_PATH> [EXPORT_EVENT_HEADER]
Arguments:
<SOURCE_PATH> path of the bpf.c file to compile
[EXPORT_EVENT_HEADER] path of the bpf.h header for defining event struct [default: ]
Options:
-o, --output-path <OUTPUT_PATH> path of output bpf object [default: ]
-a, --additional-cflags <ADDITIONAL_CFLAGS> additional c flags for clang [default: ]
-c, --clang-bin <CLANG_BIN> path of clang binary [default: clang]
-l, --llvm-strip-bin <LLVM_STRIP_BIN> path of llvm strip binary [default: llvm-strip]
-s, --subskeleton do not pack bpf object in config file
-v, --verbose print the command execution
-y, --yaml output config skel file in yaml
-h, --help Print help information (use `--help` for more detail)
-V, --version Print version information
新的编译方式:
$ ecc bootstrap.bpf.c bootstrap.h
Compiling bpf object...
Generating export types...
Packing ebpf object and config into package.json...
$ ls
bootstrap.bpf.c bootstrap.bpf.o bootstrap.h bootstrap.skel.json package.json README.md
其中编译产物是:
- bootstrap.bpf.o:object 文件
- bootstrap.skel.json:配置信息文件
- package.json:打包好的 eBPF 程序
添加 -y 参数即可生成 YAML 文件,而不是 JSON 文件。
新的配置文件举例:可以直接修改 progs/attach 控制挂载点,variables/value 控制全局变量,maps/data 控制在加载 ebpf 程序时往 map 里面放什么数据,export_types/members 控制往用户态传输什么数据格式,而不需要重新编译。配置文件和 bpf.o 二进制是配套的,应该搭配使用,或者打包成一个 package.json/yaml 分发。打包的时候有压缩,一般来说压缩后的配置文件和二进制合起来的大小在数十 kb 这样。
bpf_skel:
data_sections:
- name: .rodata
variables:
- name: min_duration_ns
type: unsigned long long
value: 100
maps:
- ident: exec_start
name: exec_start
data:
- key: 123
value: 456
- ident: rb
name: rb
- ident: rodata
mmaped: true
name: client_b.rodata
obj_name: client_bpf
progs:
- attach: tp/sched/sched_process_exec
link: true
name: handle_exec
export_types:
- members:
- name: pid
type: int
- name: ppid
type: int
- name: comm
type: char[16]
- name: filename
type: char[127]
- name: exit_event
type: bool
name: event
type_id: 613
build or install the project
-
Install the
ecli
tool for running eBPF program from the cloud:$ wget https://aka.pw/bpf-ecli -O ecli && chmod +x ./ecli $ ./ecli -h Usage: ecli [--help] [--version] [--json] [--no-cache] url-and-args ....
-
Install the compiler-toolchain for compiling eBPF kernel code to a
config
fil...