RustAya 编写 eBPF 程序( 三 )

3.2 编译 eBPF 程序首先,我们使用 cargo 工具编译 eBPF 对应的程序:
$ cd myapp$ cargo xtask build-ebpf...Compiling myapp-ebpf v0.1.0 (/home/ubuntu/myapp/myapp-ebpf)Running `rustc --crate-name myapp --edition=2021 src/main.rs --error-format=json \--json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type bin \--emit=dep-info,link -C opt-level=3 -C panic=abort -C lto -C codegen-units=1-C metadata=https://www.huyubaike.com/biancheng/dd6140d48c387b43 -C extra-filename=-dd6140d48c387b43 /--out-dir /...-Z unstable-options /Finished dev [optimized] target(s) in 11.76s编译完成后,对应的程序保存在 target 目录下:
~/myapp$ ls -hl target/bpfel-unknown-none/debug/...-rw-rw-r-- 2 ubuntu ubuntu 3.5K Nov6 22:24 myapp~/myapp$ file target/bpfel-unknown-none/debug/myapptarget/bpfel-unknown-none/debug/myapp: ELF 64-bit LSB relocatable, eBPF, version 1 (SYSV), not stripped/myapp$ llvm-objdump -S target/bpfel-unknown-none/debug/myapptarget/bpfel-unknown-none/debug/myapp: file format elf64-bpfDisassembly of section xdp/myapp:0000000000000000 <myapp>:...242: bf 61 00 00 00 00 00 00 r1 = r6243: 18 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r2 = 0 ll245: 18 03 00 00 ff ff ff ff 00 00 00 00 00 00 00 00 r3 = 4294967295 ll247: bf 04 00 00 00 00 00 00 r4 = r0248: b7 05 00 00 aa 00 00 00 r5 = 170249: 85 00 00 00 19 00 00 00 call 25至此,已经完成了 eBPF 程序的编译工作,接着我们需要继续编译用户空间代码 。
3.3 运行用户空间程序我们可以直接使用 cargo 命令来运行用户空间程序:
$ RUST_LOG=info cargo xtask run...Finished dev [unoptimized + debuginfo] target(s) in 8.38sError: failed to attach the XDP program with default flags - try changing XdpFlags::default() to XdpFlags::SKB_MODECaused by:unknown network interface eth0

RUST_LOG=info 为设置日志级别的环境变量,默认为 warn,但向导生成的代码打印的日志级别默认为 info,因此需要运行时制定,否则可能会出现程序运行查看不到日志的情况 。
cargo xtask run 命令会直接编译用户空间代码并运行,但是运行过程中我们发现出现错误 unknown network interface eth0,这是因为默认生成的程序指定将 XDP 程序加载到 eth0 网卡,而我们的 VM 默认网卡不为 eth0 导致,这里我们明确制定网卡使用 lo 测试,再次运行结果如下:
$ RUST_LOG=info cargo xtask run -- --iface lo...Finished dev [optimized] target(s) in 0.19sFinished dev [unoptimized + debuginfo] target(s) in 0.12s[2022-11-05T16:25:27Z INFOmyapp] Waiting for Ctrl-C...这次可以发现用户空间程序已经正常运行,并且将对应的 eBPF 程序加载至内核中 。
$ sudo bpftool prog list42: xdpname myapptag 2929f83b3be0f64bgpl loaded_at 2022-11-06T22:42:54+0800uid 0 xlated 2016Bjited 1151Bmemlock 4096Bmap_ids 14,13,15$ ip link show1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 xdpgeneric qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00prog/xdp id 42 # <=== 加载的 eBPF 程序 id 42我们启动网卡在 lo 网卡的 ping 包验证:
RustAya 编写 eBPF 程序

文章插图
我们可以看到当我们在另外一个窗口在本地端口运行 ping -c 1 127.0.0.1 命令的同时,在运行用户空间 myapp 的程序日志中打印了对应的日志 received a packet
至此,我们就完成了整个基于 Aya 最简单 XDP 程序的验证,如果你打算进阶一步打印报文日志或者对特定包进行对齐,则可以参考 Aya Book 中对应的章节 。
4. 总结通过对于 Aya 整个过程中的使用,我们可以发现使用 Aya 开发 eBPF 程序的确给我们带来了诸多的便利,通过向导搭建了整个项目的基本框架,并且实现了编译、加载等相关的管理工作,特别是对于新手入门更加友好 。默认生成的用户空间代码与 eBPF 代码实现了一定程度的代码复用,特别是日志相关的打印更加便捷 。同时,该项目当前的文档还不是特别完整,诸如 Probe/Tracepoint/XDP 等程序类型的文档还在完善中,如果你有兴趣也欢迎投入到相关的建设中 。更多介绍可参考 Aya: Rust 风格的 eBPF 伙伴 。

经验总结扩展阅读