Skip to content

Commit

Permalink
doc: update for aya and drop the libbpf-skel support
Browse files Browse the repository at this point in the history
Also update nix scripts.
  • Loading branch information
EHfive committed Nov 18, 2024
1 parent 9bcb0af commit fcb913e
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 50 deletions.
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ opt-level = "z"
strip = true

[features]
default = ["aya"]
default = ["aya", "pkg-config"]
# Enable IPv6 NAPT
ipv6 = []
# Enable Aya BPF loader, requires Rust>=1.80.0
aya = ["dep:aya", "dep:pkg-config"]
aya = ["dep:aya"]
# Enable libbpf BPF loader
libbpf = ["dep:libbpf-rs", "dep:libbpf-sys", "dep:pkg-config"]
libbpf = ["dep:libbpf-rs", "dep:libbpf-sys"]
# Enable libbpf skeleton-wrapped BPF loader, requires unpublish self_cell for now
libbpf-skel = [
"dep:libbpf-rs",
Expand Down
32 changes: 25 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,24 @@ For implementation details, see documentations under [reference](./docs/referenc
## Requirement

- Linux kernel >= 5.15 (compiled with BPF and BTF support) on target machine
- `clang` compiling BPF C code
- `cargo` and `rustfmt` for building
- Rust toolchain (`cargo` etc.)
- `clang` for compiling BPF C code
- `libbpf` headers
- (optional) `pkg-config` to locate `libbpf` headers

**aya** (default)
`"aya"` loader (default)

- `libbpf` headers
- `llvm-strip`
- `llvm-strip` for stripping compiled BPF object

**libbpf**
`"libbpf"` loader

- `rustfmt` for formatting generated code
- `clang` libs for bindgen
- `libelf` from elfutils
- `zlib`

The `"libbpf-skel"` loader is served as reference purpose and you should just use `aya` or `libbpf` instead.

It's also required the eBPF JIT implementation for target architecture in kernel has implemented support for BPF-to-BPF calls, which is not the case for MIPS and other architectures have less interests. This application is only tested to work on x86-64 or aarch64.

See also [OpenWrt guide](./docs/guide/openwrt.md) for pitfalls running this on OpenWrt.
Expand All @@ -42,6 +46,7 @@ See also [OpenWrt guide](./docs/guide/openwrt.md) for pitfalls running this on O

```shell
cargo install --git https://github.com/EHfive/einat-ebpf.git
cargo install --git https://github.com/EHfive/einat-ebpf.git
```

You can also enable IPv6 NAT66 feature with `--features ipv6` flag, however it would increase load time of eBPF programs to about 4 times.
Expand All @@ -59,7 +64,20 @@ For NixOS, you can use module [`github:EHfive/einat-ebpf#nixosModules.default`](

For OpenWrt, there are [openwrt-einat-ebpf](https://github.com/muink/openwrt-einat-ebpf) and [luci-app-einat](https://github.com/muink/luci-app-einat) by @muink.

See also [cross-compilation guide](./docs/guide/cross.md) for cross-compilation on Debian/Debian-based distros.
See also [cross-compilation guide](./docs/guide/cross-aya.md) for cross-compilation on Debian/Debian-based distros.

### Build Environment Variables

| Name | Example Value | Note |
| ---------------------- | -------------------------- | ----------------------------------------------- |
| `EINAT_BPF_CFLAGS` | `-I/usr/include/<triplet>` | Specify extra CFLAGS for BPF object compilation |
| `LIBBPF_NO_PKG_CONFIG` | `1` | Disable [pkg_config lookup] of libbpf. |

[pkg_config lookup]: (https://docs.rs/pkg-config/0.3.31/pkg_config/index.html#environment-variables)

You can combine `LIBBPF_NO_PKG_CONFIG` and `EINAT_BPF_CFLAGS` to specify include flag of libbpf headers manually.

See also [build.rs](./build.rs) for reference.

## Usage

Expand Down
33 changes: 23 additions & 10 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,29 +40,42 @@ fn einat_obj_build() {
// compile BPF C code
let mut cmd = Command::new("clang");

cmd.args(c_args());

if let Some(cflags) = option_env!("EINAT_BPF_CFLAGS") {
cmd.arg(cflags);
}

// Specify environment variable LIBBPF_NO_PKG_CONFIG=1 to disable pkg-config lookup.
// Or just disable the "pkg-config" feature.
#[cfg(feature = "pkg-config")]
match pkg_config::probe_library("libbpf") {
Ok(libbpf) => {
let includes = libbpf
.include_paths
.into_iter()
.map(|i| format!("-I{}", i.to_string_lossy()));
cmd.args(includes);
}
Err(e) => {
eprintln!("Can not locate libbpf with pkg-config: {}", e)
}
}

let target = if env::var("CARGO_CFG_TARGET_ENDIAN").unwrap() == "little" {
"bpfel"
} else {
"bpfeb"
};

let libbpf = pkg_config::probe_library("libbpf").unwrap();

let includes = libbpf
.include_paths
.into_iter()
.map(|i| format!("-I{}", i.to_string_lossy()));

cmd.args(c_args())
.arg("-target")
cmd.arg("-target")
.arg(target)
.arg("-g")
.arg("-O2")
.arg("-c")
.arg(SRC)
.arg("-o")
.arg(bpf_obj)
.args(includes)
.status()
.expect("compile BPF object failed");

Expand Down
25 changes: 19 additions & 6 deletions docs/guide/cross.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

This guide gives example for cross-compiling for aarch64, replace "aarch64" and "arm64" with respective architecture identifier tokens for cross-compiling for other architectures.

## Build Dependencies
The "aya" loader is used by default.
To enable only the "libbpf" loader, specify Cargo flags `--no-default-features --features aya,pkg-config`.

Install `libelf` and `zlib1g` as it's required by `libbpf`. Install `gcc-aarch64-linux-gnu` for cross linking. Install `clang` for bindgen and compile eBPF C code in this project.
### Build Dependencies

Install `gcc-aarch64-linux-gnu` for cross linking. Install `clang` for bindgen and compile eBPF C code in this project.

```
apt install libelf-dev zlib1g-dev gcc-aarch64-linux-gnu clang
apt install gcc-aarch64-linux-gnu clang
```

Install `rustup` to get Rust>=1.74, see https://www.rust-lang.org/tools/install. Also make sure `rustfmt` is installed as it's used by `libbpf-cargo`.
Expand All @@ -18,15 +21,20 @@ Add required target to Rust toolchain:
rustup target add aarch64-unknown-linux-gnu
```

## Target Dependencies
### Target Dependencies

For "libbpf" loader, you would also need to install `libelf` and `zlib1g` as it's required by `libbpf`.

```
dpkg --add-architecture arm64
apt update
# We only need libbpf headers
apt install libbpf-dev:arm64
# For "libbpf" loader only
apt install libelf-dev:arm64 zlib1g-dev:arm64
```

## Environment Variables
### Environment Variables

```
export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER="/usr/bin/aarch64-linux-gnu-gcc"
Expand All @@ -38,7 +46,12 @@ export CC_aarch64_unknown_linux_gnu="/usr/bin/aarch64-linux-gnu-gcc"
export CFLAGS_aarch64_unknown_linux_gnu="-I /usr/include/aarch64-linux-gnu -L /usr/lib/aarch64-linux-gnu"
```

## Build static binary
Specify `EINAT_BPF_CFLAGS` if einat build script failed to locate libbpf headers.
```
export EINAT_BPF_CFLAGS="-I /usr/include/aarch64-linux-gnu"
```

### Build static binary

```
cd einat-ebpf
Expand Down
1 change: 0 additions & 1 deletion docs/guide/openwrt.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ Additional kernel configs required, you might need to add these to kernel config
```
CONFIG_BPF_SYSCALL=y
CONFIG_BPF_JIT=y
CONFIG_NET_CLS_BPF=y
CONFIG_NET_ACT_BPF=y
```

Expand Down
9 changes: 6 additions & 3 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@
crossPackage' = import ./nix/cross-package.nix { inherit naersk; };

overlay = final: prev: {
einat = defaultPackage' {
pkgs = (import nixpkgs) { inherit (prev) system; };
};
einat = defaultPackage' prev;
};

module = {
Expand All @@ -60,6 +58,11 @@
crossPackage = { ... }@args: crossPackage' ({ inherit pkgs; } // args);
in
{
legacyPackages = (import nixpkgs) {
inherit system;
overlays = [ overlay ];
};

packages = {
default = defaultPackage;
ipv6 = defaultPackage;
Expand Down
25 changes: 9 additions & 16 deletions nix/cross-package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -44,34 +44,23 @@ let
#required by libelf
zstd
]
) ++ [
pkgs.libbpf
];
);

buildInputsSearchFlags = map (dep: "-L${lib.getLib dep}/lib") buildInputs;
in
naersk'.buildPackage {
src = ../.;
gitSubmodules = true;
depsBuildBuild = with pkgs; [
# build dependencies of cargo build depenceies libbpf-cargo -> libbpf-sys
stdenv.cc
];
nativeBuildInputs = with pkgs; [
pkg-config
# required by `libbpf_cargo::SkeletonBuilder`
rustfmt
## build dependencies of cargo build depenceies libbpf-cargo -> libbpf-sys
stdenv.cc.libc
zlib
elfutils

## build dependencies of libbpf-sys on target platform
# for cross linking libelf and zlib, and make libbpf
crossPkgs.stdenv.cc
# compile BPF C code
llvmPackages.clang-unwrapped
llvmPackages.bintools-unwrapped

## build dependencies of libbpf-sys on target platform
# for cross linking libelf and zlib, and make libbpf
crossPkgs.stdenv.cc
];
inherit buildInputs;
strictDeps = true;
Expand Down Expand Up @@ -99,6 +88,9 @@ naersk'.buildPackage {
"-mno-outline-atomics"
];

LIBBPF_NO_PKG_CONFIG = 1;
EINAT_BPF_CFLAGS = "-I${pkgs.libbpf}/include";

"CC_${targetUnderscore}" = crossCC;
"CARGO_TARGET_${targetUnderscoreUpper}_LINKER" = crossCC;

Expand All @@ -115,6 +107,7 @@ naersk'.buildPackage {

preBuild = ''
export BINDGEN_EXTRA_CLANG_ARGS_${targetUnderscore}="''${NIX_CFLAGS_COMPILE}";
# Avoid adding host dependencies to CFLAGS and LDFLAGS for build platform
if [[ ${pkgs.stdenv.cc.suffixSalt} != ${crossPkgs.stdenv.cc.suffixSalt} ]]; then
export NIX_CC_WRAPPER_TARGET_HOST_${pkgs.stdenv.cc.suffixSalt}="";
Expand Down
4 changes: 0 additions & 4 deletions nix/package.nix
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
lib,
rustPlatform,
pkg-config,
rustfmt,
llvmPackages,
libbpf,
elfutils,
Expand All @@ -15,12 +14,9 @@ naersk.buildPackage {

nativeBuildInputs = [
pkg-config
rustfmt
llvmPackages.clang-unwrapped
llvmPackages.bintools-unwrapped
rustPlatform.bindgenHook
elfutils
zlib
];

buildInputs = [
Expand Down

0 comments on commit fcb913e

Please sign in to comment.