RustAya 编写 eBPF 程序( 二 )


2.3 安装 bpf-linker 依赖 和 bpftool 工具为了使用 Aya , 我们还需要安装依赖包bpf-linker,但其依赖与LLVM/Clang 等工具,因此我们也需要提前安装:
$ sudo apt-get update$ sudo apt-get install llvm clang -y$ cargo install bpf-linker最后,为了生成内核数据结构的绑定,我们还必须安装 bpftool,可以从发行版中安装或从源代码中构建,这里我选用发行版安装方式(基于 Ubuntu 22.04),源码安装可参考 bpftool 仓库说明文档:
$ sudo apt install linux-tools-common linux-tools-5.15.0-52-generic linux-cloud-tools-5.15.0-52-generic -y支持我们完成了基于 Aya 开发的整个环境及依赖的安装 。
3. Aya 向导创建 eBPF 程序3.1 使用向导创建项目Aya 提供了一套模版向导用于创建 eBPF 对应的程序类型,向导创建依赖于 cargo-generate,因此我们需要在运行程序向导前提前安装:
$ cargo install cargo-generate

我在安装 cargo-generate 过程中遇到了如下的错误,主要是由于依赖 openssl 库问题导致 , 如果你也遇到类似问题可参考 cargo-generate 安装指南 和 Rust OpenSSL 文档 , 如果一切顺利,则可忽略此处的提示 。
...warning: build failed, waiting for other jobs to finish...error: failed to compile `cargo-generate v0.16.0`, intermediate artifacts can be found at `/tmp/cargo-install8NrREg...$ sudo apt install openssl pkg-config libssl-dev gcc m4 ca-certificates make perl -y# 重新安装即可
在完成依赖后,我们就可以使用向导来创建 eBPF 项目,这里以 XDP 类型程序为例:
$ cargo generate https://github.com/aya-rs/aya-template
RustAya 编写 eBPF 程序

文章插图
这里我们输入项目名称 myapp,eBPF 程序类型选择 xdp , 完成相关设定后,向导会自动帮我们创建一个名为 myapp 的 Rust 项目,项目包括了一个最简单的 XDP 类型的 eBPF 程序及相对应的用户空间程序 。myapp 目录的整体夹头如下所示:
├── Cargo.lock├── Cargo.toml├── README.md├── myapp# 用户空间程序│   ├── Cargo.toml│   └── src│  └── main.rs├── myapp-common# eBPF 程序与用户空间程序复用的代码库│   ├── Cargo.toml│   └── src│  └── lib.rs├── myapp-ebpf# eBPF 程序│   ├── Cargo.lock│   ├── Cargo.toml│   ├── rust-toolchain.toml│   └── src│  └── main.rs└── xtask# build 相关的代码├── Cargo.toml└── src├── build_ebpf.rs├── main.rs└── run.rs8 directories, 15 files生成的 eBPF 程序位于 myapp-ebpf/src 目录下,文件名为 main.rs,完整内容如下所示:
$ cat myapp-ebpf/src/main.rs#![no_std]#![no_main]use aya_bpf::{bindings::xdp_action,macros::xdp,programs::XdpContext,};use aya_log_ebpf::info;#[xdp(name="myapp")]pub fn myapp(ctx: XdpContext) -> u32 {match try_myapp(ctx) {Ok(ret) => ret,Err(_) => xdp_action::XDP_ABORTED,}}fn try_myapp(ctx: XdpContext) -> Result<u32, u32> {info!(&ctx, "received a packet"); // 每接受到一个数据包则打印一个日志Ok(xdp_action::XDP_PASS)}#[panic_handler]fn panic(_info: &core::panic::PanicInfo) -> ! {unsafe { core::hint::unreachable_unchecked() }}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

推荐阅读