test: Add compile_c_ebpf to library

This allows for C code to be compiled and used in tests!
It does require libbpf on the host machine though...

Also moved removal of the `user` and `ebpf` dirs created by rust-script
into `lib.sh` and parameterized bits of the XDP smoke test for ease of
copying

Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
pull/182/head
Dave Tucker 3 years ago
parent f41db116ac
commit 657fb44525

@ -11,8 +11,8 @@ set -e
NAME=pass
clean_up() {
rm -rf ebpf user ${NAME}.o ${NAME}
exec_vm rm -f pass pass.o
rm -rf ${NAME}.o ${NAME}
exec_vm rm -f ${NAME} ${NAME}.o
}
trap clean_up EXIT
@ -21,9 +21,9 @@ trap clean_up EXIT
compile_ebpf "$(pwd)/${NAME}.ebpf.rs"
compile_user "$(pwd)/${NAME}.rs"
scp_vm pass.o
scp_vm pass
scp_vm ${NAME}.o
scp_vm ${NAME}
exec_vm sudo ./pass
exec_vm sudo ./${NAME}
exit 0

@ -0,0 +1,85 @@
//! ```cargo
//! [dependencies]
//! libbpf-sys = { version = "0.6.1-1" }
//! anyhow = "1"
//! ```
use std::{
env,
fs::{self, OpenOptions},
io::Write,
path::Path,
process::Command,
string::String,
};
use anyhow::{bail, Context, Result};
static CLANG_DEFAULT: &str = "/usr/bin/clang";
/// Extract vendored libbpf headers from libbpf-sys.
fn extract_libbpf_headers<P: AsRef<Path>>(include_path: P) -> Result<()> {
let dir = include_path.as_ref().join("bpf");
fs::create_dir_all(&dir)?;
for (filename, contents) in libbpf_sys::API_HEADERS.iter() {
let path = dir.as_path().join(filename);
let mut file = OpenOptions::new().write(true).create(true).open(path)?;
file.write_all(contents.as_bytes())?;
}
Ok(())
}
/// Build eBPF programs with clang and libbpf headers.
fn build_ebpf<P: Clone + AsRef<Path>>(in_file: P, out_file: P, include_path: P) -> Result<()> {
extract_libbpf_headers(include_path.clone())?;
let clang = match env::var("CLANG") {
Ok(val) => val,
Err(_) => String::from(CLANG_DEFAULT),
};
let arch = match std::env::consts::ARCH {
"x86_64" => "x86",
"aarch64" => "arm64",
_ => std::env::consts::ARCH,
};
let mut cmd = Command::new(clang);
cmd.arg(format!("-I{}", include_path.as_ref().to_string_lossy()))
.arg("-g")
.arg("-O2")
.arg("-target")
.arg("bpf")
.arg("-c")
.arg(format!("-D__TARGET_ARCH_{}", arch))
.arg(in_file.as_ref().as_os_str())
.arg("-o")
.arg(out_file.as_ref().as_os_str());
let output = cmd.output().context("Failed to execute clang")?;
if !output.status.success() {
bail!(
"Failed to compile eBPF programs\n \
stdout=\n \
{}\n \
stderr=\n \
{}\n",
String::from_utf8(output.stdout).unwrap(),
String::from_utf8(output.stderr).unwrap()
);
}
Ok(())
}
fn main() -> Result<()> {
let args: Vec<String> = env::args().collect();
if args.len() != 3 {
bail!("requires 2 arguments. src and dst")
}
let path = env::current_dir()?;
let src = Path::new(&args[1]);
let dst = Path::new(&args[2]);
let include_path = path.join("include");
fs::create_dir_all(include_path.clone())?;
build_ebpf(src, dst, &include_path)?;
Ok(())
}

@ -54,6 +54,17 @@ EOF
cargo build -q --manifest-path "${dir}/ebpf/Cargo.toml"
mv "${dir}/ebpf/target/bpfel-unknown-none/debug/${artifact}" "${dir}/${base}.o"
rm -rf "${dir}/.cargo"
rm -rf "${dir}/ebpf"
}
# compile a C BPF file
compile_c_ebpf() {
file=$(basename "$1")
dir=$(dirname "$1")
base=$(echo "${file}" | cut -f1 -d '.')
rust-script "${RT_PROJECT_ROOT}/_lib/compile-ebpf.ers" "${1}" "${dir}/${base}.o"
rm -rf "${dir}/include"
}
# compiles the userspace program by using rust-script to create a temporary
@ -75,6 +86,7 @@ members = []
EOF
cargo build -q --release --manifest-path "${dir}/user/Cargo.toml" --target=x86_64-unknown-linux-musl
mv "${dir}/user/target/x86_64-unknown-linux-musl/release/${artifact}" "${dir}/${base}"
rm -rf "${dir}/user"
}
download_images() {

Loading…
Cancel
Save