From 9aa08b4271ace278055059382f92b076562a1935 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 4 Feb 2025 15:19:00 -0500 Subject: [PATCH] codegen: tidy up Move some code out of a loop, where it appears to be nonsense. --- aya-obj/include/linux_wrapper.h | 2 +- ebpf/aya-ebpf-bindings/include/bindings.h | 7 +- xtask/src/codegen/aya.rs | 306 +++++++++++----------- xtask/src/codegen/aya_ebpf_bindings.rs | 48 ++-- xtask/src/codegen/mod.rs | 25 +- 5 files changed, 200 insertions(+), 188 deletions(-) diff --git a/aya-obj/include/linux_wrapper.h b/aya-obj/include/linux_wrapper.h index 0e15d93f3..8876660a9 100644 --- a/aya-obj/include/linux_wrapper.h +++ b/aya-obj/include/linux_wrapper.h @@ -1,4 +1,3 @@ -#include #include #include #include @@ -7,6 +6,7 @@ #include #include #include +#include /* workaround the fact that bindgen can't parse the IOC macros */ int AYA_PERF_EVENT_IOC_ENABLE = PERF_EVENT_IOC_ENABLE; diff --git a/ebpf/aya-ebpf-bindings/include/bindings.h b/ebpf/aya-ebpf-bindings/include/bindings.h index 05344214b..aa831c577 100644 --- a/ebpf/aya-ebpf-bindings/include/bindings.h +++ b/ebpf/aya-ebpf-bindings/include/bindings.h @@ -1,9 +1,10 @@ #include -// __wsum is missing from types.h, see -// https://elixir.bootlin.com/linux/v5.13/source/include/uapi/linux/types.h +// __wsum is missing from types.h, compare: +// https://github.com/torvalds/linux/blob/v5.13/include/uapi/linux/types.h +// https://github.com/libbpf/libbpf/blob/v1.5.0/include/linux/types.h typedef __u32 __bitwise __wsum; -#include "bpf_helpers.h" +#include #include // needed for TC_ACT_* #include diff --git a/xtask/src/codegen/aya.rs b/xtask/src/codegen/aya.rs index 118e9d539..14767a6a1 100644 --- a/xtask/src/codegen/aya.rs +++ b/xtask/src/codegen/aya.rs @@ -1,16 +1,16 @@ use std::path::{Path, PathBuf}; -use anyhow::anyhow; +use anyhow::{Context as _, Result}; use aya_tool::{bindgen, write_to_file}; use crate::codegen::{Architecture, SysrootOptions}; -pub fn codegen(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyhow::Error> { +pub fn codegen(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<()> { codegen_internal_btf_bindings(libbpf_dir)?; codegen_bindings(opts, libbpf_dir) } -fn codegen_internal_btf_bindings(libbpf_dir: &Path) -> Result<(), anyhow::Error> { +fn codegen_internal_btf_bindings(libbpf_dir: &Path) -> Result<()> { let dir = PathBuf::from("aya-obj"); let generated = dir.join("src/generated"); @@ -26,10 +26,7 @@ fn codegen_internal_btf_bindings(libbpf_dir: &Path) -> Result<(), anyhow::Error> bindgen = bindgen.allowlist_type(x); } - let bindings = bindgen - .generate() - .map_err(|op| anyhow!("bindgen failed - {op}"))? - .to_string(); + let bindings = bindgen.generate().context("bindgen failed")?.to_string(); // write the bindings, with the original helpers removed write_to_file(generated.join("btf_internal_bindings.rs"), &bindings)?; @@ -37,7 +34,7 @@ fn codegen_internal_btf_bindings(libbpf_dir: &Path) -> Result<(), anyhow::Error> Ok(()) } -fn codegen_bindings(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyhow::Error> { +fn codegen_bindings(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<()> { let SysrootOptions { x86_64_sysroot, aarch64_sysroot, @@ -47,132 +44,154 @@ fn codegen_bindings(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyh s390x_sysroot, mips_sysroot, } = opts; - let types = [ - // BPF - "BPF_TYPES", - "bpf_cmd", - "bpf_insn", - "bpf_attr", - "bpf_map_type", - "bpf_prog_type", - "bpf_attach_type", - "bpf_prog_info", - "bpf_map_info", - "bpf_link_info", - "bpf_link_type", - "bpf_btf_info", - "bpf_func_id", - "bpf_func_info", - "bpf_line_info", - "bpf_lpm_trie_key", - "bpf_cpumap_val", - "bpf_devmap_val", - "bpf_stats_type", - "bpf_perf_event_type", - "bpf_task_fd_type", - // BTF - "btf_header", - "btf_ext_info", - "btf_ext_info_sec", - "btf_type", - "btf_enum", - "btf_array", - "btf_member", - "btf_param", - "btf_var", - "btf_var_secinfo", - "btf_func_linkage", - "btf_decl_tag", - // PERF - "perf_event_attr", - "perf_sw_ids", - "perf_hw_id", - "perf_hw_cache_id", - "perf_hw_cache_op_id", - "perf_hw_cache_op_result_id", - "perf_event_sample_format", - "perf_event_mmap_page", - "perf_event_header", - "perf_type_id", - "perf_event_type", - // NETLINK - "ifinfomsg", - "tcmsg", - "nlmsgerr_attrs", - // ITER - "bpf_cgroup_iter_order", - // NETFILTER - "nf_inet_hooks", - ]; - - let vars = [ - // BPF - "BPF_PSEUDO_.*", - "BPF_ALU", - "BPF_ALU64", - "BPF_LDX", - "BPF_ST", - "BPF_STX", - "BPF_LD", - "BPF_K", - "BPF_X", - "BPF_DW", - "BPF_W", - "BPF_H", - "BPF_B", - "BPF_IMM", - "BPF_MEM", - "BPF_SUB", - "BPF_MOV", - "BPF_F_.*", - "BPF_JMP", - "BPF_CALL", - "BPF_EXIT", - "SO_ATTACH_BPF", - "SO_DETACH_BPF", - // BTF - "BTF_INT_.*", - "BTF_KIND_.*", - "BTF_VAR_.*", - // PERF - "PERF_FLAG_.*", - "PERF_EVENT_.*", - "PERF_MAX_.*", - // see linux_wrapper.h, these are to workaround the IOC macros - "AYA_PERF_EVENT_.*", - // NETLINK - "NLMSG_ALIGNTO", - "IFLA_XDP_FD", - "TCA_KIND", - "TCA_OPTIONS", - "TCA_BPF_FD", - "TCA_BPF_NAME", - "TCA_BPF_FLAGS", - "TCA_BPF_FLAG_ACT_DIRECT", - "XDP_FLAGS_.*", - "TC_H_MAJ_MASK", - "TC_H_MIN_MASK", - "TC_H_UNSPEC", - "TC_H_ROOT", - "TC_H_INGRESS", - "TC_H_CLSACT", - "TC_H_MIN_PRIORITY", - "TC_H_MIN_INGRESS", - "TC_H_MIN_EGRESS", - // Ringbuf - "BPF_RINGBUF_.*", - // NETFILTER - "NFPROTO_.*", - ]; - let dir = PathBuf::from("aya-obj"); let generated = dir.join("src/generated"); let builder = || { - bindgen::user_builder() + let mut bindgen = bindgen::user_builder() .header(dir.join("include/linux_wrapper.h").to_str().unwrap()) .clang_args(["-I", libbpf_dir.join("include/uapi").to_str().unwrap()]) .clang_args(["-I", libbpf_dir.join("include").to_str().unwrap()]) + // BPF_F_LINK is defined twice. Once in an anonymous enum + // which bindgen will constify, and once via #define macro + // which generates a duplicate const. + .blocklist_var("BPF_F_LINK") + .constified_enum("BPF_F_.*") + .constified_enum("BTF_KIND_.*") + .constified_enum("BTF_VAR_.*") + .constified_enum("IFLA_.*") + .constified_enum("TCA_.*") + .constified_enum("BPF_RINGBUF_.*") + // NETFILTER + .constified_enum("NFPROTO_.*"); + + let types = [ + // BPF + "bpf_cmd", + "bpf_insn", + "bpf_attr", + "bpf_map_type", + "bpf_prog_type", + "bpf_attach_type", + "bpf_prog_info", + "bpf_map_info", + "bpf_link_info", + "bpf_link_type", + "bpf_btf_info", + "bpf_func_id", + "bpf_func_info", + "bpf_line_info", + "bpf_lpm_trie_key", + "bpf_cpumap_val", + "bpf_devmap_val", + "bpf_stats_type", + "bpf_perf_event_type", + "bpf_task_fd_type", + // BTF + "btf_header", + "btf_ext_info", + "btf_ext_info_sec", + "btf_type", + "btf_enum", + "btf_array", + "btf_member", + "btf_param", + "btf_var", + "btf_var_secinfo", + "btf_func_linkage", + "btf_decl_tag", + // PERF + "perf_event_attr", + "perf_sw_ids", + "perf_hw_id", + "perf_hw_cache_id", + "perf_hw_cache_op_id", + "perf_hw_cache_op_result_id", + "perf_event_sample_format", + "perf_event_mmap_page", + "perf_event_header", + "perf_type_id", + "perf_event_type", + // NETLINK + "ifinfomsg", + "tcmsg", + "nlmsgerr_attrs", + // ITER + "bpf_cgroup_iter_order", + // NETFILTER + "nf_inet_hooks", + ]; + + let vars = [ + // BPF + "BPF_FUNC_.*", + "BPF_PSEUDO_.*", + "BPF_ALU", + "BPF_ALU64", + "BPF_LDX", + "BPF_ST", + "BPF_STX", + "BPF_LD", + "BPF_K", + "BPF_X", + "BPF_DW", + "BPF_W", + "BPF_H", + "BPF_B", + "BPF_IMM", + "BPF_MEM", + "BPF_SUB", + "BPF_MOV", + "BPF_F_.*", + "BPF_JMP", + "BPF_CALL", + "BPF_EXIT", + "SO_ATTACH_BPF", + "SO_DETACH_BPF", + // BTF + "BTF_INT_.*", + "BTF_KIND_.*", + "BTF_VAR_.*", + // PERF + "PERF_FLAG_.*", + "PERF_EVENT_.*", + "PERF_MAX_.*", + // see linux_wrapper.h, these are to workaround the IOC macros + "AYA_PERF_EVENT_.*", + // NETLINK + "NLMSG_ALIGNTO", + "IFLA_XDP_FD", + "TCA_KIND", + "TCA_OPTIONS", + "TCA_BPF_FD", + "TCA_BPF_NAME", + "TCA_BPF_FLAGS", + "TCA_BPF_FLAG_ACT_DIRECT", + "XDP_FLAGS_.*", + "TC_H_MAJ_MASK", + "TC_H_MIN_MASK", + "TC_H_UNSPEC", + "TC_H_ROOT", + "TC_H_INGRESS", + "TC_H_CLSACT", + "TC_H_MIN_PRIORITY", + "TC_H_MIN_INGRESS", + "TC_H_MIN_EGRESS", + // Ringbuf + "BPF_RINGBUF_.*", + // NETFILTER + "NFPROTO_.*", + ]; + + for x in &types { + bindgen = bindgen.allowlist_type(x); + } + + for x in &vars { + bindgen = bindgen.allowlist_var(x); + } + + bindgen }; for arch in Architecture::supported() { @@ -204,38 +223,7 @@ fn codegen_bindings(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyh }; bindgen = bindgen.clang_args(["-I", sysroot.to_str().unwrap()]); - for x in &types { - bindgen = bindgen.allowlist_type(x); - } - for x in &vars { - bindgen = bindgen - .allowlist_var(x) - // BPF_F_LINK is defined twice. Once in an anonymous enum - // which bindgen will constify, and once via #define macro - // which generates a duplicate const. - .blocklist_var("BPF_F_LINK") - .constified_enum("BPF_F_.*") - .constified_enum("BTF_KIND_.*") - .constified_enum("BTF_VAR_.*") - .constified_enum("IFLA_.*") - .constified_enum("TCA_.*") - .constified_enum("BPF_RINGBUF_.*") - // NETFILTER - .constified_enum("NFPROTO_.*"); - } - - for x in &types { - bindgen = bindgen.allowlist_type(x); - } - - for x in &vars { - bindgen = bindgen.allowlist_var(x); - } - - let bindings = bindgen - .generate() - .map_err(|op| anyhow!("bindgen failed - {op}"))? - .to_string(); + let bindings = bindgen.generate().context("bindgen failed")?.to_string(); // write the bindings, with the original helpers removed write_to_file( diff --git a/xtask/src/codegen/aya_ebpf_bindings.rs b/xtask/src/codegen/aya_ebpf_bindings.rs index de62c0a45..e422a7929 100644 --- a/xtask/src/codegen/aya_ebpf_bindings.rs +++ b/xtask/src/codegen/aya_ebpf_bindings.rs @@ -1,20 +1,25 @@ use std::{ + ffi::OsString, fs::create_dir_all, path::{Path, PathBuf}, + process::Command, }; -use anyhow::anyhow; +use anyhow::{Context as _, Result}; use aya_tool::{bindgen, write_to_file_fmt}; use proc_macro2::TokenStream; use quote::ToTokens; use syn::{parse_str, Item}; -use crate::codegen::{ - helpers::{expand_helpers, extract_helpers}, - Architecture, SysrootOptions, +use crate::{ + codegen::{ + helpers::{expand_helpers, extract_helpers}, + Architecture, SysrootOptions, + }, + exec, }; -pub fn codegen(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyhow::Error> { +pub fn codegen(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<()> { let SysrootOptions { x86_64_sysroot, aarch64_sysroot, @@ -25,17 +30,35 @@ pub fn codegen(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyhow::E mips_sysroot, } = opts; + let tmp_dir = tempfile::tempdir().context("tempdir failed")?; + let libbpf_headers_dir = tmp_dir.path().join("libbpf_headers"); + + let mut includedir = OsString::new(); + includedir.push("INCLUDEDIR="); + includedir.push(&libbpf_headers_dir); + + exec( + Command::new("make") + .arg("-C") + .arg(libbpf_dir.join("src")) + .arg(includedir) + .arg("install_headers"), + )?; + let dir = PathBuf::from("ebpf/aya-ebpf-bindings"); let builder = || { let mut bindgen = bindgen::bpf_builder() .header(dir.join("include/bindings.h").to_str().unwrap()) + .clang_args(["-I", libbpf_dir.join("include/uapi").to_str().unwrap()]) + .clang_args(["-I", libbpf_dir.join("include").to_str().unwrap()]) + .clang_args(["-I", libbpf_headers_dir.to_str().unwrap()]) // aya-tool uses aya_ebpf::cty. We can't use that here since aya-bpf // depends on aya-ebpf-bindings so it would create a circular dep. .ctypes_prefix("::aya_ebpf_cty") - .clang_args(["-I", libbpf_dir.join("include/uapi").to_str().unwrap()]) - .clang_args(["-I", libbpf_dir.join("include").to_str().unwrap()]) - .clang_args(["-I", libbpf_dir.join("src").to_str().unwrap()]) + // we define our own version which is compatible with both libbpf + // and iproute2. + .blocklist_type("bpf_map_def") // BPF_F_LINK is defined twice. Once in an anonymous enum // which bindgen will constify, and once via #define macro // which generates a duplicate const. @@ -70,10 +93,6 @@ pub fn codegen(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyhow::E bindgen = bindgen.allowlist_type(x); } - // we define our own version which is compatible with both libbpf and - // iproute2 - bindgen = bindgen.blocklist_type("bpf_map_def"); - for x in &vars { bindgen = bindgen.allowlist_var(x); } @@ -110,10 +129,7 @@ pub fn codegen(opts: &SysrootOptions, libbpf_dir: &Path) -> Result<(), anyhow::E }; bindgen = bindgen.clang_args(["-I", sysroot.to_str().unwrap()]); - let bindings = bindgen - .generate() - .map_err(|op| anyhow!("bindgen failed - {op}"))? - .to_string(); + let bindings = bindgen.generate().context("bindgen failed")?.to_string(); let mut tree = parse_str::(&bindings).unwrap(); diff --git a/xtask/src/codegen/mod.rs b/xtask/src/codegen/mod.rs index 7dae08709..657447e5b 100644 --- a/xtask/src/codegen/mod.rs +++ b/xtask/src/codegen/mod.rs @@ -2,8 +2,11 @@ mod aya; mod aya_ebpf_bindings; mod helpers; -use std::path::{Path, PathBuf}; +use std::{ + path::{Path, PathBuf}, +}; +use anyhow::{Context as _, Result}; use clap::Parser; const SUPPORTED_ARCHS: &[Architecture] = &[ @@ -92,34 +95,38 @@ pub struct SysrootOptions { #[derive(Parser)] pub struct Options { - #[command(flatten)] + #[clap(flatten)] sysroot_options: SysrootOptions, - #[command(subcommand)] - command: Option, + #[clap(subcommand)] + command: Option, } #[derive(clap::Subcommand)] -enum Command { +enum Target { #[command(name = "aya")] Aya, #[command(name = "aya-ebpf-bindings")] AyaEbpfBindings, } -pub fn codegen(opts: Options, libbpf_dir: &Path) -> Result<(), anyhow::Error> { +pub fn codegen(opts: Options, libbpf_dir: &Path) -> Result<()> { let Options { sysroot_options, command, } = opts; + match command { Some(command) => match command { - Command::Aya => aya::codegen(&sysroot_options, libbpf_dir), - Command::AyaEbpfBindings => aya_ebpf_bindings::codegen(&sysroot_options, libbpf_dir), + Target::Aya => aya::codegen(&sysroot_options, libbpf_dir).context("aya"), + Target::AyaEbpfBindings => aya_ebpf_bindings::codegen(&sysroot_options, libbpf_dir) + .context("aya_ebpf_bindings"), }, None => { - aya::codegen(&sysroot_options, libbpf_dir)?; + aya::codegen(&sysroot_options, libbpf_dir).context("aya")?; aya_ebpf_bindings::codegen(&sysroot_options, libbpf_dir) + .context("aya_ebpf_bindings")?; + Ok(()) } } }