Welcome to coolbpf’s documentation!
This is the top level of the coolbpf’s documentation tree. Coolbpf documentation, like the coolbpf itself, is very much a work in progress; that is especially true as we work to integrate our many scattered documents into a coherent whole. Please note that improvements to the documentation are welcome; join coolbpf at https://gitee.com/anolis/coolbpf.git if you want to help out.
Coolbpf API Documentation
This is documentation for coolbpf, a userspace library for quickly build and develop eBPF applications.
LightWeight CoolBPF documentation
LightWeight CoolBPF 是基于 eBPF 的脚本化编程工具,其搭配轻量级 eBPF 编译器,提供丰富的 API,使得开发者 能够快速开发 eBPF 程序。
LightWeight CoolBPF (LWCB)
LightWeight CoolBPF introduction
lwcb(LightWeight CoolBPF) 是一款使用 eBPF(Berkeley Packet Filter) 的脚本化语言, 可以用于编写和分析系统性能的工具。lwcb可以帮助用户收集有关系统的活动的信息,如进程运行时间、 调用堆栈、网络流量等。它也可以用于监控和调试应用程序。
LightWeight CoolBPF tutorial
一个 lwcb 程序主要有两部分构成,我们将结合下面的 lwcb 代码片段来进行说明:
探测类型 & 探测点:
kprobe:tcp_drop
其中kprobe
指明了探测类型,tcp_drop
指明了探测点;程序体:lwcb 语句语法与
C
类似,但有一些不同之处。比如,它无需定义变量类型,变量类型由 lwcb 进行推导。
注意: tcphdr、bswap、iphdr、ntop、timestr、ns、tcpflags、kstack
等是 lwcb 提供的简易 API,便于用户直接
在脚本里进行简单的数据处理,更多的 API 请见 reference
对于下面的 lwcb 程序,我们可以通过 ./lwcb tcpdrop.cb
来运行它。
kprobe:tcp_drop {
th = tcphdr(skb);
sport = bswap(th->source);
dport = bswap(th->dest);
ih = iphdr(skb);
sip = ntop(bswap(ih->saddr));
dip = ntop(bswap(ih->daddr));
state = tcpstate(sk->__sk_common.skc_state);
print("%s ip: %s:%d -> %s:%d state: %s flags:%s %s\n", timestr(ns()), sip, sport, dip, dport, state, tcpflags(((u8 *)th)[13]), kstack());
}
LightWeight CoolBPF building guide
1. 编译准备工作
安装 rust 编译工具链:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
克隆 coolbpf 代码:
git clone https://gitee.com/anolis/coolbpf.git
进入到 lwcb 目录:
cd coolbpf/lwcb
2. 编译
cargo build --release
即可完成编译,生成的 lwcb 可执行程序在:target/release/lwcb
。
LightWeight CoolBPF reference
lwcb 参考手册
1. 使用说明
单行命令
lwcb -t
可以直接运行单条命令形式的 eBPF 程序,如:
lwcb -t 'kprobe:tcp_rcv_established {print("%s :triggerred by tcp_rcv_established\n", timestr(ns()));}'
lwcb 脚本
lwcb <脚本路径>
可以运行 lwcb 脚本
2. 语法说明
lwcb 的语法和 c 语言非常类似,
{ } : 是一个代码块
// :是注释
“string” :是字符串
-> 或 .:取结构体成员
`` if {} else {} ``:if 语句
return
:返回语句[]
:数组索引或者是 eBPF map 查找
3. 探测类型
目前支持的探测类型有:
k(ret)probe: BPF_PROG_TYPE_KPROBE
后续需要支持的探测类型有:
tracepoint: BPF_PROG_TYPE_TRACEPOINT
raw tracepoint:BPF_PROG_TYPE_RAW_TRACEPOINT
syscall: BPF_PROG_TYPE_SYSCALL
perf event:BPF_PROG_TYPE_PERF_EVENT
4. MAP 类型
目前支持的 eBPF map 类型有:
BPF_MAP_TYPE_PERF_EVENT_ARRAY
BPF_MAP_TYPE_HASH
后续需要支持的 eBPF map 类型有:
BPF_MAP_TYPE_ARRAY
BPF_MAP_TYPE_PERCPU_HASH
BPF_MAP_TYPE_PERCPU_ARRAY
BPF_MAP_TYPE_RINGBUF: 如果内核版本支持 ringbuffer 的话,我们应该用 ringbuffer 替代 perf buffer
5. 内置函数
print
语法: print(fmt, args)
iphdr
语法: iphdr(skb)
tcphdr
语法: tcphdr(skb)
ntop
语法: ntop(i32 addr)
bswap
语法: bswap(u8 | i8 | u16 | i16 | u32 | i32 | u64 | i64)
kstack
语法: kstack(i32 depth) | kstack()
ns
语法: ns()
pid
语法: pid()
tcpstate
语法: tcpstate(i32 tcpstate)
tcpflags
语法: tcpstate(i32 tcpflags)
timestr
语法: timestr(u64 ts)
ksym
语法: ksym(u64 kernel_address)
reg
语法: reg(string)
6. 内置常量
linux 内核包含了大量的宏常量,比如 #define IPPROTO_TCP 6
。 为此,lwcb 也提供了这些宏常量,使得
用户在写 lwcb 脚本代码时,能够用到内核常用的宏常量。目前已经支持的宏常量如下:
IPPROTO_IP
IPPROTO_TCP
IPPROTO_ICMP
IPPROTO_UDP
也欢迎大家贡献更多的宏常量,相关代码请参考:lwcb/src/cmacro.rs
LightWeight CoolBPF todo features
虽然 lwcb 已经能够初步运行,但是仍存在一些不足之处,需要通过增加新的特性来完善它:
- 支持 tracepoint 探测类型,其主要工作主要有:
解析
/sys/kernel/debug/tracing/events/<category>/<name>/format
数据格式提供参数入参解析
实现
TracepointProgram
,完成load、attach
等操作
支持
array map
类型,具体实现可以参考hash map
类型的实现:lwcb/src/bpf/map/hash.rs
支持
uprobe
探测类型支持
begin、end
探测类型完善编译错误信息
支持
tuple
支持
for
循环及循环展开支持
btf id
, 由于btf id
是高内核版本才支持的,所以需要动态检测判断是否开启btf id
LightWeight CoolBPF (LWCB) for Python
pylwcb introduction
- pylwcb 是 lwcb 的 python 模块。通过 pylwcb 我们可以使用 lwcb 提供的 tracing 能力,同时可以利用
python 强大的数据处理能力。
pylwcb tutorial
pylwcb 是 lwcb 的 python 模块。我们可以利用它来进行开发 eBPF 程序,然后使用 python 进行复杂的 数据处理。
1. hello world
通过 import pylwcb
导入 pylwcb 模块。 我们提供了一个简单的 say_hello 方法,该方法会打印
出 hello from pylwcb modules
字样。
import pylwcb
print(pylwcb.say_hello())
2. 一个简单的 pylwcb 程序
下面是一个结合了 lwcb 脚本代码的 pylwcb 程序。
import pylwcb
lwcb_program = """
kprobe:tcp_rcv_established {
th = tcphdr(skb);
ih = iphdr(skb);
print(ntop(bswap(ih->saddr)), ntop(bswap(ih->daddr)), bswap(th->source), bswap(th->dest));
}
"""
lwcb = pylwcb.Pylwcb(lwcb_program)
lwcb.attach()
events = lwcb.read_events()
for event in events:
print(event)
lwcb_program
存放了 lwcb 脚本代码,其主要功能是探测内核的 tcp_rcv_established 函数,打印 tcp 接收到报文的四元组,即源地址、目的地址、源端口和目的端口。
lwcb = pylwcb.Pylwcb(lwcb_program)
创建了 Pylwcb 实例lwcb.attach()
编译并加载 eBPF 程序lwcb.read_events()
读取 eBPF 程序的输出
pylwcb developing guide
如果你想要开发 pylwcb 的更多功能,可以参考如下步骤去搭建开发环境、编译 pylwcb 和运行 pylwcb。
1. 开发环境搭建
首先,我们需要搭建 pylwcb 的开发环境,主要有以下几个步骤:
创建独立的 python 开发虚拟环境:
python -m venv .env
激活该开发虚拟环境:
source .env/bin/activate
- 安装 pylwcb 开发环境依赖的 python 库
pip install tomli
pip install setuptools_rust
pip install maturin
至此,我们已经搭建好了 pylwcb 的开发环境。
2. 编译 pylwcb
我们可以通过命令:maturin develop
来编译 pylwcb,进而生产相应的 python 模块。一般生成的
python 模块所在目录是:.env/lib64/python3.6/site-packages/
注意:一般建议使用 pylwcb 提供的 devbuild.sh 脚本来编译。
3. 使用 pylwcb
在第 2 步,我们生成了 pylwcb 的 python 模块,下面将介绍如何使用生成的 python 模块。
$ ./devbuild.sh
$ python
>>> import pylwcb
>>> pylwcb.say_hello()
'hello from pylwcb modules'
4. 调试 pylwcb
在开发过程中,可能会遇到各种各样的 BUG,特别是 python 截取了 rust 程序的输出,导致无法在终端 查看 rust 产生的各种日志。
如果遇到程序 crash,我们可以通过如下命令查看 crash 时的堆栈:
执行你的 python 脚本:
rust-gdb --args python test.py
按下 r 键盘,让程序跑起来:
r
输入
bt
即可显示 crash 时的堆栈