Skip to content

Repository files navigation

Anettrace

Anettrace 是面向 Linux 与已 root Android 设备的 eBPF 网络诊断工具。它从内核中的 sk_buff、socket、网络函数和 tracepoint 采集事件,把单个报文的协议栈路径、丢包原因、 处理延迟以及线程流量整理为可直接阅读的终端输出。

master 是推荐分支,构建产物名为 anettrace。当前版本同时保留 KPROBE/KRETPROBE 兼容后端与 BPF TRACING 后端,并提供 Android arm64 静态打包流程。

主要功能

  • 报文生命周期追踪:展示报文进入、经过和离开内核协议栈的函数路径,支持 IPv4、 IPv6、TCP、UDP、ICMP、ARP 等协议。
  • 组合过滤:可按源/目标地址、端口、协议、网络命名空间、TID 和 UID 缩小范围; --uid 0 可正确过滤 root 流量。
  • 故障诊断与丢包定位--diag 将事件与 src/trace.yaml 中的规则匹配, --drop 监控释放点并在内核支持时输出 skb drop reason。
  • 性能分析:支持协议栈延迟、延迟分布、TCP RTT、socket 生命周期与轻量监控模式。
  • Android 诊断字段:可输出 TID、TGID、UID、CPU、网卡、IPv4 ID、skb mark、 本地时间或原始单调时间戳。
  • 线程流量视图--traffic 按 PID/TID、协议和本地/远端端点累计 TCP/UDP 应用层收发字节。
  • Perfetto 联合时间线:记录 socket 创建/状态、TCP 发包路径的逐点时间戳和结束点, 与 Perfetto 的线程调度状态合并;不保存报文 payload。

常用示例:

# 跟踪 ICMP 报文的内核路径
sudo ./src/anettrace --proto icmp --detail
# 诊断指定地址的异常报文
sudo ./src/anettrace --diag --addr 192.0.2.10
# 监控丢包并显示内核栈
sudo ./src/anettrace --drop --drop-stack
# 每 2 秒输出指定 UID 的 TCP 线程流量
sudo ./src/anettrace --traffic --proto tcp --uid 1000 --interval 2
# 查看当前内核实际可用的追踪目标
sudo ./src/anettrace -t "?"# 仅导出指定 UID 的 socket/发包元数据,供 Perfetto 转换
sudo ./src/anettrace --uid 10000 \
--perfetto-events /data/local/tmp/anettrace-events.jsonl

完整参数以 ./src/anettrace --help 为准。

原理与架构

命令行参数与过滤条件
|
v
trace.yaml --gen_trace.py--> 跟踪点、分组和诊断规则
|
v
用户态控制层(trace / analysis / traffic)
|
+--> KPROBE/KRETPROBE:默认、basic、diag、drop、sock、latency、traffic
|
+--> fentry/fexit:支持 trampoline 时的 monitor
|
+--> tracepoint/tp_btf:内核事件与 drop/reset reason
|
v
eBPF 过滤、上下文关联与 BPF maps
|
v
perf event / map 快照 -> 用户态聚合、规则匹配、格式化输出

核心流程分为四层:

  1. 配置层src/anettrace.c 解析运行模式和过滤条件; src/trace.yaml 描述跟踪分组、函数、tracepoint 与诊断规则, src/gen_trace.py 在构建时生成 C 定义。
  2. 挂载层:主分支优先按模式选择后端。普通追踪通过 KPROBE/KRETPROBE 适配更多内核;--monitor 在能力满足时使用 fentry/fexit;tracepoint 继续按内核能力使用 tracepoint 或 tp_btf。
  3. 内核采集层src/progs/ 中的 eBPF 程序尽早执行地址、端口、协议、 TID/UID 等过滤,并用 maps 保存报文上下文、调用栈和流量统计。
  4. 用户态分析层src/trace.c 负责加载、挂载和轮询事件, src/analysis.c 关联报文生命周期并执行规则, src/output.csrc/traffic.c 生成最终输出。

--traffic 是独立统计通路:它在 TCP/UDP send/recv 的入口保存调用上下文, 在返回点按真实返回值累计字节,因此显示的是可归属到线程的应用层流量,不包含纯内核转发流量。

Perfetto 联合时间线

--perfetto-events FILE 启用最小数据导出,默认采集:

  • sk_alloc 的 socket 分配开始/结束;
  • sock:inet_sock_set_statetcp_close 等 TCP 生命周期事件;
  • tcp_sendmsg_locked 到 TCP/IP、qdisc/NIC 发送点,以及 consume_skb/kfree_skb 结束点;
  • 每个事件的单调时钟时间、TID/TGID/UID、CPU、网卡和协议元数据。

该模式不读取或写出包体;内核对象地址会先按本次会话加盐哈希。逻辑 packet_id 使用五元组和 TCP seq/ack/flags 关联 skb clone 前后的发送阶段,匿名 skb_id 只用于观察 buffer 生命周期。socket lifetime 在 tcp_close 或采集结束时闭合。

为避免无边界的全机追踪,必须指定 --uid--pid、地址/端口/协议过滤之一,或显式使用 --force。单独 --uid 0 仍然过宽,必须再加 --pid/包过滤,或明确使用 --force

在已 root Android 设备上一键联合采集:

tools/capture_android_perfetto.sh \
--uid 10000 \
--duration 10 \
--anettrace src/anettrace \
--out output/perfetto-demo

脚本同时用系统 Perfetto 采集 sched_switchsched_waking 和进程信息,再生成 anettrace-combined.pftrace。把该文件拖入 Perfetto UI 后, 发包时间点位于实际执行线程轨道,线程 Running/Runnable/Sleeping 状态来自系统 sched 数据。

整合方式是:设备端的 perfetto 负责产生系统级调度轨迹,Anettrace 只输出网络事件 JSONL; 脚本以同一采集窗口将二者转换、合并为一个 trace 文件。因而可在同一时间轴上从 tcp_sendmsg_locked 等网络阶段跳到对应 TID 的调度切换,判断延迟来自线程未被调度、内核网络 路径,还是网卡发送之后。它不会替代系统 Perfetto,也不会向系统 trace 写入报文 payload。

如果设备没有系统 perfetto 命令,先单独使用 --perfetto-events 生成 JSONL 后离线转换; 该结果仅包含 Anettrace 网络轨道,不能提供 Running/Runnable/Sleeping 等调度状态。 首个版本聚焦 TCP TX;UDP TX、socket cookie 归属和 Android netId/VPN/Fwmark 关联留待后续。

只做离线转换时:

uv run --with perfetto==0.57.2 python tools/anettrace_to_perfetto.py \
anettrace-events.jsonl anettrace.pftrace

运行要求

  • 需要 root 权限以及允许 BPF program load、attach 和内核文件访问的安全策略。
  • 默认 CO-RE 构建需要可读的 /sys/kernel/btf/vmlinux
  • KPROBE 模式需要内核启用 KPROBES/KPROBE_EVENTS。
  • fentry/fexit 模式需要 BPF TRACING、BPF trampoline 和相应函数的 BTF 信息。
  • 某个跟踪目标不存在或能力不足时,Anettrace 会跳过该目标或给出错误;构建成功不等于 已验证目标设备内核。

编译

1. 安装依赖

Ubuntu/Debian:

sudo apt update
sudo apt install -y \
clang gcc llvm make pkg-config python3 python3-yaml \
libbpf-dev libelf-dev libzstd-dev zlib1g-dev

建议使用较新的 clang、libbpf 和 bpftool。Android CI 的可复现环境使用 Ubuntu 22.04 arm64、libbpf 1.6.2、bpftool v7.6.0 和 Linux v6.12 的 UAPI bpf.h

2. 默认 BTF 构建

git clone https://github.com/ron159/Anettrace.git
cd Anettrace
make clean
make -j$(nproc) all
./src/anettrace --version
./tests/source-contracts.sh

如果系统 bpftool 不可用或版本不合适,可显式指定:

make BPFTOOL=/absolute/path/to/bpftool all

3. 无 BTF 内核的兼容构建

兼容构建必须使用目标运行内核对应的头文件:

make clean
make KERNEL=/path/to/target-kernel COMPAT=1 all

COMPAT=1 会启用 NO_BTFNO_GLOBAL_DATAINLINE。这类产物与构建时 指定的内核结构强相关,不应作为跨内核通用二进制发布。

4. Android arm64 静态构建

请在 arm64 Linux 环境或 arm64 容器/QEMU 中准备 libbpf 静态库和 bpftool,然后执行:

make clean
make BPFTOOL=/absolute/path/to/bpftool \
STATIC=1 TARGET_PLATFORM=android-arm64 all
make BPFTOOL=/absolute/path/to/bpftool \
STATIC=1 TARGET_PLATFORM=android-arm64 pack

默认归档为:

output/anettrace-0.4.0-android-arm64-dual.tar.bz2

CI 中的完整依赖安装、静态链接检查和校验和步骤见 .github/workflows/build-android-arm64.yml

5. 安装与打包

# 安装到系统;也会安装 man page 和 bash completion
sudo make PREFIX=/ install
# 生成 output/anettrace-<version>-<platform>-<type>.tar.bz2
make pack

Android 设备验证

adb push src/anettrace /data/local/tmp/anettrace
adb push tests/android-smoke.sh /data/local/tmp/android-smoke.sh
adb shell chmod 0755 /data/local/tmp/anettrace /data/local/tmp/android-smoke.sh
adb shell su -c '/data/local/tmp/android-smoke.sh /data/local/tmp/anettrace'

测试会检查权限、BTF、CLI 契约,并尝试执行最小 ICMP 追踪。SELinux、vendor 内核配置和 模块 BTF 都可能影响实际可用的跟踪点。

分支说明

  • master:推荐使用的双后端分支,包含 KPROBE 兼容路径、TRACING monitor 和 --traffic 线程流量统计。
  • android-tracing:以 BTF/TRACING 为基线的实验分支,面向具备 fentry/fexit 和 trampoline 的较新 Android 内核,不在进程内回退到 KPROBE。

来源与致谢

Anettrace 源于 OpenCloudOS 上游项目。 感谢原项目作者和贡献者建立 eBPF 报文追踪、诊断规则与用户态分析框架;本项目在此基础上 持续维护 Anettrace 产品标识、Android arm64 适配、静态制品和设备验证。

项目沿用 Mulan PSL v2,详见 LICENSE

About

Enhanced nettrace for Android

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages