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 已经能够初步运行,但是仍存在一些不足之处,需要通过增加新的特性来完善它:

  1. 支持 tracepoint 探测类型,其主要工作主要有:
    • 解析 /sys/kernel/debug/tracing/events/<category>/<name>/format 数据格式

    • 提供参数入参解析

    • 实现 TracepointProgram ,完成 load、attach 等操作

  2. 支持 array map 类型,具体实现可以参考 hash map 类型的实现: lwcb/src/bpf/map/hash.rs

  3. 支持 uprobe 探测类型

  4. 支持 begin、end 探测类型

  5. 完善编译错误信息

  6. 支持 tuple

  7. 支持 for 循环及循环展开

  8. 支持 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 的开发环境,主要有以下几个步骤:

  1. 创建独立的 python 开发虚拟环境: python -m venv .env

  2. 激活该开发虚拟环境: source .env/bin/activate

  3. 安装 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 时的堆栈

参考:pyo3 debugging guide

Indices and tables