diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 281a0d82..491fa966 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -236,7 +236,7 @@ jobs: # linux-image-5.10.0-23-cloud-amd64-unsigned_5.10.179-3_amd64.deb \ printf '%s\0' \ linux-image-6.1.0-10-cloud-amd64-unsigned_6.1.38-2_amd64.deb \ - linux-image-6.4.0-3-cloud-amd64-unsigned_6.4.11-1_amd64.deb \ + linux-image-6.4.0-4-cloud-amd64-unsigned_6.4.13-1_amd64.deb \ | xargs -0 -t -P0 -I {} wget -nd -nv -P test/.tmp/debian-kernels/amd64 ftp://ftp.us.debian.org/debian/pool/main/l/linux/{} - name: Extract debian kernels diff --git a/Cargo.toml b/Cargo.toml index 8ad69dfc..b534f567 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,13 +57,13 @@ aya-log-common = { path = "aya-log-common", version = "0.1.13", default-features aya-log-parser = { path = "aya-log-parser", default-features = false } aya-obj = { path = "aya-obj", version = "0.1.0", default-features = false } aya-tool = { path = "aya-tool", default-features = false } -bindgen = { version = "0.66", default-features = false } +bindgen = { version = "0.68", default-features = false } bitflags = { version = "2.2.1", default-features = false } bytes = { version = "1", default-features = false } -cargo_metadata = { version = "0.17.0", default-features = false } +cargo_metadata = { version = "0.18.0", default-features = false } clap = { version = "4", default-features = false } core-error = { version = "0.0.0", default-features = false } -dialoguer = { version = "0.10", default-features = false } +dialoguer = { version = "0.11", default-features = false } diff = { version = "0.1.13", default-features = false } env_logger = { version = "0.10", default-features = false } hashbrown = { version = "0.14", default-features = false } diff --git a/README.md b/README.md index de31ec77..9b4e2b42 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,15 @@ [![Crates.io][crates-badge]][crates-url] ![License][license-badge] -![Build status][build-badge] +[![Build status][build-badge]][build-url] [![Book][book-badge]][book-url] [crates-badge]: https://img.shields.io/crates/v/aya.svg?style=for-the-badge&logo=rust [crates-url]: https://crates.io/crates/aya [license-badge]: https://img.shields.io/badge/license-MIT%2FApache--2.0-blue?style=for-the-badge -[build-badge]: https://img.shields.io/github/actions/workflow/status/aya-rs/aya/build-aya.yml?branch=main&style=for-the-badge +[build-badge]: https://img.shields.io/github/actions/workflow/status/aya-rs/aya/ci.yml?style=for-the-badge +[build-url]: https://github.com/aya-rs/aya/actions/workflows/ci.yml [book-badge]: https://img.shields.io/badge/read%20the-book-9cf.svg?style=for-the-badge&logo=mdbook [book-url]: https://aya-rs.dev/book diff --git a/aya-bpf-macros/src/lib.rs b/aya-bpf-macros/src/lib.rs index 5696b82d..f29b725f 100644 --- a/aya-bpf-macros/src/lib.rs +++ b/aya-bpf-macros/src/lib.rs @@ -128,6 +128,28 @@ pub fn sk_msg(attrs: TokenStream, item: TokenStream) -> TokenStream { } } +/// Marks a function as an eBPF XDP program that can be attached to a network interface. +/// +/// On some NIC drivers, XDP probes are compatible with jumbo frames through the use of +/// multi-buffer packets. Programs can opt-in this support by passing the `frags` argument. +/// +/// XDP programs can also be chained through the use of CPU maps and dev maps, but must opt-in +/// with the `map = "cpumap"` or `map = "devmap"` arguments. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.8. +/// +/// # Examples +/// +/// ```no_run +/// use aya_bpf::{bindings::xdp_action::XDP_PASS, macros::xdp, programs::XdpContext}; +/// +/// #[xdp(frags)] +/// pub fn xdp(ctx: XdpContext) -> u32 { +/// XDP_PASS +/// } +/// ``` #[proc_macro_error] #[proc_macro_attribute] pub fn xdp(attrs: TokenStream, item: TokenStream) -> TokenStream { diff --git a/aya-bpf-macros/src/xdp.rs b/aya-bpf-macros/src/xdp.rs index 9a5ff36a..61f8c014 100644 --- a/aya-bpf-macros/src/xdp.rs +++ b/aya-bpf-macros/src/xdp.rs @@ -1,31 +1,52 @@ -use std::borrow::Cow; - use proc_macro2::TokenStream; use quote::quote; -use syn::{ItemFn, Result}; +use syn::{Error, ItemFn, Result}; -use crate::args::{err_on_unknown_args, pop_bool_arg, Args}; +use crate::args::{err_on_unknown_args, pop_bool_arg, pop_string_arg, Args}; pub(crate) struct Xdp { item: ItemFn, frags: bool, + map: Option, +} + +#[derive(Clone, Copy)] +pub(crate) enum XdpMap { + CpuMap, + DevMap, } impl Xdp { pub(crate) fn parse(attrs: TokenStream, item: TokenStream) -> Result { let item = syn::parse2(item)?; let mut args: Args = syn::parse2(attrs)?; + let frags = pop_bool_arg(&mut args, "frags"); + let map = match pop_string_arg(&mut args, "map").as_deref() { + Some("cpumap") => Some(XdpMap::CpuMap), + Some("devmap") => Some(XdpMap::DevMap), + Some(name) => { + return Err(Error::new_spanned( + "map", + format!("Invalid value. Expected 'cpumap' or 'devmap', found '{name}'"), + )) + } + None => None, + }; + err_on_unknown_args(&args)?; - Ok(Xdp { item, frags }) + Ok(Xdp { item, frags, map }) } pub(crate) fn expand(&self) -> Result { - let section_name: Cow<'_, _> = if self.frags { - "xdp.frags".into() - } else { - "xdp".into() + let mut section_name = vec![if self.frags { "xdp.frags" } else { "xdp" }]; + match self.map { + Some(XdpMap::CpuMap) => section_name.push("cpumap"), + Some(XdpMap::DevMap) => section_name.push("devmap"), + None => (), }; + let section_name = section_name.join("/"); + let fn_vis = &self.item.vis; let fn_name = self.item.sig.ident.clone(); let item = &self.item; @@ -97,4 +118,122 @@ mod tests { }; assert_eq!(expected.to_string(), expanded.to_string()); } + + #[test] + fn test_xdp_cpumap() { + let prog = Xdp::parse( + parse_quote! { map = "cpumap" }, + parse_quote! { + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + }, + ) + .unwrap(); + let expanded = prog.expand().unwrap(); + let expected = quote! { + #[no_mangle] + #[link_section = "xdp/cpumap"] + fn prog(ctx: *mut ::aya_bpf::bindings::xdp_md) -> u32 { + return prog(::aya_bpf::programs::XdpContext::new(ctx)); + + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + } + }; + assert_eq!(expected.to_string(), expanded.to_string()); + } + + #[test] + fn test_xdp_devmap() { + let prog = Xdp::parse( + parse_quote! { map = "devmap" }, + parse_quote! { + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + }, + ) + .unwrap(); + let expanded = prog.expand().unwrap(); + let expected = quote! { + #[no_mangle] + #[link_section = "xdp/devmap"] + fn prog(ctx: *mut ::aya_bpf::bindings::xdp_md) -> u32 { + return prog(::aya_bpf::programs::XdpContext::new(ctx)); + + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + } + }; + assert_eq!(expected.to_string(), expanded.to_string()); + } + + #[test] + #[should_panic(expected = "Invalid value. Expected 'cpumap' or 'devmap', found 'badmap'")] + fn test_xdp_bad_map() { + Xdp::parse( + parse_quote! { map = "badmap" }, + parse_quote! { + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + }, + ) + .unwrap(); + } + + #[test] + fn test_xdp_frags_cpumap() { + let prog = Xdp::parse( + parse_quote! { frags, map = "cpumap" }, + parse_quote! { + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + }, + ) + .unwrap(); + let expanded = prog.expand().unwrap(); + let expected = quote! { + #[no_mangle] + #[link_section = "xdp.frags/cpumap"] + fn prog(ctx: *mut ::aya_bpf::bindings::xdp_md) -> u32 { + return prog(::aya_bpf::programs::XdpContext::new(ctx)); + + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + } + }; + assert_eq!(expected.to_string(), expanded.to_string()); + } + + #[test] + fn test_xdp_frags_devmap() { + let prog = Xdp::parse( + parse_quote! { frags, map = "devmap" }, + parse_quote! { + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + }, + ) + .unwrap(); + let expanded = prog.expand().unwrap(); + let expected = quote! { + #[no_mangle] + #[link_section = "xdp.frags/devmap"] + fn prog(ctx: *mut ::aya_bpf::bindings::xdp_md) -> u32 { + return prog(::aya_bpf::programs::XdpContext::new(ctx)); + + fn prog(ctx: &mut ::aya_bpf::programs::XdpContext) -> i32 { + 0 + } + } + }; + assert_eq!(expected.to_string(), expanded.to_string()); + } } diff --git a/aya-obj/src/lib.rs b/aya-obj/src/lib.rs index d6d2a8a5..ea0e5670 100644 --- a/aya-obj/src/lib.rs +++ b/aya-obj/src/lib.rs @@ -77,6 +77,12 @@ mod std { pub use core_error::Error; } pub use core::*; + + pub mod os { + pub mod fd { + pub type RawFd = core::ffi::c_int; + } + } } pub mod btf; diff --git a/aya-obj/src/maps.rs b/aya-obj/src/maps.rs index dbffed0c..aede3cfe 100644 --- a/aya-obj/src/maps.rs +++ b/aya-obj/src/maps.rs @@ -176,6 +176,14 @@ impl Map { } } + /// Set the value size in bytes + pub fn set_value_size(&mut self, size: u32) { + match self { + Map::Legacy(m) => m.def.value_size = size, + Map::Btf(m) => m.def.value_size = size, + } + } + /// Returns the max entry number pub fn max_entries(&self) -> u32 { match self { diff --git a/aya-obj/src/obj.rs b/aya-obj/src/obj.rs index deadeeaf..38221f96 100644 --- a/aya-obj/src/obj.rs +++ b/aya-obj/src/obj.rs @@ -19,6 +19,7 @@ use crate::{ btf::BtfFeatures, generated::{BPF_CALL, BPF_JMP, BPF_K}, maps::{BtfMap, LegacyMap, Map, MINIMUM_MAP_SIZE}, + programs::XdpAttachType, relocation::*, util::HashMap, }; @@ -47,17 +48,22 @@ pub struct Features { bpf_perf_link: bool, bpf_global_data: bool, bpf_cookie: bool, + cpumap_prog_id: bool, + devmap_prog_id: bool, btf: Option, } impl Features { #[doc(hidden)] + #[allow(clippy::too_many_arguments)] pub fn new( bpf_name: bool, bpf_probe_read_kernel: bool, bpf_perf_link: bool, bpf_global_data: bool, bpf_cookie: bool, + cpumap_prog_id: bool, + devmap_prog_id: bool, btf: Option, ) -> Self { Self { @@ -66,6 +72,8 @@ impl Features { bpf_perf_link, bpf_global_data, bpf_cookie, + cpumap_prog_id, + devmap_prog_id, btf, } } @@ -95,6 +103,16 @@ impl Features { self.bpf_cookie } + /// Returns whether XDP CPU Maps support chained program IDs. + pub fn cpumap_prog_id(&self) -> bool { + self.cpumap_prog_id + } + + /// Returns whether XDP Device Maps support chained program IDs. + pub fn devmap_prog_id(&self) -> bool { + self.devmap_prog_id + } + /// If BTF is supported, returns which BTF features are supported. pub fn btf(&self) -> Option<&BtfFeatures> { self.btf.as_ref() @@ -204,8 +222,6 @@ pub struct Function { /// - `struct_ops+` /// - `fmod_ret+`, `fmod_ret.s+` /// - `iter+`, `iter.s+` -/// - `xdp.frags/cpumap`, `xdp/cpumap` -/// - `xdp.frags/devmap`, `xdp/devmap` #[derive(Debug, Clone)] #[allow(missing_docs)] pub enum ProgramSection { @@ -221,6 +237,7 @@ pub enum ProgramSection { SocketFilter, Xdp { frags: bool, + attach_type: XdpAttachType, }, SkMsg, SkSkbStreamParser, @@ -283,8 +300,19 @@ impl FromStr for ProgramSection { "uprobe.s" => UProbe { sleepable: true }, "uretprobe" => URetProbe { sleepable: false }, "uretprobe.s" => URetProbe { sleepable: true }, - "xdp" => Xdp { frags: false }, - "xdp.frags" => Xdp { frags: true }, + "xdp" | "xdp.frags" => Xdp { + frags: kind == "xdp.frags", + attach_type: match pieces.next() { + None => XdpAttachType::Interface, + Some("cpumap") => XdpAttachType::CpuMap, + Some("devmap") => XdpAttachType::DevMap, + Some(_) => { + return Err(ParseError::InvalidProgramSection { + section: section.to_owned(), + }) + } + }, + }, "tp_btf" => BtfTracePoint, "tracepoint" | "tp" => TracePoint, "socket" => SocketFilter, @@ -2012,7 +2040,7 @@ mod tests { assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, - "xdp/foo", + "xdp", bytes_of(&fake_ins()), None )), @@ -2035,7 +2063,7 @@ mod tests { assert_matches!( obj.parse_section(fake_section( BpfSectionKind::Program, - "xdp.frags/foo", + "xdp.frags", bytes_of(&fake_ins()), None )), diff --git a/aya-obj/src/programs/mod.rs b/aya-obj/src/programs/mod.rs index 4f76211a..6b66b005 100644 --- a/aya-obj/src/programs/mod.rs +++ b/aya-obj/src/programs/mod.rs @@ -3,7 +3,9 @@ pub mod cgroup_sock; pub mod cgroup_sock_addr; pub mod cgroup_sockopt; +pub mod xdp; pub use cgroup_sock::CgroupSockAttachType; pub use cgroup_sock_addr::CgroupSockAddrAttachType; pub use cgroup_sockopt::CgroupSockoptAttachType; +pub use xdp::XdpAttachType; diff --git a/aya-obj/src/programs/xdp.rs b/aya-obj/src/programs/xdp.rs new file mode 100644 index 00000000..17fab6ab --- /dev/null +++ b/aya-obj/src/programs/xdp.rs @@ -0,0 +1,24 @@ +//! XDP programs. + +use crate::generated::bpf_attach_type; + +/// Defines where to attach an `XDP` program. +#[derive(Copy, Clone, Debug)] +pub enum XdpAttachType { + /// Attach to a network interface. + Interface, + /// Attach to a cpumap. Requires kernel 5.9 or later. + CpuMap, + /// Attach to a devmap. Requires kernel 5.8 or later. + DevMap, +} + +impl From for bpf_attach_type { + fn from(value: XdpAttachType) -> Self { + match value { + XdpAttachType::Interface => bpf_attach_type::BPF_XDP, + XdpAttachType::CpuMap => bpf_attach_type::BPF_XDP_CPUMAP, + XdpAttachType::DevMap => bpf_attach_type::BPF_XDP_DEVMAP, + } + } +} diff --git a/aya-obj/src/relocation.rs b/aya-obj/src/relocation.rs index 8269f6ca..83879fc8 100644 --- a/aya-obj/src/relocation.rs +++ b/aya-obj/src/relocation.rs @@ -105,7 +105,7 @@ pub(crate) struct Symbol { impl Object { /// Relocates the map references - pub fn relocate_maps<'a, I: Iterator>( + pub fn relocate_maps<'a, I: Iterator>( &mut self, maps: I, text_sections: &HashSet, @@ -178,8 +178,8 @@ impl Object { fn relocate_maps<'a, I: Iterator>( fun: &mut Function, relocations: I, - maps_by_section: &HashMap, - maps_by_symbol: &HashMap, + maps_by_section: &HashMap, + maps_by_symbol: &HashMap, symbol_table: &HashMap, text_sections: &HashSet, ) -> Result<(), RelocationError> { diff --git a/aya/Cargo.toml b/aya/Cargo.toml index 59025b2d..9cdae143 100644 --- a/aya/Cargo.toml +++ b/aya/Cargo.toml @@ -12,6 +12,7 @@ edition = "2021" rust-version = "1.66" [dependencies] +assert_matches = { workspace = true } async-io = { workspace = true, optional = true } aya-obj = { workspace = true, features = ["std"] } bitflags = { workspace = true } @@ -28,7 +29,6 @@ thiserror = { workspace = true } tokio = { workspace = true, features = ["rt"], optional = true } [dev-dependencies] -assert_matches = { workspace = true } tempfile = { workspace = true } [features] diff --git a/aya/src/bpf.rs b/aya/src/bpf.rs index f967c737..2272bc52 100644 --- a/aya/src/bpf.rs +++ b/aya/src/bpf.rs @@ -3,7 +3,7 @@ use std::{ collections::{HashMap, HashSet}, fs, io, os::{ - fd::{AsFd as _, OwnedFd}, + fd::{AsFd as _, AsRawFd as _, OwnedFd}, raw::c_int, }, path::{Path, PathBuf}, @@ -36,12 +36,12 @@ use crate::{ SkMsg, SkSkb, SkSkbKind, SockOps, SocketFilter, TracePoint, UProbe, Xdp, }, sys::{ - bpf_load_btf, bpf_map_freeze, bpf_map_update_elem_ptr, is_bpf_cookie_supported, - is_bpf_global_data_supported, is_btf_datasec_supported, is_btf_decl_tag_supported, - is_btf_enum64_supported, is_btf_float_supported, is_btf_func_global_supported, - is_btf_func_supported, is_btf_supported, is_btf_type_tag_supported, is_perf_link_supported, - is_probe_read_kernel_supported, is_prog_name_supported, retry_with_verifier_logs, - SyscallError, + bpf_load_btf, is_bpf_cookie_supported, is_bpf_global_data_supported, + is_btf_datasec_supported, is_btf_decl_tag_supported, is_btf_enum64_supported, + is_btf_float_supported, is_btf_func_global_supported, is_btf_func_supported, + is_btf_supported, is_btf_type_tag_supported, is_perf_link_supported, + is_probe_read_kernel_supported, is_prog_id_supported, is_prog_name_supported, + retry_with_verifier_logs, }, util::{bytes_of, bytes_of_slice, possible_cpus, POSSIBLE_CPUS}, }; @@ -94,6 +94,8 @@ fn detect_features() -> Features { is_perf_link_supported(), is_bpf_global_data_supported(), is_bpf_cookie_supported(), + is_prog_id_supported(BPF_MAP_TYPE_CPUMAP), + is_prog_id_supported(BPF_MAP_TYPE_DEVMAP), btf, ); debug!("BPF Feature Detection: {:#?}", f); @@ -413,7 +415,10 @@ impl<'a> BpfLoader<'a> { | ProgramSection::URetProbe { sleepable: _ } | ProgramSection::TracePoint | ProgramSection::SocketFilter - | ProgramSection::Xdp { frags: _ } + | ProgramSection::Xdp { + frags: _, + attach_type: _, + } | ProgramSection::SkMsg | ProgramSection::SkSkbStreamParser | ProgramSection::SkSkbStreamVerdict @@ -474,6 +479,15 @@ impl<'a> BpfLoader<'a> { } } } + match obj.map_type().try_into() { + Ok(BPF_MAP_TYPE_CPUMAP) => { + obj.set_value_size(if FEATURES.cpumap_prog_id() { 8 } else { 4 }) + } + Ok(BPF_MAP_TYPE_DEVMAP | BPF_MAP_TYPE_DEVMAP_HASH) => { + obj.set_value_size(if FEATURES.devmap_prog_id() { 8 } else { 4 }) + } + _ => (), + } let btf_fd = btf_fd.as_deref().map(|fd| fd.as_fd()); let mut map = match obj.pinning() { PinningType::None => MapData::create(obj, &name, btf_fd)?, @@ -482,23 +496,7 @@ impl<'a> BpfLoader<'a> { MapData::create_pinned(path, obj, &name, btf_fd)? } }; - let fd = map.fd; - if !map.obj.data().is_empty() && map.obj.section_kind() != BpfSectionKind::Bss { - bpf_map_update_elem_ptr(fd, &0 as *const _, map.obj.data_mut().as_mut_ptr(), 0) - .map_err(|(_, io_error)| SyscallError { - call: "bpf_map_update_elem", - io_error, - }) - .map_err(MapError::from)?; - } - if map.obj.section_kind() == BpfSectionKind::Rodata { - bpf_map_freeze(fd) - .map_err(|(_, io_error)| SyscallError { - call: "bpf_map_freeze", - io_error, - }) - .map_err(MapError::from)?; - } + map.finalize()?; maps.insert(name, map); } @@ -510,7 +508,7 @@ impl<'a> BpfLoader<'a> { obj.relocate_maps( maps.iter() - .map(|(s, data)| (s.as_str(), data.fd, &data.obj)), + .map(|(s, data)| (s.as_str(), data.fd().as_fd().as_raw_fd(), data.obj())), &text_sections, )?; obj.relocate_calls(&text_sections)?; @@ -573,13 +571,18 @@ impl<'a> BpfLoader<'a> { ProgramSection::SocketFilter => Program::SocketFilter(SocketFilter { data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), }), - ProgramSection::Xdp { frags, .. } => { + ProgramSection::Xdp { + frags, attach_type, .. + } => { let mut data = ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level); if *frags { data.flags = BPF_F_XDP_HAS_FRAGS; } - Program::Xdp(Xdp { data }) + Program::Xdp(Xdp { + data, + attach_type: *attach_type, + }) } ProgramSection::SkMsg => Program::SkMsg(SkMsg { data: ProgramData::new(prog_name, obj, btf_fd, *verifier_log_level), @@ -691,7 +694,7 @@ impl<'a> BpfLoader<'a> { if !*allow_unsupported_maps { maps.iter().try_for_each(|(_, x)| match x { Map::Unsupported(map) => Err(BpfError::MapError(MapError::Unsupported { - map_type: map.obj.map_type(), + map_type: map.obj().map_type(), })), _ => Ok(()), })?; @@ -705,7 +708,7 @@ fn parse_map(data: (String, MapData)) -> Result<(String, Map), BpfError> { let name = data.0; let map = data.1; let map_type = - bpf_map_type::try_from(map.obj.map_type()).map_err(|e| MapError::InvalidMapType { + bpf_map_type::try_from(map.obj().map_type()).map_err(|e| MapError::InvalidMapType { map_type: e.map_type, })?; let map = match map_type { @@ -724,6 +727,10 @@ fn parse_map(data: (String, MapData)) -> Result<(String, Map), BpfError> { BPF_MAP_TYPE_STACK => Map::Stack(map), BPF_MAP_TYPE_STACK_TRACE => Map::StackTraceMap(map), BPF_MAP_TYPE_QUEUE => Map::Queue(map), + BPF_MAP_TYPE_CPUMAP => Map::CpuMap(map), + BPF_MAP_TYPE_DEVMAP => Map::DevMap(map), + BPF_MAP_TYPE_DEVMAP_HASH => Map::DevMapHash(map), + BPF_MAP_TYPE_XSKMAP => Map::XskMap(map), m => { warn!("The map {name} is of type {:#?} which is currently unsupported in Aya, use `allow_unsupported_maps()` to load it anyways", m); Map::Unsupported(map) diff --git a/aya/src/maps/array/array.rs b/aya/src/maps/array/array.rs index 64454a3c..5d137d05 100644 --- a/aya/src/maps/array/array.rs +++ b/aya/src/maps/array/array.rs @@ -1,6 +1,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsFd as _, }; use crate::{ @@ -61,7 +62,7 @@ impl, V: Pod> Array { pub fn get(&self, index: &u32, flags: u64) -> Result { let data = self.inner.borrow(); check_bounds(data, *index)?; - let fd = data.fd; + let fd = data.fd().as_fd(); let value = bpf_map_lookup_elem(fd, index, flags).map_err(|(_, io_error)| SyscallError { @@ -88,7 +89,7 @@ impl, V: Pod> Array { pub fn set(&mut self, index: u32, value: impl Borrow, flags: u64) -> Result<(), MapError> { let data = self.inner.borrow_mut(); check_bounds(data, index)?; - let fd = data.fd; + let fd = data.fd().as_fd(); bpf_map_update_elem(fd, Some(&index), value.borrow(), flags).map_err(|(_, io_error)| { SyscallError { call: "bpf_map_update_elem", diff --git a/aya/src/maps/array/per_cpu_array.rs b/aya/src/maps/array/per_cpu_array.rs index db6169bd..f384b713 100644 --- a/aya/src/maps/array/per_cpu_array.rs +++ b/aya/src/maps/array/per_cpu_array.rs @@ -1,6 +1,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsFd as _, }; use crate::{ @@ -80,7 +81,7 @@ impl, V: Pod> PerCpuArray { pub fn get(&self, index: &u32, flags: u64) -> Result, MapError> { let data = self.inner.borrow(); check_bounds(data, *index)?; - let fd = data.fd; + let fd = data.fd().as_fd(); let value = bpf_map_lookup_elem_per_cpu(fd, index, flags).map_err(|(_, io_error)| { SyscallError { @@ -108,7 +109,7 @@ impl, V: Pod> PerCpuArray { pub fn set(&mut self, index: u32, values: PerCpuValues, flags: u64) -> Result<(), MapError> { let data = self.inner.borrow_mut(); check_bounds(data, index)?; - let fd = data.fd; + let fd = data.fd().as_fd(); bpf_map_update_elem_per_cpu(fd, &index, &values, flags).map_err(|(_, io_error)| { SyscallError { diff --git a/aya/src/maps/array/program_array.rs b/aya/src/maps/array/program_array.rs index a38ce023..48bb6b9d 100644 --- a/aya/src/maps/array/program_array.rs +++ b/aya/src/maps/array/program_array.rs @@ -74,7 +74,7 @@ impl> ProgramArray { pub fn set(&mut self, index: u32, program: &ProgramFd, flags: u64) -> Result<(), MapError> { let data = self.inner.borrow_mut(); check_bounds(data, index)?; - let fd = data.fd; + let fd = data.fd().as_fd(); let prog_fd = program.as_fd(); let prog_fd = prog_fd.as_raw_fd(); @@ -94,7 +94,7 @@ impl> ProgramArray { pub fn clear_index(&mut self, index: &u32) -> Result<(), MapError> { let data = self.inner.borrow_mut(); check_bounds(data, *index)?; - let fd = self.inner.borrow_mut().fd; + let fd = data.fd().as_fd(); bpf_map_delete_elem(fd, index) .map(|_| ()) diff --git a/aya/src/maps/bloom_filter.rs b/aya/src/maps/bloom_filter.rs index 0396d0f6..dfe4d2cb 100644 --- a/aya/src/maps/bloom_filter.rs +++ b/aya/src/maps/bloom_filter.rs @@ -2,6 +2,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsFd as _, }; use crate::{ @@ -52,7 +53,7 @@ impl, V: Pod> BloomFilter { /// Query the existence of the element. pub fn contains(&self, mut value: &V, flags: u64) -> Result<(), MapError> { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); bpf_map_lookup_elem_ptr::(fd, None, &mut value, flags) .map_err(|(_, io_error)| SyscallError { @@ -67,7 +68,7 @@ impl, V: Pod> BloomFilter { impl, V: Pod> BloomFilter { /// Inserts a value into the map. pub fn insert(&mut self, value: impl Borrow, flags: u64) -> Result<(), MapError> { - let fd = self.inner.borrow_mut().fd; + let fd = self.inner.borrow_mut().fd().as_fd(); bpf_map_push_elem(fd, value.borrow(), flags).map_err(|(_, io_error)| SyscallError { call: "bpf_map_push_elem", io_error, diff --git a/aya/src/maps/hash_map/hash_map.rs b/aya/src/maps/hash_map/hash_map.rs index 8d091582..9d587b33 100644 --- a/aya/src/maps/hash_map/hash_map.rs +++ b/aya/src/maps/hash_map/hash_map.rs @@ -1,6 +1,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsFd as _, }; use crate::{ @@ -52,7 +53,7 @@ impl, K: Pod, V: Pod> HashMap { /// Returns a copy of the value associated with the key. pub fn get(&self, key: &K, flags: u64) -> Result { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError { call: "bpf_map_lookup_elem", io_error, diff --git a/aya/src/maps/hash_map/mod.rs b/aya/src/maps/hash_map/mod.rs index 5e18cb19..40c171ce 100644 --- a/aya/src/maps/hash_map/mod.rs +++ b/aya/src/maps/hash_map/mod.rs @@ -4,6 +4,7 @@ use crate::{ sys::{bpf_map_delete_elem, bpf_map_update_elem, SyscallError}, Pod, }; +use std::os::fd::AsFd as _; #[allow(clippy::module_inception)] mod hash_map; @@ -20,7 +21,7 @@ pub(crate) fn insert( value: &V, flags: u64, ) -> Result<(), MapError> { - let fd = map.fd; + let fd = map.fd().as_fd(); bpf_map_update_elem(fd, Some(key), value, flags).map_err(|(_, io_error)| SyscallError { call: "bpf_map_update_elem", io_error, @@ -30,7 +31,7 @@ pub(crate) fn insert( } pub(crate) fn remove(map: &MapData, key: &K) -> Result<(), MapError> { - let fd = map.fd; + let fd = map.fd().as_fd(); bpf_map_delete_elem(fd, key) .map(|_| ()) .map_err(|(_, io_error)| { diff --git a/aya/src/maps/hash_map/per_cpu_hash_map.rs b/aya/src/maps/hash_map/per_cpu_hash_map.rs index aabc71f6..56fc2ae2 100644 --- a/aya/src/maps/hash_map/per_cpu_hash_map.rs +++ b/aya/src/maps/hash_map/per_cpu_hash_map.rs @@ -2,6 +2,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsFd as _, }; use crate::{ @@ -61,7 +62,7 @@ impl, K: Pod, V: Pod> PerCpuHashMap { /// Returns a slice of values - one for each CPU - associated with the key. pub fn get(&self, key: &K, flags: u64) -> Result, MapError> { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); let values = bpf_map_lookup_elem_per_cpu(fd, key, flags).map_err(|(_, io_error)| SyscallError { call: "bpf_map_lookup_elem", @@ -118,7 +119,7 @@ impl, K: Pod, V: Pod> PerCpuHashMap { values: PerCpuValues, flags: u64, ) -> Result<(), MapError> { - let fd = self.inner.borrow_mut().fd; + let fd = self.inner.borrow_mut().fd().as_fd(); bpf_map_update_elem_per_cpu(fd, key.borrow(), &values, flags).map_err( |(_, io_error)| SyscallError { call: "bpf_map_update_elem", diff --git a/aya/src/maps/lpm_trie.rs b/aya/src/maps/lpm_trie.rs index dcdc443d..d4e1e678 100644 --- a/aya/src/maps/lpm_trie.rs +++ b/aya/src/maps/lpm_trie.rs @@ -2,6 +2,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsFd as _, }; use crate::{ @@ -126,7 +127,7 @@ impl, K: Pod, V: Pod> LpmTrie { /// Returns a copy of the value associated with the longest prefix matching key in the LpmTrie. pub fn get(&self, key: &Key, flags: u64) -> Result { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError { call: "bpf_map_lookup_elem", io_error, @@ -155,7 +156,7 @@ impl, K: Pod, V: Pod> LpmTrie { value: impl Borrow, flags: u64, ) -> Result<(), MapError> { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); bpf_map_update_elem(fd, Some(key), value.borrow(), flags).map_err(|(_, io_error)| { SyscallError { call: "bpf_map_update_elem", @@ -170,7 +171,7 @@ impl, K: Pod, V: Pod> LpmTrie { /// /// Both the prefix and data must match exactly - this method does not do a longest prefix match. pub fn remove(&mut self, key: &Key) -> Result<(), MapError> { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); bpf_map_delete_elem(fd, key) .map(|_| ()) .map_err(|(_, io_error)| { diff --git a/aya/src/maps/mod.rs b/aya/src/maps/mod.rs index 4d8183e9..1a590791 100644 --- a/aya/src/maps/mod.rs +++ b/aya/src/maps/mod.rs @@ -18,17 +18,28 @@ //! the [`TryFrom`] or [`TryInto`] trait. For example: //! //! ```no_run +//! # #[derive(Debug, thiserror::Error)] +//! # enum Error { +//! # #[error(transparent)] +//! # IO(#[from] std::io::Error), +//! # #[error(transparent)] +//! # Map(#[from] aya::maps::MapError), +//! # #[error(transparent)] +//! # Program(#[from] aya::programs::ProgramError), +//! # #[error(transparent)] +//! # Bpf(#[from] aya::BpfError) +//! # } //! # let mut bpf = aya::Bpf::load(&[])?; //! use aya::maps::SockMap; //! use aya::programs::SkMsg; //! //! let intercept_egress = SockMap::try_from(bpf.map_mut("INTERCEPT_EGRESS").unwrap())?; -//! let map_fd = intercept_egress.fd()?; +//! let map_fd = intercept_egress.fd().try_clone()?; //! let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; //! prog.load()?; -//! prog.attach(map_fd)?; +//! prog.attach(&map_fd)?; //! -//! # Ok::<(), aya::BpfError>(()) +//! # Ok::<(), Error>(()) //! ``` //! //! # Maps and `Pod` values @@ -42,22 +53,22 @@ use std::{ marker::PhantomData, mem, ops::Deref, - os::fd::{AsFd as _, AsRawFd, BorrowedFd, IntoRawFd as _, OwnedFd, RawFd}, + os::fd::{AsFd, BorrowedFd, OwnedFd}, path::Path, ptr, }; use crate::util::KernelVersion; -use libc::{getrlimit, rlimit, RLIMIT_MEMLOCK, RLIM_INFINITY}; +use libc::{getrlimit, rlim_t, rlimit, RLIMIT_MEMLOCK, RLIM_INFINITY}; use log::warn; use thiserror::Error; use crate::{ - obj::{self, parse_map_info}, + obj::{self, parse_map_info, BpfSectionKind}, pin::PinError, sys::{ - bpf_create_map, bpf_get_object, bpf_map_get_info_by_fd, bpf_map_get_next_key, - bpf_pin_object, SyscallError, + bpf_create_map, bpf_get_object, bpf_map_freeze, bpf_map_get_info_by_fd, + bpf_map_get_next_key, bpf_map_update_elem_ptr, bpf_pin_object, SyscallError, }, util::nr_cpus, PinningType, Pod, @@ -72,6 +83,7 @@ pub mod queue; pub mod sock; pub mod stack; pub mod stack_trace; +pub mod xdp; pub use array::{Array, PerCpuArray, ProgramArray}; pub use bloom_filter::BloomFilter; @@ -85,6 +97,7 @@ pub use queue::Queue; pub use sock::{SockHash, SockMap}; pub use stack::Stack; pub use stack_trace::StackTraceMap; +pub use xdp::{CpuMap, DevMap, DevMapHash, XskMap}; #[derive(Error, Debug)] /// Errors occuring from working with Maps @@ -168,6 +181,10 @@ pub enum MapError { error: PinError, }, + /// Program IDs are not supported + #[error("program ids are not supported by the current kernel")] + ProgIdNotSupported, + /// Unsupported Map type #[error("Unsupported map type found {map_type}")] Unsupported { @@ -177,25 +194,13 @@ pub enum MapError { } /// A map file descriptor. -pub struct MapFd(RawFd); - -impl AsRawFd for MapFd { - fn as_raw_fd(&self) -> RawFd { - self.0 - } -} +#[derive(Debug)] +pub struct MapFd(OwnedFd); -#[derive(PartialEq, Eq, PartialOrd, Ord)] -struct RlimitSize(usize); -impl fmt::Display for RlimitSize { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.0 < 1024 { - write!(f, "{} bytes", self.0) - } else if self.0 < 1024 * 1024 { - write!(f, "{} KiB", self.0 / 1024) - } else { - write!(f, "{} MiB", self.0 / 1024 / 1024) - } +impl AsFd for MapFd { + fn as_fd(&self) -> BorrowedFd<'_> { + let Self(fd) = self; + fd.as_fd() } } @@ -207,15 +212,28 @@ fn maybe_warn_rlimit() { if ret == 0 { let limit = unsafe { limit.assume_init() }; - let limit: RlimitSize = RlimitSize(limit.rlim_cur.try_into().unwrap()); - if limit.0 == RLIM_INFINITY.try_into().unwrap() { + if limit.rlim_cur == RLIM_INFINITY { return; } + struct HumanSize(rlim_t); + + impl fmt::Display for HumanSize { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let &Self(size) = self; + if size < 1024 { + write!(f, "{} bytes", size) + } else if size < 1024 * 1024 { + write!(f, "{} KiB", size / 1024) + } else { + write!(f, "{} MiB", size / 1024 / 1024) + } + } + } warn!( - "RLIMIT_MEMLOCK value is {}, not RLIM_INFNITY; if experiencing problems with creating \ - maps, try raising RMILIT_MEMLOCK either to RLIM_INFINITY or to a higher value sufficient \ - for size of your maps", - limit + "RLIMIT_MEMLOCK value is {}, not RLIM_INFINITY; if experiencing problems with creating \ + maps, try raising RLIMIT_MEMLOCK either to RLIM_INFINITY or to a higher value sufficient \ + for the size of your maps", + HumanSize(limit.rlim_cur) ); } } @@ -223,37 +241,45 @@ fn maybe_warn_rlimit() { /// eBPF map types. #[derive(Debug)] pub enum Map { - /// A [`Array`] map + /// An [`Array`] map. Array(MapData), - /// A [`PerCpuArray`] map + /// A [`PerCpuArray`] map. PerCpuArray(MapData), - /// A [`ProgramArray`] map + /// A [`ProgramArray`] map. ProgramArray(MapData), - /// A [`HashMap`] map + /// A [`HashMap`] map. HashMap(MapData), - /// A [`PerCpuHashMap`] map + /// A [`PerCpuHashMap`] map. PerCpuHashMap(MapData), /// A [`HashMap`] map that uses a LRU eviction policy. LruHashMap(MapData), /// A [`PerCpuHashMap`] map that uses a LRU eviction policy. PerCpuLruHashMap(MapData), - /// A [`PerfEventArray`] map + /// A [`PerfEventArray`] map. PerfEventArray(MapData), - /// A [`SockMap`] map + /// A [`SockMap`] map. SockMap(MapData), - /// A [`SockHash`] map + /// A [`SockHash`] map. SockHash(MapData), - /// A [`BloomFilter`] map + /// A [`BloomFilter`] map. BloomFilter(MapData), - /// A [`LpmTrie`] map + /// A [`LpmTrie`] map. LpmTrie(MapData), - /// A [`Stack`] map + /// A [`Stack`] map. Stack(MapData), - /// A [`StackTraceMap`] map + /// A [`StackTraceMap`] map. StackTraceMap(MapData), - /// A [`Queue`] map + /// A [`Queue`] map. Queue(MapData), - /// An unsupported map type + /// A [`CpuMap`] map. + CpuMap(MapData), + /// A [`DevMap`] map. + DevMap(MapData), + /// A [`DevMapHash`] map. + DevMapHash(MapData), + /// A [`XskMap`] map. + XskMap(MapData), + /// An unsupported map type. Unsupported(MapData), } @@ -276,6 +302,10 @@ impl Map { Self::Stack(map) => map.obj.map_type(), Self::StackTraceMap(map) => map.obj.map_type(), Self::Queue(map) => map.obj.map_type(), + Self::CpuMap(map) => map.obj.map_type(), + Self::DevMap(map) => map.obj.map_type(), + Self::DevMapHash(map) => map.obj.map_type(), + Self::XskMap(map) => map.obj.map_type(), Self::Unsupported(map) => map.obj.map_type(), } } @@ -335,6 +365,10 @@ impl_try_from_map!(() { SockMap, PerfEventArray, StackTraceMap, + CpuMap, + DevMap, + DevMapHash, + XskMap, }); #[cfg(any(feature = "async_tokio", feature = "async_std"))] @@ -395,10 +429,8 @@ pub(crate) fn check_v_size(map: &MapData) -> Result<(), MapError> { /// You should never need to use this unless you're implementing a new map type. #[derive(Debug)] pub struct MapData { - pub(crate) obj: obj::Map, - pub(crate) fd: RawFd, - /// Indicates if this map has been pinned to bpffs - pub pinned: bool, + obj: obj::Map, + fd: MapFd, } impl MapData { @@ -426,14 +458,8 @@ impl MapData { io_error, } })?; - - #[allow(trivial_numeric_casts)] - let fd = fd as RawFd; - Ok(Self { - obj, - fd, - pinned: false, - }) + let fd = MapFd(fd); + Ok(Self { obj, fd }) } pub(crate) fn create_pinned>( @@ -459,14 +485,14 @@ impl MapData { call: "BPF_OBJ_GET", io_error, }) { - Ok(fd) => Ok(Self { - obj, - fd: fd.into_raw_fd(), - pinned: false, - }), + Ok(fd) => { + let fd = MapFd(fd); + Ok(Self { obj, fd }) + } Err(_) => { let mut map = Self::create(obj, name, btf_fd)?; - map.pin(name, path).map_err(|error| MapError::PinError { + let path = path.join(name); + map.pin(&path).map_err(|error| MapError::PinError { name: Some(name.into()), error, })?; @@ -475,6 +501,27 @@ impl MapData { } } + pub(crate) fn finalize(&mut self) -> Result<(), MapError> { + let Self { obj, fd } = self; + if !obj.data().is_empty() && obj.section_kind() != BpfSectionKind::Bss { + bpf_map_update_elem_ptr(fd.as_fd(), &0 as *const _, obj.data_mut().as_mut_ptr(), 0) + .map_err(|(_, io_error)| SyscallError { + call: "bpf_map_update_elem", + io_error, + }) + .map_err(MapError::from)?; + } + if obj.section_kind() == BpfSectionKind::Rodata { + bpf_map_freeze(fd.as_fd()) + .map_err(|(_, io_error)| SyscallError { + call: "bpf_map_freeze", + io_error, + }) + .map_err(MapError::from)?; + } + Ok(()) + } + /// Loads a map from a pinned path in bpffs. pub fn from_pin>(path: P) -> Result { use std::os::unix::ffi::OsStrExt as _; @@ -493,13 +540,13 @@ impl MapData { call: "BPF_OBJ_GET", io_error, })?; + let fd = MapFd(fd); let info = bpf_map_get_info_by_fd(fd.as_fd())?; Ok(Self { obj: parse_map_info(info, PinningType::ByName), - fd: fd.into_raw_fd(), - pinned: true, + fd, }) } @@ -511,56 +558,64 @@ impl MapData { pub fn from_fd(fd: OwnedFd) -> Result { let info = bpf_map_get_info_by_fd(fd.as_fd())?; + let fd = MapFd(fd); Ok(Self { obj: parse_map_info(info, PinningType::None), - fd: fd.into_raw_fd(), - pinned: false, + fd, }) } - pub(crate) fn pin>(&mut self, name: &str, path: P) -> Result<(), PinError> { + /// Allows the map to be pinned to the provided path. + /// + /// Any directories in the the path provided should have been created by the caller. + /// The path must be on a BPF filesystem. + /// + /// # Errors + /// + /// Returns a [`PinError::SyscallError`] if the underlying syscall fails. + /// This may also happen if the path already exists, in which case the wrapped + /// [`std::io::Error`] kind will be [`std::io::ErrorKind::AlreadyExists`]. + /// Returns a [`PinError::InvalidPinPath`] if the path provided cannot be + /// converted to a [`CString`]. + /// + /// # Example + /// + /// ```no_run + /// # let mut bpf = aya::Bpf::load(&[])?; + /// # use aya::maps::MapData; + /// + /// let mut map = MapData::from_pin("/sys/fs/bpf/my_map")?; + /// map.pin("/sys/fs/bpf/my_map2")?; + /// + /// # Ok::<(), Box>(()) + /// ``` + pub fn pin>(&mut self, path: P) -> Result<(), PinError> { use std::os::unix::ffi::OsStrExt as _; - let Self { fd, pinned, obj: _ } = self; - if *pinned { - return Err(PinError::AlreadyPinned { name: name.into() }); - } - let path = path.as_ref().join(name); - let path_string = CString::new(path.as_os_str().as_bytes()) - .map_err(|error| PinError::InvalidPinPath { path, error })?; - bpf_pin_object(*fd, &path_string).map_err(|(_, io_error)| SyscallError { + let Self { fd, obj: _ } = self; + let path = path.as_ref(); + let path_string = CString::new(path.as_os_str().as_bytes()).map_err(|error| { + PinError::InvalidPinPath { + path: path.to_path_buf(), + error, + } + })?; + bpf_pin_object(fd.as_fd(), &path_string).map_err(|(_, io_error)| SyscallError { call: "BPF_OBJ_PIN", io_error, })?; - *pinned = true; Ok(()) } /// Returns the file descriptor of the map. - /// - /// Can be converted to [`RawFd`] using [`AsRawFd`]. - pub fn fd(&self) -> MapFd { - MapFd(self.fd) - } -} - -impl Drop for MapData { - fn drop(&mut self) { - // TODO: Replace this with an OwnedFd once that is stabilized. - // - // SAFETY: `drop` is only called once. - unsafe { libc::close(self.fd) }; + pub fn fd(&self) -> &MapFd { + let Self { obj: _, fd } = self; + fd } -} -impl Clone for MapData { - fn clone(&self) -> Self { - let Self { obj, fd, pinned } = self; - Self { - obj: obj.clone(), - fd: unsafe { libc::dup(*fd) }, - pinned: *pinned, - } + pub(crate) fn obj(&self) -> &obj::Map { + let Self { obj, fd: _ } = self; + obj } } @@ -598,7 +653,7 @@ impl Iterator for MapKeys<'_, K> { return None; } - let fd = self.map.fd; + let fd = self.map.fd().as_fd(); let key = bpf_map_get_next_key(fd, self.key.as_ref()).map_err(|(_, io_error)| SyscallError { call: "bpf_map_get_next_key", @@ -754,6 +809,7 @@ impl Deref for PerCpuValues { mod tests { use assert_matches::assert_matches; use libc::EFAULT; + use std::os::fd::AsRawFd as _; use crate::{ bpf_map_def, @@ -795,9 +851,8 @@ mod tests { MapData::create(new_obj_map(), "foo", None), Ok(MapData { obj: _, - fd: 42, - pinned: false - }) + fd, + }) => assert_eq!(fd.as_fd().as_raw_fd(), 42) ); } diff --git a/aya/src/maps/perf/perf_event_array.rs b/aya/src/maps/perf/perf_event_array.rs index 1d19d373..ebeef672 100644 --- a/aya/src/maps/perf/perf_event_array.rs +++ b/aya/src/maps/perf/perf_event_array.rs @@ -4,7 +4,7 @@ use std::{ borrow::{Borrow, BorrowMut}, ops::Deref, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd as _, AsRawFd, RawFd}, sync::Arc, }; @@ -181,7 +181,7 @@ impl> PerfEventArray { // FIXME: keep track of open buffers let map_data: &MapData = self.map.deref().borrow(); - let map_fd = map_data.fd; + let map_fd = map_data.fd().as_fd(); let buf = PerfBuffer::open(index, self.page_size, page_count.unwrap_or(2))?; bpf_map_update_elem(map_fd, Some(&index), &buf.as_raw_fd(), 0) .map_err(|(_, io_error)| io_error)?; diff --git a/aya/src/maps/queue.rs b/aya/src/maps/queue.rs index 6eebbf01..31c44633 100644 --- a/aya/src/maps/queue.rs +++ b/aya/src/maps/queue.rs @@ -2,6 +2,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsFd as _, }; use crate::{ @@ -60,7 +61,7 @@ impl, V: Pod> Queue { /// Returns [`MapError::ElementNotFound`] if the queue is empty, [`MapError::SyscallError`] /// if `bpf_map_lookup_and_delete_elem` fails. pub fn pop(&mut self, flags: u64) -> Result { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); let value = bpf_map_lookup_and_delete_elem::(fd, None, flags).map_err( |(_, io_error)| SyscallError { @@ -77,7 +78,7 @@ impl, V: Pod> Queue { /// /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails. pub fn push(&mut self, value: impl Borrow, flags: u64) -> Result<(), MapError> { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); bpf_map_push_elem(fd, value.borrow(), flags).map_err(|(_, io_error)| SyscallError { call: "bpf_map_push_elem", io_error, diff --git a/aya/src/maps/sock/mod.rs b/aya/src/maps/sock/mod.rs index 05fe112c..0c3262a2 100644 --- a/aya/src/maps/sock/mod.rs +++ b/aya/src/maps/sock/mod.rs @@ -5,17 +5,29 @@ mod sock_map; pub use sock_hash::SockHash; pub use sock_map::SockMap; -use std::os::fd::{AsFd, BorrowedFd, RawFd}; +use std::{ + io, + os::fd::{AsFd, BorrowedFd}, +}; /// A socket map file descriptor. -#[derive(Copy, Clone)] -pub struct SockMapFd(RawFd); +#[repr(transparent)] +pub struct SockMapFd(super::MapFd); + +impl SockMapFd { + /// Creates a new instance that shares the same underlying file description as [`self`]. + pub fn try_clone(&self) -> io::Result { + let Self(inner) = self; + let super::MapFd(inner) = inner; + let inner = inner.try_clone()?; + let inner = super::MapFd(inner); + Ok(Self(inner)) + } +} impl AsFd for SockMapFd { fn as_fd(&self) -> BorrowedFd<'_> { - // SAFETY: This isn't necessarily safe, we need to find ways - // to enforce that the file descriptor is still - // valid. TODO(#612) - unsafe { BorrowedFd::borrow_raw(self.0) } + let Self(fd) = self; + fd.as_fd() } } diff --git a/aya/src/maps/sock/sock_hash.rs b/aya/src/maps/sock/sock_hash.rs index 503dcaae..99d0f871 100644 --- a/aya/src/maps/sock/sock_hash.rs +++ b/aya/src/maps/sock/sock_hash.rs @@ -1,12 +1,13 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd as _, AsRawFd, RawFd}, }; use crate::{ maps::{ - check_kv_size, hash_map, sock::SockMapFd, IterableMap, MapData, MapError, MapIter, MapKeys, + check_kv_size, hash_map, sock::SockMapFd, IterableMap, MapData, MapError, MapFd, MapIter, + MapKeys, }, sys::{bpf_map_lookup_elem, SyscallError}, Pod, @@ -47,11 +48,11 @@ use crate::{ /// use aya::programs::SkMsg; /// /// let mut intercept_egress = SockHash::<_, u32>::try_from(bpf.map("INTERCEPT_EGRESS").unwrap())?; -/// let map_fd = intercept_egress.fd()?; +/// let map_fd = intercept_egress.fd().try_clone()?; /// /// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; /// prog.load()?; -/// prog.attach(map_fd)?; +/// prog.attach(&map_fd)?; /// /// let mut client = TcpStream::connect("127.0.0.1:1234")?; /// let mut intercept_egress = SockHash::try_from(bpf.map_mut("INTERCEPT_EGRESS").unwrap())?; @@ -81,7 +82,7 @@ impl, K: Pod> SockHash { /// Returns the fd of the socket stored at the given key. pub fn get(&self, key: &K, flags: u64) -> Result { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); let value = bpf_map_lookup_elem(fd, key, flags).map_err(|(_, io_error)| SyscallError { call: "bpf_map_lookup_elem", io_error, @@ -105,8 +106,11 @@ impl, K: Pod> SockHash { /// /// The returned file descriptor can be used to attach programs that work with /// socket maps, like [`SkMsg`](crate::programs::SkMsg) and [`SkSkb`](crate::programs::SkSkb). - pub fn fd(&self) -> Result { - Ok(SockMapFd(self.inner.borrow().fd)) + pub fn fd(&self) -> &SockMapFd { + let fd: &MapFd = self.inner.borrow().fd(); + // TODO(https://github.com/rust-lang/rfcs/issues/3066): avoid this unsafe. + // SAFETY: `SockMapFd` is #[repr(transparent)] over `MapFd`. + unsafe { std::mem::transmute(fd) } } } diff --git a/aya/src/maps/sock/sock_map.rs b/aya/src/maps/sock/sock_map.rs index 8194cd71..42246c8b 100644 --- a/aya/src/maps/sock/sock_map.rs +++ b/aya/src/maps/sock/sock_map.rs @@ -2,11 +2,11 @@ use std::{ borrow::{Borrow, BorrowMut}, - os::fd::{AsRawFd, RawFd}, + os::fd::{AsFd as _, AsRawFd, RawFd}, }; use crate::{ - maps::{check_bounds, check_kv_size, sock::SockMapFd, MapData, MapError, MapKeys}, + maps::{check_bounds, check_kv_size, sock::SockMapFd, MapData, MapError, MapFd, MapKeys}, sys::{bpf_map_delete_elem, bpf_map_update_elem, SyscallError}, }; @@ -26,18 +26,29 @@ use crate::{ /// # Examples /// /// ```no_run +/// # #[derive(Debug, thiserror::Error)] +/// # enum Error { +/// # #[error(transparent)] +/// # IO(#[from] std::io::Error), +/// # #[error(transparent)] +/// # Map(#[from] aya::maps::MapError), +/// # #[error(transparent)] +/// # Program(#[from] aya::programs::ProgramError), +/// # #[error(transparent)] +/// # Bpf(#[from] aya::BpfError) +/// # } /// # let mut bpf = aya::Bpf::load(&[])?; /// use aya::maps::SockMap; /// use aya::programs::SkSkb; /// /// let intercept_ingress = SockMap::try_from(bpf.map("INTERCEPT_INGRESS").unwrap())?; -/// let map_fd = intercept_ingress.fd()?; +/// let map_fd = intercept_ingress.fd().try_clone()?; /// /// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?; /// prog.load()?; -/// prog.attach(map_fd)?; +/// prog.attach(&map_fd)?; /// -/// # Ok::<(), aya::BpfError>(()) +/// # Ok::<(), Error>(()) /// ``` #[doc(alias = "BPF_MAP_TYPE_SOCKMAP")] pub struct SockMap { @@ -62,8 +73,11 @@ impl> SockMap { /// /// The returned file descriptor can be used to attach programs that work with /// socket maps, like [`SkMsg`](crate::programs::SkMsg) and [`SkSkb`](crate::programs::SkSkb). - pub fn fd(&self) -> Result { - Ok(SockMapFd(self.inner.borrow().fd)) + pub fn fd(&self) -> &SockMapFd { + let fd: &MapFd = self.inner.borrow().fd(); + // TODO(https://github.com/rust-lang/rfcs/issues/3066): avoid this unsafe. + // SAFETY: `SockMapFd` is #[repr(transparent)] over `MapFd`. + unsafe { std::mem::transmute(&fd) } } } @@ -71,7 +85,7 @@ impl> SockMap { /// Stores a socket into the map. pub fn set(&mut self, index: u32, socket: &I, flags: u64) -> Result<(), MapError> { let data = self.inner.borrow_mut(); - let fd = data.fd; + let fd = data.fd().as_fd(); check_bounds(data, index)?; bpf_map_update_elem(fd, Some(&index), &socket.as_raw_fd(), flags).map_err( |(_, io_error)| SyscallError { @@ -85,7 +99,7 @@ impl> SockMap { /// Removes the socket stored at `index` from the map. pub fn clear_index(&mut self, index: &u32) -> Result<(), MapError> { let data = self.inner.borrow_mut(); - let fd = data.fd; + let fd = data.fd().as_fd(); check_bounds(data, *index)?; bpf_map_delete_elem(fd, index) .map(|_| ()) diff --git a/aya/src/maps/stack.rs b/aya/src/maps/stack.rs index c4afeebb..ac1453cd 100644 --- a/aya/src/maps/stack.rs +++ b/aya/src/maps/stack.rs @@ -2,6 +2,7 @@ use std::{ borrow::{Borrow, BorrowMut}, marker::PhantomData, + os::fd::AsFd as _, }; use crate::{ @@ -60,7 +61,7 @@ impl, V: Pod> Stack { /// Returns [`MapError::ElementNotFound`] if the stack is empty, [`MapError::SyscallError`] /// if `bpf_map_lookup_and_delete_elem` fails. pub fn pop(&mut self, flags: u64) -> Result { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); let value = bpf_map_lookup_and_delete_elem::(fd, None, flags).map_err( |(_, io_error)| SyscallError { @@ -77,7 +78,7 @@ impl, V: Pod> Stack { /// /// [`MapError::SyscallError`] if `bpf_map_update_elem` fails. pub fn push(&mut self, value: impl Borrow, flags: u64) -> Result<(), MapError> { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); bpf_map_update_elem(fd, None::<&u32>, value.borrow(), flags).map_err(|(_, io_error)| { SyscallError { call: "bpf_map_update_elem", diff --git a/aya/src/maps/stack_trace.rs b/aya/src/maps/stack_trace.rs index 07281a2b..fdf1d937 100644 --- a/aya/src/maps/stack_trace.rs +++ b/aya/src/maps/stack_trace.rs @@ -1,7 +1,7 @@ //! A hash map of kernel or user space stack traces. //! //! See [`StackTraceMap`] for documentation and examples. -use std::{borrow::Borrow, fs, io, mem, path::Path, str::FromStr}; +use std::{borrow::Borrow, fs, io, mem, os::fd::AsFd as _, path::Path, str::FromStr}; use crate::{ maps::{IterableMap, MapData, MapError, MapIter, MapKeys}, @@ -103,7 +103,7 @@ impl> StackTraceMap { /// Returns [`MapError::KeyNotFound`] if there is no stack trace with the /// given `stack_id`, or [`MapError::SyscallError`] if `bpf_map_lookup_elem` fails. pub fn get(&self, stack_id: &u32, flags: u64) -> Result { - let fd = self.inner.borrow().fd; + let fd = self.inner.borrow().fd().as_fd(); let mut frames = vec![0; self.max_stack_depth]; bpf_map_lookup_elem_ptr(fd, Some(stack_id), frames.as_mut_ptr(), flags) diff --git a/aya/src/maps/xdp/cpu_map.rs b/aya/src/maps/xdp/cpu_map.rs new file mode 100644 index 00000000..d9cc7d19 --- /dev/null +++ b/aya/src/maps/xdp/cpu_map.rs @@ -0,0 +1,195 @@ +//! An array of available CPUs. + +use std::{ + borrow::{Borrow, BorrowMut}, + num::NonZeroU32, + os::fd::{AsFd, AsRawFd}, +}; + +use aya_obj::generated::bpf_cpumap_val; + +use crate::{ + maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError}, + programs::ProgramFd, + sys::{bpf_map_lookup_elem, bpf_map_update_elem, SyscallError}, + Pod, FEATURES, +}; + +use super::XdpMapError; + +/// An array of available CPUs. +/// +/// XDP programs can use this map to redirect packets to a target +/// CPU for processing. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.15. +/// +/// # Examples +/// ```no_run +/// # let elf_bytes = &[]; +/// use aya::maps::xdp::CpuMap; +/// +/// let ncpus = aya::util::nr_cpus().unwrap() as u32; +/// let mut bpf = aya::BpfLoader::new() +/// .set_max_entries("CPUS", ncpus) +/// .load(elf_bytes) +/// .unwrap(); +/// let mut cpumap = CpuMap::try_from(bpf.map_mut("CPUS").unwrap())?; +/// let flags = 0; +/// let queue_size = 2048; +/// for i in 0..ncpus { +/// cpumap.set(i, queue_size, None, flags); +/// } +/// +/// # Ok::<(), aya::BpfError>(()) +/// ``` +/// +/// # See also +/// +/// Kernel documentation: +#[doc(alias = "BPF_MAP_TYPE_CPUMAP")] +pub struct CpuMap { + inner: T, +} + +impl> CpuMap { + pub(crate) fn new(map: T) -> Result { + let data = map.borrow(); + + if FEATURES.cpumap_prog_id() { + check_kv_size::(data)?; + } else { + check_kv_size::(data)?; + } + + Ok(Self { inner: map }) + } + + /// Returns the number of elements in the array. + /// + /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. + pub fn len(&self) -> u32 { + self.inner.borrow().obj.max_entries() + } + + /// Returns the queue size and optional program for a given CPU index. + /// + /// # Errors + /// + /// Returns [`MapError::OutOfBounds`] if `cpu_index` is out of bounds, + /// [`MapError::SyscallError`] if `bpf_map_lookup_elem` fails. + pub fn get(&self, cpu_index: u32, flags: u64) -> Result { + let data = self.inner.borrow(); + check_bounds(data, cpu_index)?; + let fd = data.fd().as_fd(); + + let value = if FEATURES.cpumap_prog_id() { + bpf_map_lookup_elem::<_, bpf_cpumap_val>(fd, &cpu_index, flags).map(|value| { + value.map(|value| CpuMapValue { + queue_size: value.qsize, + // SAFETY: map writes use fd, map reads use id. + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6241 + prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), + }) + }) + } else { + bpf_map_lookup_elem::<_, u32>(fd, &cpu_index, flags).map(|value| { + value.map(|qsize| CpuMapValue { + queue_size: qsize, + prog_id: None, + }) + }) + }; + value + .map_err(|(_, io_error)| SyscallError { + call: "bpf_map_lookup_elem", + io_error, + })? + .ok_or(MapError::KeyNotFound) + } + + /// An iterator over the elements of the map. + pub fn iter(&self) -> impl Iterator> + '_ { + (0..self.len()).map(move |i| self.get(i, 0)) + } +} + +impl> CpuMap { + /// Sets the queue size at the given CPU index, and optionally a chained program. + /// + /// When sending the packet to the CPU at the given index, the kernel will queue up to + /// `queue_size` packets before dropping them. + /// + /// Starting from Linux kernel 5.9, another XDP program can be passed in that will be run on the + /// target CPU, instead of the CPU that receives the packets. This allows to perform minimal + /// computations on CPUs that directly handle packets from a NIC's RX queues, and perform + /// possibly heavier ones in other, less busy CPUs. + /// + /// The chained program must be loaded with the `BPF_XDP_CPUMAP` attach type. When using + /// `aya-ebpf`, that means XDP programs that specify the `map = "cpumap"` argument. See the + /// kernel-space `aya_ebpf::xdp` for more information. + /// + /// # Errors + /// + /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] + /// if `bpf_map_update_elem` fails, [`XdpMapError::ChainedProgramNotSupported`] if the kernel + /// does not support chained programs and one is provided. + pub fn set( + &mut self, + cpu_index: u32, + queue_size: u32, + program: Option<&ProgramFd>, + flags: u64, + ) -> Result<(), XdpMapError> { + let data = self.inner.borrow_mut(); + check_bounds(data, cpu_index)?; + let fd = data.fd().as_fd(); + + let res = if FEATURES.cpumap_prog_id() { + let mut value = unsafe { std::mem::zeroed::() }; + value.qsize = queue_size; + // Default is valid as the kernel will only consider fd > 0: + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/cpumap.c#L466 + value.bpf_prog.fd = program + .map(|prog| prog.as_fd().as_raw_fd()) + .unwrap_or_default(); + bpf_map_update_elem(fd, Some(&cpu_index), &value, flags) + } else { + if program.is_some() { + return Err(XdpMapError::ChainedProgramNotSupported); + } + bpf_map_update_elem(fd, Some(&cpu_index), &queue_size, flags) + }; + + res.map_err(|(_, io_error)| { + MapError::from(SyscallError { + call: "bpf_map_update_elem", + io_error, + }) + })?; + Ok(()) + } +} + +impl> IterableMap for CpuMap { + fn map(&self) -> &MapData { + self.inner.borrow() + } + + fn get(&self, key: &u32) -> Result { + self.get(*key, 0) + } +} + +unsafe impl Pod for bpf_cpumap_val {} + +#[derive(Clone, Copy, Debug)] +/// The value of a CPU map. +pub struct CpuMapValue { + /// Size of the for the CPU. + pub queue_size: u32, + /// Chained XDP program ID. + pub prog_id: Option, +} diff --git a/aya/src/maps/xdp/dev_map.rs b/aya/src/maps/xdp/dev_map.rs new file mode 100644 index 00000000..3c4240f5 --- /dev/null +++ b/aya/src/maps/xdp/dev_map.rs @@ -0,0 +1,187 @@ +//! An array of network devices. + +use std::{ + borrow::{Borrow, BorrowMut}, + num::NonZeroU32, + os::fd::{AsFd, AsRawFd}, +}; + +use aya_obj::generated::bpf_devmap_val; + +use crate::{ + maps::{check_bounds, check_kv_size, IterableMap, MapData, MapError}, + programs::ProgramFd, + sys::{bpf_map_lookup_elem, bpf_map_update_elem, SyscallError}, + Pod, FEATURES, +}; + +use super::XdpMapError; + +/// An array of network devices. +/// +/// XDP programs can use this map to redirect to other network +/// devices. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.14. +/// +/// # Examples +/// ```no_run +/// # let mut bpf = aya::Bpf::load(&[])?; +/// use aya::maps::xdp::DevMap; +/// +/// let mut devmap = DevMap::try_from(bpf.map_mut("IFACES").unwrap())?; +/// // Lookups at index 2 will redirect packets to interface with index 3 (e.g. eth1) +/// devmap.set(2, 3, None, 0); +/// +/// # Ok::<(), aya::BpfError>(()) +/// ``` +/// +/// # See also +/// +/// Kernel documentation: +#[doc(alias = "BPF_MAP_TYPE_DEVMAP")] +pub struct DevMap { + inner: T, +} + +impl> DevMap { + pub(crate) fn new(map: T) -> Result { + let data = map.borrow(); + + if FEATURES.devmap_prog_id() { + check_kv_size::(data)?; + } else { + check_kv_size::(data)?; + } + + Ok(Self { inner: map }) + } + + /// Returns the number of elements in the array. + /// + /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. + pub fn len(&self) -> u32 { + self.inner.borrow().obj.max_entries() + } + + /// Returns the target interface index and optional program at a given index. + /// + /// # Errors + /// + /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] + /// if `bpf_map_lookup_elem` fails. + pub fn get(&self, index: u32, flags: u64) -> Result { + let data = self.inner.borrow(); + check_bounds(data, index)?; + let fd = data.fd().as_fd(); + + let value = if FEATURES.devmap_prog_id() { + bpf_map_lookup_elem::<_, bpf_devmap_val>(fd, &index, flags).map(|value| { + value.map(|value| DevMapValue { + if_index: value.ifindex, + // SAFETY: map writes use fd, map reads use id. + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6228 + prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), + }) + }) + } else { + bpf_map_lookup_elem::<_, u32>(fd, &index, flags).map(|value| { + value.map(|ifindex| DevMapValue { + if_index: ifindex, + prog_id: None, + }) + }) + }; + value + .map_err(|(_, io_error)| SyscallError { + call: "bpf_map_lookup_elem", + io_error, + })? + .ok_or(MapError::KeyNotFound) + } + + /// An iterator over the elements of the array. + pub fn iter(&self) -> impl Iterator> + '_ { + (0..self.len()).map(move |i| self.get(i, 0)) + } +} + +impl> DevMap { + /// Sets the target interface index at index, and optionally a chained program. + /// + /// When redirecting using `index`, packets will be transmitted by the interface with + /// `target_if_index`. + /// + /// Starting from Linux kernel 5.8, another XDP program can be passed in that will be run before + /// actual transmission. It can be used to modify the packet before transmission with NIC + /// specific data (MAC address update, checksum computations, etc) or other purposes. + /// + /// The chained program must be loaded with the `BPF_XDP_DEVMAP` attach type. When using + /// `aya-ebpf`, that means XDP programs that specify the `map = "devmap"` argument. See the + /// kernel-space `aya_ebpf::xdp` for more information. + /// + /// # Errors + /// + /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] + /// if `bpf_map_update_elem` fails, [`MapError::ProgIdNotSupported`] if the kernel does not + /// support chained programs and one is provided. + pub fn set( + &mut self, + index: u32, + target_if_index: u32, + program: Option<&ProgramFd>, + flags: u64, + ) -> Result<(), XdpMapError> { + let data = self.inner.borrow_mut(); + check_bounds(data, index)?; + let fd = data.fd().as_fd(); + + let res = if FEATURES.devmap_prog_id() { + let mut value = unsafe { std::mem::zeroed::() }; + value.ifindex = target_if_index; + // Default is valid as the kernel will only consider fd > 0: + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918 + value.bpf_prog.fd = program + .map(|prog| prog.as_fd().as_raw_fd()) + .unwrap_or_default(); + bpf_map_update_elem(fd, Some(&index), &value, flags) + } else { + if program.is_some() { + return Err(XdpMapError::ChainedProgramNotSupported); + } + bpf_map_update_elem(fd, Some(&index), &target_if_index, flags) + }; + + res.map_err(|(_, io_error)| { + MapError::from(SyscallError { + call: "bpf_map_update_elem", + io_error, + }) + })?; + Ok(()) + } +} + +impl> IterableMap for DevMap { + fn map(&self) -> &MapData { + self.inner.borrow() + } + + fn get(&self, key: &u32) -> Result { + self.get(*key, 0) + } +} + +unsafe impl Pod for bpf_devmap_val {} + +#[derive(Clone, Copy, Debug)] +/// The value of a device map. +pub struct DevMapValue { + /// Target interface index to redirect to. + pub if_index: u32, + /// Chained XDP program ID. + pub prog_id: Option, +} diff --git a/aya/src/maps/xdp/dev_map_hash.rs b/aya/src/maps/xdp/dev_map_hash.rs new file mode 100644 index 00000000..469c8420 --- /dev/null +++ b/aya/src/maps/xdp/dev_map_hash.rs @@ -0,0 +1,168 @@ +//! An hashmap of network devices. + +use std::{ + borrow::{Borrow, BorrowMut}, + num::NonZeroU32, + os::fd::{AsFd, AsRawFd}, +}; + +use aya_obj::generated::bpf_devmap_val; + +use crate::{ + maps::{check_kv_size, hash_map, IterableMap, MapData, MapError, MapIter, MapKeys}, + programs::ProgramFd, + sys::{bpf_map_lookup_elem, SyscallError}, + FEATURES, +}; + +use super::{dev_map::DevMapValue, XdpMapError}; + +/// An hashmap of network devices. +/// +/// XDP programs can use this map to redirect to other network +/// devices. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 5.4. +/// +/// # Examples +/// ```no_run +/// # let mut bpf = aya::Bpf::load(&[])?; +/// use aya::maps::xdp::DevMapHash; +/// +/// let mut devmap = DevMapHash::try_from(bpf.map_mut("IFACES").unwrap())?; +/// // Lookups with key 2 will redirect packets to interface with index 3 (e.g. eth1) +/// devmap.insert(2, 3, None, 0); +/// +/// # Ok::<(), aya::BpfError>(()) +/// ``` +/// +/// # See also +/// +/// Kernel documentation: +#[doc(alias = "BPF_MAP_TYPE_DEVMAP_HASH")] +pub struct DevMapHash { + inner: T, +} + +impl> DevMapHash { + pub(crate) fn new(map: T) -> Result { + let data = map.borrow(); + + if FEATURES.devmap_prog_id() { + check_kv_size::(data)?; + } else { + check_kv_size::(data)?; + } + + Ok(Self { inner: map }) + } + + /// Returns the target interface index and optional program for a given key. + /// + /// # Errors + /// + /// Returns [`MapError::SyscallError`] if `bpf_map_lookup_elem` fails. + pub fn get(&self, key: u32, flags: u64) -> Result { + let fd = self.inner.borrow().fd().as_fd(); + + let value = if FEATURES.devmap_prog_id() { + bpf_map_lookup_elem::<_, bpf_devmap_val>(fd, &key, flags).map(|value| { + value.map(|value| DevMapValue { + if_index: value.ifindex, + // SAFETY: map writes use fd, map reads use id. + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/include/uapi/linux/bpf.h#L6228 + prog_id: NonZeroU32::new(unsafe { value.bpf_prog.id }), + }) + }) + } else { + bpf_map_lookup_elem::<_, u32>(fd, &key, flags).map(|value| { + value.map(|ifindex| DevMapValue { + if_index: ifindex, + prog_id: None, + }) + }) + }; + value + .map_err(|(_, io_error)| SyscallError { + call: "bpf_map_lookup_elem", + io_error, + })? + .ok_or(MapError::KeyNotFound) + } + + /// An iterator over the elements of the devmap in arbitrary order. + pub fn iter(&self) -> MapIter<'_, u32, DevMapValue, Self> { + MapIter::new(self) + } + + /// An iterator visiting all keys in arbitrary order. + pub fn keys(&self) -> MapKeys<'_, u32> { + MapKeys::new(self.inner.borrow()) + } +} + +impl> DevMapHash { + /// Inserts an ifindex and optionally a chained program in the map. + /// + /// When redirecting using `key`, packets will be transmitted by the interface with `ifindex`. + /// + /// Starting from Linux kernel 5.8, another XDP program can be passed in that will be run before + /// actual transmission. It can be used to modify the packet before transmission with NIC + /// specific data (MAC address update, checksum computations, etc) or other purposes. + /// + /// The chained program must be loaded with the `BPF_XDP_DEVMAP` attach type. When using + /// `aya-ebpf`, that means XDP programs that specify the `map = "devmap"` argument. See the + /// kernel-space `aya_ebpf::xdp` for more information. + /// + /// # Errors + /// + /// Returns [`MapError::SyscallError`] if `bpf_map_update_elem` fails, + /// [`MapError::ProgIdNotSupported`] if the kernel does not support chained programs and one is + /// provided. + pub fn insert( + &mut self, + key: u32, + target_if_index: u32, + program: Option<&ProgramFd>, + flags: u64, + ) -> Result<(), XdpMapError> { + if FEATURES.devmap_prog_id() { + let mut value = unsafe { std::mem::zeroed::() }; + value.ifindex = target_if_index; + // Default is valid as the kernel will only consider fd > 0: + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L866 + // https://github.com/torvalds/linux/blob/2dde18cd1d8fac735875f2e4987f11817cc0bc2c/kernel/bpf/devmap.c#L918 + value.bpf_prog.fd = program + .map(|prog| prog.as_fd().as_raw_fd()) + .unwrap_or_default(); + hash_map::insert(self.inner.borrow_mut(), &key, &value, flags)?; + } else { + if program.is_some() { + return Err(XdpMapError::ChainedProgramNotSupported); + } + hash_map::insert(self.inner.borrow_mut(), &key, &target_if_index, flags)?; + } + Ok(()) + } + + /// Removes a value from the map. + /// + /// # Errors + /// + /// Returns [`MapError::SyscallError`] if `bpf_map_delete_elem` fails. + pub fn remove(&mut self, key: u32) -> Result<(), MapError> { + hash_map::remove(self.inner.borrow_mut(), &key) + } +} + +impl> IterableMap for DevMapHash { + fn map(&self) -> &MapData { + self.inner.borrow() + } + + fn get(&self, key: &u32) -> Result { + self.get(*key, 0) + } +} diff --git a/aya/src/maps/xdp/mod.rs b/aya/src/maps/xdp/mod.rs new file mode 100644 index 00000000..0faa41bb --- /dev/null +++ b/aya/src/maps/xdp/mod.rs @@ -0,0 +1,25 @@ +//! XDP maps. +mod cpu_map; +mod dev_map; +mod dev_map_hash; +mod xsk_map; + +pub use cpu_map::CpuMap; +pub use dev_map::DevMap; +pub use dev_map_hash::DevMapHash; +pub use xsk_map::XskMap; + +use super::MapError; +use thiserror::Error; + +#[derive(Error, Debug)] +/// Errors occuring from working with XDP maps. +pub enum XdpMapError { + /// Chained programs are not supported. + #[error("chained programs are not supported by the current kernel")] + ChainedProgramNotSupported, + + /// Map operation failed. + #[error(transparent)] + MapError(#[from] MapError), +} diff --git a/aya/src/maps/xdp/xsk_map.rs b/aya/src/maps/xdp/xsk_map.rs new file mode 100644 index 00000000..5382ae4c --- /dev/null +++ b/aya/src/maps/xdp/xsk_map.rs @@ -0,0 +1,81 @@ +//! An array of AF_XDP sockets. + +use std::{ + borrow::{Borrow, BorrowMut}, + os::fd::{AsFd, AsRawFd, RawFd}, +}; + +use crate::{ + maps::{check_bounds, check_kv_size, MapData, MapError}, + sys::{bpf_map_update_elem, SyscallError}, +}; + +/// An array of AF_XDP sockets. +/// +/// XDP programs can use this map to redirect packets to a target +/// AF_XDP socket using the `XDP_REDIRECT` action. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.18. +/// +/// # Examples +/// ```no_run +/// # let mut bpf = aya::Bpf::load(&[])?; +/// # let socket_fd = 1; +/// use aya::maps::XskMap; +/// +/// let mut xskmap = XskMap::try_from(bpf.map_mut("SOCKETS").unwrap())?; +/// // socket_fd is the RawFd of an AF_XDP socket +/// xskmap.set(0, socket_fd, 0); +/// # Ok::<(), aya::BpfError>(()) +/// ``` +/// +/// # See also +/// +/// Kernel documentation: +#[doc(alias = "BPF_MAP_TYPE_XSKMAP")] +pub struct XskMap { + inner: T, +} + +impl> XskMap { + pub(crate) fn new(map: T) -> Result { + let data = map.borrow(); + check_kv_size::(data)?; + + Ok(Self { inner: map }) + } + + /// Returns the number of elements in the array. + /// + /// This corresponds to the value of `bpf_map_def::max_entries` on the eBPF side. + pub fn len(&self) -> u32 { + self.inner.borrow().obj.max_entries() + } +} + +impl> XskMap { + /// Sets the `AF_XDP` socket at a given index. + /// + /// When redirecting a packet, the `AF_XDP` socket at `index` will recieve the packet. Note + /// that it will do so only if the socket is bound to the same queue the packet was recieved + /// on. + /// + /// # Errors + /// + /// Returns [`MapError::OutOfBounds`] if `index` is out of bounds, [`MapError::SyscallError`] + /// if `bpf_map_update_elem` fails. + pub fn set(&mut self, index: u32, socket_fd: impl AsRawFd, flags: u64) -> Result<(), MapError> { + let data = self.inner.borrow_mut(); + check_bounds(data, index)?; + let fd = data.fd().as_fd(); + bpf_map_update_elem(fd, Some(&index), &socket_fd.as_raw_fd(), flags).map_err( + |(_, io_error)| SyscallError { + call: "bpf_map_update_elem", + io_error, + }, + )?; + Ok(()) + } +} diff --git a/aya/src/pin.rs b/aya/src/pin.rs index 743df95f..43e197ff 100644 --- a/aya/src/pin.rs +++ b/aya/src/pin.rs @@ -6,12 +6,6 @@ use thiserror::Error; /// An error ocurred working with a pinned BPF object. #[derive(Error, Debug)] pub enum PinError { - /// The object has already been pinned. - #[error("the BPF object `{name}` has already been pinned")] - AlreadyPinned { - /// Object name. - name: String, - }, /// The object FD is not known by Aya. #[error("the BPF object `{name}`'s FD is not known")] NoFd { diff --git a/aya/src/programs/links.rs b/aya/src/programs/links.rs index d06a62e4..e8eeb417 100644 --- a/aya/src/programs/links.rs +++ b/aya/src/programs/links.rs @@ -154,11 +154,9 @@ impl FdLink { error, } })?; - bpf_pin_object(self.fd.as_raw_fd(), &path_string).map_err(|(_, io_error)| { - SyscallError { - call: "BPF_OBJ_PIN", - io_error, - } + bpf_pin_object(self.fd.as_fd(), &path_string).map_err(|(_, io_error)| SyscallError { + call: "BPF_OBJ_PIN", + io_error, })?; Ok(PinnedLink::new(path.into(), self)) } diff --git a/aya/src/programs/mod.rs b/aya/src/programs/mod.rs index 616244e0..bb9622fe 100644 --- a/aya/src/programs/mod.rs +++ b/aya/src/programs/mod.rs @@ -218,9 +218,8 @@ pub enum ProgramError { pub struct ProgramFd(OwnedFd); impl ProgramFd { - /// Creates a new `ProgramFd` instance that shares the same underlying file - /// description as the existing `ProgramFd` instance. - pub fn try_clone(&self) -> Result { + /// Creates a new instance that shares the same underlying file description as [`self`]. + pub fn try_clone(&self) -> io::Result { let Self(inner) = self; let inner = inner.try_clone()?; Ok(Self(inner)) @@ -410,6 +409,39 @@ impl Program { Self::CgroupDevice(p) => p.fd(), } } + + /// Returns information about a loaded program with the [`ProgramInfo`] structure. + /// + /// This information is populated at load time by the kernel and can be used + /// to get kernel details for a given [`Program`]. + pub fn info(&self) -> Result { + match self { + Self::KProbe(p) => p.info(), + Self::UProbe(p) => p.info(), + Self::TracePoint(p) => p.info(), + Self::SocketFilter(p) => p.info(), + Self::Xdp(p) => p.info(), + Self::SkMsg(p) => p.info(), + Self::SkSkb(p) => p.info(), + Self::SockOps(p) => p.info(), + Self::SchedClassifier(p) => p.info(), + Self::CgroupSkb(p) => p.info(), + Self::CgroupSysctl(p) => p.info(), + Self::CgroupSockopt(p) => p.info(), + Self::LircMode2(p) => p.info(), + Self::PerfEvent(p) => p.info(), + Self::RawTracePoint(p) => p.info(), + Self::Lsm(p) => p.info(), + Self::BtfTracePoint(p) => p.info(), + Self::FEntry(p) => p.info(), + Self::FExit(p) => p.info(), + Self::Extension(p) => p.info(), + Self::CgroupSockAddr(p) => p.info(), + Self::SkLookup(p) => p.info(), + Self::CgroupSock(p) => p.info(), + Self::CgroupDevice(p) => p.info(), + } + } } #[derive(Debug)] @@ -536,7 +568,7 @@ fn pin_program>(data: &ProgramData, path: P) -> Resul path: path.into(), error, })?; - bpf_pin_object(fd.as_fd().as_raw_fd(), &path_string).map_err(|(_, io_error)| SyscallError { + bpf_pin_object(fd.as_fd(), &path_string).map_err(|(_, io_error)| SyscallError { call: "BPF_OBJ_PIN", io_error, })?; @@ -847,7 +879,6 @@ macro_rules! impl_from_pin { impl_from_pin!( TracePoint, SocketFilter, - Xdp, SkMsg, CgroupSysctl, LircMode2, @@ -923,12 +954,12 @@ impl_try_from_program!( /// This information is populated at load time by the kernel and can be used /// to correlate a given [`Program`] to it's corresponding [`ProgramInfo`] /// metadata. -macro_rules! impl_program_info { +macro_rules! impl_info { ($($struct_name:ident),+ $(,)?) => { $( impl $struct_name { /// Returns the file descriptor of this Program. - pub fn program_info(&self) -> Result { + pub fn info(&self) -> Result { let ProgramFd(fd) = self.fd()?; ProgramInfo::new_from_fd(fd.as_fd()) @@ -938,7 +969,7 @@ macro_rules! impl_program_info { } } -impl_program_info!( +impl_info!( KProbe, UProbe, TracePoint, diff --git a/aya/src/programs/sk_msg.rs b/aya/src/programs/sk_msg.rs index 554c3e86..f169447b 100644 --- a/aya/src/programs/sk_msg.rs +++ b/aya/src/programs/sk_msg.rs @@ -43,11 +43,11 @@ use crate::{ /// use aya::programs::SkMsg; /// /// let intercept_egress: SockHash<_, u32> = bpf.map("INTERCEPT_EGRESS").unwrap().try_into()?; -/// let map_fd = intercept_egress.fd()?; +/// let map_fd = intercept_egress.fd().try_clone()?; /// /// let prog: &mut SkMsg = bpf.program_mut("intercept_egress_packet").unwrap().try_into()?; /// prog.load()?; -/// prog.attach(map_fd)?; +/// prog.attach(&map_fd)?; /// /// let mut client = TcpStream::connect("127.0.0.1:1234")?; /// let mut intercept_egress: SockHash<_, u32> = bpf.map_mut("INTERCEPT_EGRESS").unwrap().try_into()?; @@ -77,7 +77,7 @@ impl SkMsg { /// Attaches the program to the given sockmap. /// /// The returned value can be used to detach, see [SkMsg::detach]. - pub fn attach(&mut self, map: SockMapFd) -> Result { + pub fn attach(&mut self, map: &SockMapFd) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); let link = ProgAttachLink::attach(prog_fd, map.as_fd(), BPF_SK_MSG_VERDICT)?; diff --git a/aya/src/programs/sk_skb.rs b/aya/src/programs/sk_skb.rs index dac5ba3f..81bc9534 100644 --- a/aya/src/programs/sk_skb.rs +++ b/aya/src/programs/sk_skb.rs @@ -37,18 +37,29 @@ pub enum SkSkbKind { /// # Examples /// /// ```no_run +/// # #[derive(Debug, thiserror::Error)] +/// # enum Error { +/// # #[error(transparent)] +/// # IO(#[from] std::io::Error), +/// # #[error(transparent)] +/// # Map(#[from] aya::maps::MapError), +/// # #[error(transparent)] +/// # Program(#[from] aya::programs::ProgramError), +/// # #[error(transparent)] +/// # Bpf(#[from] aya::BpfError) +/// # } /// # let mut bpf = aya::Bpf::load(&[])?; /// use aya::maps::SockMap; /// use aya::programs::SkSkb; /// /// let intercept_ingress: SockMap<_> = bpf.map("INTERCEPT_INGRESS").unwrap().try_into()?; -/// let map_fd = intercept_ingress.fd()?; +/// let map_fd = intercept_ingress.fd().try_clone()?; /// /// let prog: &mut SkSkb = bpf.program_mut("intercept_ingress_packet").unwrap().try_into()?; /// prog.load()?; -/// prog.attach(map_fd)?; +/// prog.attach(&map_fd)?; /// -/// # Ok::<(), aya::BpfError>(()) +/// # Ok::<(), Error>(()) /// ``` /// /// [socket maps]: crate::maps::sock @@ -70,7 +81,7 @@ impl SkSkb { /// Attaches the program to the given socket map. /// /// The returned value can be used to detach, see [SkSkb::detach]. - pub fn attach(&mut self, map: SockMapFd) -> Result { + pub fn attach(&mut self, map: &SockMapFd) -> Result { let prog_fd = self.fd()?; let prog_fd = prog_fd.as_fd(); diff --git a/aya/src/programs/utils.rs b/aya/src/programs/utils.rs index 0f8f61ae..0930e62b 100644 --- a/aya/src/programs/utils.rs +++ b/aya/src/programs/utils.rs @@ -74,7 +74,7 @@ pub(crate) fn boot_time() -> SystemTime { }; let since_boot = get_time(libc::CLOCK_BOOTTIME); let since_epoch = get_time(libc::CLOCK_REALTIME); - UNIX_EPOCH + since_boot - since_epoch + UNIX_EPOCH + since_epoch - since_boot } /// Get the specified information from a file descriptor's fdinfo. @@ -82,7 +82,7 @@ pub(crate) fn get_fdinfo(fd: BorrowedFd<'_>, key: &str) -> Result, + pub(crate) attach_type: XdpAttachType, } impl Xdp { /// Loads the program inside the kernel. pub fn load(&mut self) -> Result<(), ProgramError> { - self.data.expected_attach_type = Some(bpf_attach_type::BPF_XDP); + self.data.expected_attach_type = Some(self.attach_type.into()); load_program(bpf_prog_type::BPF_PROG_TYPE_XDP, &mut self.data) } @@ -133,10 +137,18 @@ impl Xdp { let prog_fd = prog_fd.as_fd(); if KernelVersion::current().unwrap() >= KernelVersion::new(5, 9, 0) { + // Unwrap safety: the function starts with `self.fd()?` that will succeed if and only + // if the program has been loaded, i.e. there is an fd. We get one by: + // - Using `Xdp::from_pin` that sets `expected_attach_type` + // - Calling `Xdp::attach` that sets `expected_attach_type`, as geting an `Xdp` + // instance trhough `Xdp:try_from(Program)` does not set any fd. + // So, in all cases where we have an fd, we have an expected_attach_type. Thus, if we + // reach this point, expected_attach_type is guaranteed to be Some(_). + let attach_type = self.data.expected_attach_type.unwrap(); let link_fd = bpf_link_create( prog_fd, LinkTarget::IfIndex(if_index), - bpf_attach_type::BPF_XDP, + attach_type, None, flags.bits(), ) @@ -163,6 +175,21 @@ impl Xdp { } } + /// Creates a program from a pinned entry on a bpffs. + /// + /// Existing links will not be populated. To work with existing links you should use [`crate::programs::links::PinnedLink`]. + /// + /// On drop, any managed links are detached and the program is unloaded. This will not result in + /// the program being unloaded from the kernel if it is still pinned. + pub fn from_pin>( + path: P, + attach_type: XdpAttachType, + ) -> Result { + let mut data = ProgramData::from_pinned_path(path, VerifierLogLevel::default())?; + data.expected_attach_type = Some(attach_type.into()); + Ok(Self { data, attach_type }) + } + /// Detaches the program. /// /// See [Xdp::attach]. diff --git a/aya/src/sys/bpf.rs b/aya/src/sys/bpf.rs index 801ea48d..cf41b74a 100644 --- a/aya/src/sys/bpf.rs +++ b/aya/src/sys/bpf.rs @@ -8,6 +8,7 @@ use std::{ }; use crate::util::KernelVersion; +use assert_matches::assert_matches; use libc::{c_char, c_long, ENOENT, ENOSPC}; use obj::{ btf::{BtfEnum64, Enum64}, @@ -38,7 +39,7 @@ pub(crate) fn bpf_create_map( def: &obj::Map, btf_fd: Option>, kernel_version: KernelVersion, -) -> SysResult { +) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_1 }; @@ -91,13 +92,14 @@ pub(crate) fn bpf_create_map( .copy_from_slice(unsafe { slice::from_raw_parts(name.as_ptr(), name_len) }); } - sys_bpf(bpf_cmd::BPF_MAP_CREATE, &mut attr) + // SAFETY: BPF_MAP_CREATE returns a new file descriptor. + unsafe { fd_sys_bpf(bpf_cmd::BPF_MAP_CREATE, &mut attr) } } -pub(crate) fn bpf_pin_object(fd: RawFd, path: &CStr) -> SysResult { +pub(crate) fn bpf_pin_object(fd: BorrowedFd<'_>, path: &CStr) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_4 }; - u.bpf_fd = fd as u32; + u.bpf_fd = fd.as_raw_fd() as u32; u.pathname = path.as_ptr() as u64; sys_bpf(bpf_cmd::BPF_OBJ_PIN, &mut attr) } @@ -194,7 +196,7 @@ pub(crate) fn bpf_load_program( } fn lookup( - fd: RawFd, + fd: BorrowedFd<'_>, key: Option<&K>, flags: u64, cmd: bpf_cmd, @@ -203,7 +205,7 @@ fn lookup( let mut value = MaybeUninit::zeroed(); let u = unsafe { &mut attr.__bindgen_anon_2 }; - u.map_fd = fd as u32; + u.map_fd = fd.as_raw_fd() as u32; if let Some(key) = key { u.key = key as *const _ as u64; } @@ -218,7 +220,7 @@ fn lookup( } pub(crate) fn bpf_map_lookup_elem( - fd: RawFd, + fd: BorrowedFd<'_>, key: &K, flags: u64, ) -> Result, (c_long, io::Error)> { @@ -226,7 +228,7 @@ pub(crate) fn bpf_map_lookup_elem( } pub(crate) fn bpf_map_lookup_and_delete_elem( - fd: RawFd, + fd: BorrowedFd<'_>, key: Option<&K>, flags: u64, ) -> Result, (c_long, io::Error)> { @@ -234,7 +236,7 @@ pub(crate) fn bpf_map_lookup_and_delete_elem( } pub(crate) fn bpf_map_lookup_elem_per_cpu( - fd: RawFd, + fd: BorrowedFd<'_>, key: &K, flags: u64, ) -> Result>, (c_long, io::Error)> { @@ -247,7 +249,7 @@ pub(crate) fn bpf_map_lookup_elem_per_cpu( } pub(crate) fn bpf_map_lookup_elem_ptr( - fd: RawFd, + fd: BorrowedFd<'_>, key: Option<&K>, value: *mut V, flags: u64, @@ -255,7 +257,7 @@ pub(crate) fn bpf_map_lookup_elem_ptr( let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_2 }; - u.map_fd = fd as u32; + u.map_fd = fd.as_raw_fd() as u32; if let Some(key) = key { u.key = key as *const _ as u64; } @@ -270,7 +272,7 @@ pub(crate) fn bpf_map_lookup_elem_ptr( } pub(crate) fn bpf_map_update_elem( - fd: RawFd, + fd: BorrowedFd<'_>, key: Option<&K>, value: &V, flags: u64, @@ -278,7 +280,7 @@ pub(crate) fn bpf_map_update_elem( let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_2 }; - u.map_fd = fd as u32; + u.map_fd = fd.as_raw_fd() as u32; if let Some(key) = key { u.key = key as *const _ as u64; } @@ -288,11 +290,15 @@ pub(crate) fn bpf_map_update_elem( sys_bpf(bpf_cmd::BPF_MAP_UPDATE_ELEM, &mut attr) } -pub(crate) fn bpf_map_push_elem(fd: RawFd, value: &V, flags: u64) -> SysResult { +pub(crate) fn bpf_map_push_elem( + fd: BorrowedFd<'_>, + value: &V, + flags: u64, +) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_2 }; - u.map_fd = fd as u32; + u.map_fd = fd.as_raw_fd() as u32; u.__bindgen_anon_1.value = value as *const _ as u64; u.flags = flags; @@ -300,7 +306,7 @@ pub(crate) fn bpf_map_push_elem(fd: RawFd, value: &V, flags: u64) -> Sys } pub(crate) fn bpf_map_update_elem_ptr( - fd: RawFd, + fd: BorrowedFd<'_>, key: *const K, value: *mut V, flags: u64, @@ -308,7 +314,7 @@ pub(crate) fn bpf_map_update_elem_ptr( let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_2 }; - u.map_fd = fd as u32; + u.map_fd = fd.as_raw_fd() as u32; u.key = key as u64; u.__bindgen_anon_1.value = value as u64; u.flags = flags; @@ -317,7 +323,7 @@ pub(crate) fn bpf_map_update_elem_ptr( } pub(crate) fn bpf_map_update_elem_per_cpu( - fd: RawFd, + fd: BorrowedFd<'_>, key: &K, values: &PerCpuValues, flags: u64, @@ -326,25 +332,25 @@ pub(crate) fn bpf_map_update_elem_per_cpu( bpf_map_update_elem_ptr(fd, key, mem.as_mut_ptr(), flags) } -pub(crate) fn bpf_map_delete_elem(fd: RawFd, key: &K) -> SysResult { +pub(crate) fn bpf_map_delete_elem(fd: BorrowedFd<'_>, key: &K) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_2 }; - u.map_fd = fd as u32; + u.map_fd = fd.as_raw_fd() as u32; u.key = key as *const _ as u64; sys_bpf(bpf_cmd::BPF_MAP_DELETE_ELEM, &mut attr) } pub(crate) fn bpf_map_get_next_key( - fd: RawFd, + fd: BorrowedFd<'_>, key: Option<&K>, ) -> Result, (c_long, io::Error)> { let mut attr = unsafe { mem::zeroed::() }; let mut next_key = MaybeUninit::uninit(); let u = unsafe { &mut attr.__bindgen_anon_2 }; - u.map_fd = fd as u32; + u.map_fd = fd.as_raw_fd() as u32; if let Some(key) = key { u.key = key as *const _ as u64; } @@ -358,10 +364,10 @@ pub(crate) fn bpf_map_get_next_key( } // since kernel 5.2 -pub(crate) fn bpf_map_freeze(fd: RawFd) -> SysResult { +pub(crate) fn bpf_map_freeze(fd: BorrowedFd<'_>) -> SysResult { let mut attr = unsafe { mem::zeroed::() }; let u = unsafe { &mut attr.__bindgen_anon_2 }; - u.map_fd = fd as u32; + u.map_fd = fd.as_raw_fd() as u32; sys_bpf(bpf_cmd::BPF_MAP_FREEZE, &mut attr) } @@ -754,7 +760,7 @@ pub(crate) fn is_bpf_global_data_supported() -> bool { ); if let Ok(map) = map { - insns[0].imm = map.fd; + insns[0].imm = map.fd().as_fd().as_raw_fd(); let gpl = b"GPL\0"; u.license = gpl.as_ptr() as u64; @@ -788,6 +794,28 @@ pub(crate) fn is_bpf_cookie_supported() -> bool { bpf_prog_load(&mut attr).is_ok() } +/// Tests whether CpuMap, DevMap and DevMapHash support program ids +pub(crate) fn is_prog_id_supported(map_type: bpf_map_type) -> bool { + assert_matches!( + map_type, + bpf_map_type::BPF_MAP_TYPE_CPUMAP + | bpf_map_type::BPF_MAP_TYPE_DEVMAP + | bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH + ); + + let mut attr = unsafe { mem::zeroed::() }; + let u = unsafe { &mut attr.__bindgen_anon_1 }; + + u.map_type = map_type as u32; + u.key_size = 4; + u.value_size = 8; // 4 for CPU ID, 8 for CPU ID + prog ID + u.max_entries = 1; + u.map_flags = 0; + + // SAFETY: BPF_MAP_CREATE returns a new file descriptor. + unsafe { fd_sys_bpf(bpf_cmd::BPF_MAP_CREATE, &mut attr) }.is_ok() +} + pub(crate) fn is_btf_supported() -> bool { let mut btf = Btf::new(); let name_offset = btf.add_string("int"); @@ -1067,4 +1095,28 @@ mod tests { let supported = is_perf_link_supported(); assert!(!supported); } + + #[test] + fn test_prog_id_supported() { + override_syscall(|_call| Ok(42)); + + // Ensure that the three map types we can check are accepted + let supported = is_prog_id_supported(bpf_map_type::BPF_MAP_TYPE_CPUMAP); + assert!(supported); + let supported = is_prog_id_supported(bpf_map_type::BPF_MAP_TYPE_DEVMAP); + assert!(supported); + let supported = is_prog_id_supported(bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH); + assert!(supported); + + override_syscall(|_call| Err((-1, io::Error::from_raw_os_error(EINVAL)))); + let supported = is_prog_id_supported(bpf_map_type::BPF_MAP_TYPE_CPUMAP); + assert!(!supported); + } + + #[test] + #[should_panic = "assertion failed: `BPF_MAP_TYPE_HASH` does not match `bpf_map_type::BPF_MAP_TYPE_CPUMAP | bpf_map_type::BPF_MAP_TYPE_DEVMAP | +bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH`"] + fn test_prog_id_supported_reject_types() { + is_prog_id_supported(bpf_map_type::BPF_MAP_TYPE_HASH); + } } diff --git a/bpf/aya-bpf/src/maps/mod.rs b/bpf/aya-bpf/src/maps/mod.rs index 8fa375dd..b46bf084 100644 --- a/bpf/aya-bpf/src/maps/mod.rs +++ b/bpf/aya-bpf/src/maps/mod.rs @@ -17,6 +17,7 @@ pub mod sock_hash; pub mod sock_map; pub mod stack; pub mod stack_trace; +pub mod xdp; pub use array::Array; pub use bloom_filter::BloomFilter; @@ -30,3 +31,4 @@ pub use sock_hash::SockHash; pub use sock_map::SockMap; pub use stack::Stack; pub use stack_trace::StackTrace; +pub use xdp::{CpuMap, DevMap, DevMapHash, XskMap}; diff --git a/bpf/aya-bpf/src/maps/xdp/cpu_map.rs b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs new file mode 100644 index 00000000..133be94b --- /dev/null +++ b/bpf/aya-bpf/src/maps/xdp/cpu_map.rs @@ -0,0 +1,120 @@ +use core::{cell::UnsafeCell, mem}; + +use aya_bpf_bindings::bindings::bpf_cpumap_val; + +use crate::{ + bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_CPUMAP}, + maps::PinningType, +}; + +use super::try_redirect_map; + +/// An array of available CPUs. +/// +/// XDP programs can use this map to redirect packets to a target CPU for processing. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.15. +/// +/// # Examples +/// +/// ```rust,no_run +/// use aya_bpf::{bindings::xdp_action, macros::{map, xdp}, maps::CpuMap, programs::XdpContext}; +/// +/// #[map] +/// static MAP: CpuMap = CpuMap::with_max_entries(8, 0); +/// +/// #[xdp] +/// fn xdp(_ctx: XdpContext) -> i32 { +/// // Redirect to CPU 7 or drop packet if no entry found. +/// MAP.redirect(7, xdp_action::XDP_DROP as u64) +/// } +/// ``` +#[repr(transparent)] +pub struct CpuMap { + def: UnsafeCell, +} + +unsafe impl Sync for CpuMap {} + +impl CpuMap { + /// Creates a [`CpuMap`] with a set maximum number of elements. + /// + /// In a CPU map, an entry represents a CPU core. Thus there should be as many entries as there + /// are CPU cores on the system. `max_entries` can be set to zero here, and updated by userspace + /// at runtime. Refer to the userspace documentation for more information. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::CpuMap}; + /// + /// #[map] + /// static MAP: CpuMap = CpuMap::with_max_entries(8, 0); + /// ``` + pub const fn with_max_entries(max_entries: u32, flags: u32) -> CpuMap { + CpuMap { + def: UnsafeCell::new(bpf_map_def { + type_: BPF_MAP_TYPE_CPUMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }), + } + } + + /// Creates a [`CpuMap`] with a set maximum number of elements that can be pinned to the BPF + /// File System (bpffs). + /// + /// See [`CpuMap::with_max_entries`] for more information. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::CpuMap}; + /// + /// #[map] + /// static MAP: CpuMap = CpuMap::pinned(8, 0); + /// ``` + pub const fn pinned(max_entries: u32, flags: u32) -> CpuMap { + CpuMap { + def: UnsafeCell::new(bpf_map_def { + type_: BPF_MAP_TYPE_CPUMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::ByName as u32, + }), + } + } + + /// Redirects the current packet on the CPU at `index`. + /// + /// The lower two bits of `flags` are used for the return code if the map lookup fails, which + /// can be used as the XDP program's return code if a CPU cannot be found. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{bindings::xdp_action, macros::{map, xdp}, maps::CpuMap, programs::XdpContext}; + /// + /// #[map] + /// static MAP: CpuMap = CpuMap::with_max_entries(8, 0); + /// + /// #[xdp] + /// fn xdp(_ctx: XdpContext) -> u32 { + /// // Redirect to CPU 7 or drop packet if no entry found. + /// MAP.redirect(7, 0).unwrap_or(xdp_action::XDP_DROP) + /// } + /// ``` + #[inline(always)] + pub fn redirect(&self, index: u32, flags: u64) -> Result { + try_redirect_map(&self.def, index, flags) + } +} diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map.rs b/bpf/aya-bpf/src/maps/xdp/dev_map.rs new file mode 100644 index 00000000..cfa44cb3 --- /dev/null +++ b/bpf/aya-bpf/src/maps/xdp/dev_map.rs @@ -0,0 +1,155 @@ +use core::{cell::UnsafeCell, mem, num::NonZeroU32, ptr::NonNull}; + +use aya_bpf_bindings::bindings::bpf_devmap_val; +use aya_bpf_cty::c_void; + +use crate::{ + bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_DEVMAP}, + helpers::bpf_map_lookup_elem, + maps::PinningType, +}; + +use super::try_redirect_map; + +/// An array of network devices. +/// +/// XDP programs can use this map to redirect packets to other network deviecs. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.14. +/// +/// # Examples +/// +/// ```rust,no_run +/// use aya_bpf::{bindings::xdp_action, macros::{map, xdp}, maps::DevMap, programs::XdpContext}; +/// +/// #[map] +/// static MAP: DevMap = DevMap::with_max_entries(1, 0); +/// +/// #[xdp] +/// fn xdp(_ctx: XdpContext) -> i32 { +/// MAP.redirect(0, xdp_action::XDP_PASS as u64) +/// } +/// ``` +#[repr(transparent)] +pub struct DevMap { + def: UnsafeCell, +} + +unsafe impl Sync for DevMap {} + +impl DevMap { + /// Creates a [`DevMap`] with a set maximum number of elements. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::DevMap}; + /// + /// #[map] + /// static MAP: DevMap = DevMap::with_max_entries(8, 0); + /// ``` + pub const fn with_max_entries(max_entries: u32, flags: u32) -> DevMap { + DevMap { + def: UnsafeCell::new(bpf_map_def { + type_: BPF_MAP_TYPE_DEVMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }), + } + } + + /// Creates a [`DevMap`] with a set maximum number of elements that can be pinned to the BPF + /// File System (bpffs). + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::DevMap}; + /// + /// #[map] + /// static MAP: DevMap = DevMap::pinned(8, 0); + /// ``` + pub const fn pinned(max_entries: u32, flags: u32) -> DevMap { + DevMap { + def: UnsafeCell::new(bpf_map_def { + type_: BPF_MAP_TYPE_DEVMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::ByName as u32, + }), + } + } + + /// Retrieves the interface index at `index` in the array. + /// + /// To actually redirect a packet, see [`DevMap::redirect`]. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::DevMap}; + /// + /// #[map] + /// static MAP: DevMap = DevMap::with_max_entries(1, 0); + /// + /// let target_if_index = MAP.get(0).target_if_index; + /// + /// // redirect to if_index + /// ``` + #[inline(always)] + pub fn get(&self, index: u32) -> Option { + unsafe { + let value = bpf_map_lookup_elem( + self.def.get() as *mut _, + &index as *const _ as *const c_void, + ); + NonNull::new(value as *mut bpf_devmap_val).map(|p| DevMapValue { + if_index: p.as_ref().ifindex, + // SAFETY: map writes use fd, map reads use id. + // https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/bpf.h#L6136 + prog_id: NonZeroU32::new(p.as_ref().bpf_prog.id), + }) + } + } + + /// Redirects the current packet on the interface at `index`. + /// + /// The lower two bits of `flags` are used for the return code if the map lookup fails, which + /// can be used as the XDP program's return code if a CPU cannot be found. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{bindings::xdp_action, macros::{map, xdp}, maps::DevMap, programs::XdpContext}; + /// + /// #[map] + /// static MAP: DevMap = DevMap::with_max_entries(8, 0); + /// + /// #[xdp] + /// fn xdp(_ctx: XdpContext) -> u32 { + /// MAP.redirect(7, 0).unwrap_or(xdp_action::XDP_DROP) + /// } + /// ``` + #[inline(always)] + pub fn redirect(&self, index: u32, flags: u64) -> Result { + try_redirect_map(&self.def, index, flags) + } +} + +#[derive(Clone, Copy)] +/// The value of a device map. +pub struct DevMapValue { + /// Target interface index to redirect to. + pub if_index: u32, + /// Chained XDP program ID. + pub prog_id: Option, +} diff --git a/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs new file mode 100644 index 00000000..cbec50bb --- /dev/null +++ b/bpf/aya-bpf/src/maps/xdp/dev_map_hash.rs @@ -0,0 +1,146 @@ +use core::{cell::UnsafeCell, mem, num::NonZeroU32, ptr::NonNull}; + +use aya_bpf_bindings::bindings::bpf_devmap_val; +use aya_bpf_cty::c_void; + +use crate::{ + bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_DEVMAP_HASH}, + helpers::bpf_map_lookup_elem, + maps::PinningType, +}; + +use super::{dev_map::DevMapValue, try_redirect_map}; + +/// A map of network devices. +/// +/// XDP programs can use this map to redirect packets to other network devices. It is similar to +/// [`DevMap`](super::DevMap), but is an hash map rather than an array. Keys do not need to be +/// contiguous nor start at zero, but there is a hashing cost to every lookup. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 5.4. +/// +/// # Examples +/// +/// ```rust,no_run +/// use aya_bpf::{bindings::xdp_action, macros::{map, xdp}, maps::DevMapHash, programs::XdpContext}; +/// +/// #[map] +/// static MAP: DevMapHash = DevMapHash::with_max_entries(1, 0); +/// +/// #[xdp] +/// fn xdp(_ctx: XdpContext) -> i32 { +/// MAP.redirect(42, xdp_action::XDP_PASS as u64) +/// } +/// ``` +#[repr(transparent)] +pub struct DevMapHash { + def: UnsafeCell, +} + +unsafe impl Sync for DevMapHash {} + +impl DevMapHash { + /// Creates a [`DevMapHash`] with a set maximum number of elements. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::DevMapHash}; + /// + /// #[map] + /// static MAP: DevMapHash = DevMapHash::with_max_entries(8, 0); + /// ``` + pub const fn with_max_entries(max_entries: u32, flags: u32) -> DevMapHash { + DevMapHash { + def: UnsafeCell::new(bpf_map_def { + type_: BPF_MAP_TYPE_DEVMAP_HASH, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }), + } + } + + /// Creates a [`DevMapHash`] with a set maximum number of elements that can be pinned to the BPF + /// File System (bpffs). + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::DevMapHash}; + /// + /// #[map] + /// static MAP: DevMapHash = DevMapHash::pinned(8, 0); + /// ``` + pub const fn pinned(max_entries: u32, flags: u32) -> DevMapHash { + DevMapHash { + def: UnsafeCell::new(bpf_map_def { + type_: BPF_MAP_TYPE_DEVMAP_HASH, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::ByName as u32, + }), + } + } + + /// Retrieves the interface index with `key` in the map. + /// + /// To actually redirect a packet, see [`DevMapHash::redirect`]. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::DevMapHash}; + /// + /// #[map] + /// static MAP: DevMapHash = DevMapHash::with_max_entries(1, 0); + /// + /// let target_if_index = MAP.get(42).target_if_index; + /// + /// // redirect to ifindex + /// ``` + #[inline(always)] + pub fn get(&self, key: u32) -> Option { + unsafe { + let value = + bpf_map_lookup_elem(self.def.get() as *mut _, &key as *const _ as *const c_void); + NonNull::new(value as *mut bpf_devmap_val).map(|p| DevMapValue { + if_index: p.as_ref().ifindex, + // SAFETY: map writes use fd, map reads use id. + // https://elixir.bootlin.com/linux/v6.2/source/include/uapi/linux/bpf.h#L6136 + prog_id: NonZeroU32::new(p.as_ref().bpf_prog.id), + }) + } + } + + /// Redirects the current packet on the interface at `key`. + /// + /// The lower two bits of `flags` are used for the return code if the map lookup fails, which + /// can be used as the XDP program's return code if a CPU cannot be found. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{bindings::xdp_action, macros::{map, xdp}, maps::DevMapHash, programs::XdpContext}; + /// + /// #[map] + /// static MAP: DevMapHash = DevMapHash::with_max_entries(8, 0); + /// + /// #[xdp] + /// fn xdp(_ctx: XdpContext) -> u32 { + /// MAP.redirect(7, 0).unwrap_or(xdp_action::XDP_DROP) + /// } + /// ``` + #[inline(always)] + pub fn redirect(&self, key: u32, flags: u64) -> Result { + try_redirect_map(&self.def, key, flags) + } +} diff --git a/bpf/aya-bpf/src/maps/xdp/mod.rs b/bpf/aya-bpf/src/maps/xdp/mod.rs new file mode 100644 index 00000000..5c8df0e5 --- /dev/null +++ b/bpf/aya-bpf/src/maps/xdp/mod.rs @@ -0,0 +1,33 @@ +mod cpu_map; +mod dev_map; +mod dev_map_hash; +mod xsk_map; + +use core::cell::UnsafeCell; + +use aya_bpf_bindings::{ + bindings::{bpf_map_def, xdp_action::XDP_REDIRECT}, + helpers::bpf_redirect_map, +}; +pub use cpu_map::CpuMap; +pub use dev_map::DevMap; +pub use dev_map_hash::DevMapHash; +pub use xsk_map::XskMap; + +/// Wrapper aroung the `bpf_redirect_map` function. +/// +/// # Return value +/// +/// - `Ok(XDP_REDIRECT)` on success. +/// - `Err(_)` of the lowest two bits of `flags` on failure. +#[inline(always)] +fn try_redirect_map(def: &UnsafeCell, key: u32, flags: u64) -> Result { + // Return XDP_REDIRECT on success, or the value of the two lower bits of the flags argument on + // error. Thus I have no idea why it returns a long (i64) instead of something saner, hence the + // unsigned_abs. + let ret = unsafe { bpf_redirect_map(def.get() as *mut _, key.into(), flags) }; + match ret.unsigned_abs() as u32 { + XDP_REDIRECT => Ok(XDP_REDIRECT), + ret => Err(ret), + } +} diff --git a/bpf/aya-bpf/src/maps/xdp/xsk_map.rs b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs new file mode 100644 index 00000000..455dfc84 --- /dev/null +++ b/bpf/aya-bpf/src/maps/xdp/xsk_map.rs @@ -0,0 +1,164 @@ +use core::{cell::UnsafeCell, mem, ptr::NonNull}; + +use aya_bpf_bindings::bindings::bpf_xdp_sock; +use aya_bpf_cty::c_void; + +use crate::{ + bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_XSKMAP}, + helpers::bpf_map_lookup_elem, + maps::PinningType, +}; + +use super::try_redirect_map; + +/// An array of AF_XDP sockets. +/// +/// XDP programs can use this map to redirect packets to a target AF_XDP socket using the +/// `XDP_REDIRECT` action. +/// +/// # Minimum kernel version +/// +/// The minimum kernel version required to use this feature is 4.18. +/// +/// # Examples +/// +/// ```rust,no_run +/// use aya_bpf::{bindings::xdp_action, macros::{map, xdp}, maps::XskMap, programs::XdpContext}; +/// +/// #[map] +/// static SOCKS: XskMap = XskMap::with_max_entries(8, 0); +/// +/// #[xdp] +/// fn xdp(ctx, XdpContext) -> i32 { +/// let queue_id = unsafe { (*ctx.ctx).rx_queue_index }; +/// MAP.redirect(queue_id, xdp_action::XDP_DROP as u64) +/// } +/// ``` +/// +/// # Queue management +/// +/// Packets received on a RX queue can only be redirected to sockets bound on the same queue. Most +/// hardware NICs have multiple RX queue to spread the load across multiple CPU cores using RSS. +/// +/// Three strategies are possible: +/// +/// - Reduce the RX queue count to a single one. This option is great for development, but is +/// detrimental for performance as the single CPU core recieving packets will get overwhelmed. +/// Setting the queue count for a NIC can be achieved using `ethtool -L combined 1`. +/// - Create a socket for every RX queue. Most modern NICs will have an RX queue per CPU thread, so +/// a socket per CPU thread is best for performance. To dynamically size the map depending on the +/// recieve queue count, see the userspace documentation of `CpuMap`. +/// - Create a single socket and use a [`CpuMap`](super::CpuMap) to redirect the packet to the +/// correct CPU core. This way, the packet is sent to another CPU, and a chained XDP program can +/// the redirect to the AF_XDP socket. Using a single socket simplifies the userspace code but +/// will not perform great unless not a lot of traffic is redirected to the socket. Regular +/// traffic however will not be impacted, contrary to reducing the queue count. +#[repr(transparent)] +pub struct XskMap { + def: UnsafeCell, +} + +unsafe impl Sync for XskMap {} + +impl XskMap { + /// Creates a [`XskMap`] with a set maximum number of elements. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::XskMap}; + /// + /// #[map] + /// static SOCKS: XskMap::with_max_entries(8, 0); + /// ``` + pub const fn with_max_entries(max_entries: u32, flags: u32) -> XskMap { + XskMap { + def: UnsafeCell::new(bpf_map_def { + type_: BPF_MAP_TYPE_XSKMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::None as u32, + }), + } + } + + /// Creates a [`XskMap`] with a set maximum number of elements that can be pinned to the BPF + /// filesystem (bpffs). + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::XskMap}; + /// + /// #[map] + /// static SOCKS: XskMap::pinned(8, 0); + /// ``` + pub const fn pinned(max_entries: u32, flags: u32) -> XskMap { + XskMap { + def: UnsafeCell::new(bpf_map_def { + type_: BPF_MAP_TYPE_XSKMAP, + key_size: mem::size_of::() as u32, + value_size: mem::size_of::() as u32, + max_entries, + map_flags: flags, + id: 0, + pinning: PinningType::ByName as u32, + }), + } + } + + /// Retrieves the queue to which the socket is bound at `index` in the array. + /// + /// To actually redirect a packet, see [`XskMap::redirect`]. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{macros::map, maps::XskMap}; + /// + /// #[map] + /// static SOCKS: XskMap = XskMap::with_max_entries(8, 0); + /// + /// let queue_id = SOCKS.get(0); + /// ``` + #[inline(always)] + pub fn get(&self, index: u32) -> Option { + unsafe { + let value = bpf_map_lookup_elem( + self.def.get() as *mut _, + &index as *const _ as *const c_void, + ); + NonNull::new(value as *mut bpf_xdp_sock).map(|p| p.as_ref().queue_id) + } + } + + /// Redirects the current packet to the AF_XDP socket at `index`. + /// + /// The lower two bits of `flags` are used for the return code if the map lookup fails, which + /// can be used as the XDP program's return code if a matching socket cannot be found. + /// + /// However, if the socket at `index` is bound to a RX queue which is not the current RX queue, + /// the packet will be dropped. + /// + /// # Examples + /// + /// ```rust,no_run + /// use aya_bpf::{bindings::xdp_action, macros::{map, xdp}, maps::XskMap, programs::XdpContext}; + /// + /// #[map] + /// static SOCKS: XskMap = XskMap::with_max_entries(8, 0); + /// + /// #[xdp] + /// fn xdp(ctx, XdpContext) -> u32 { + /// let queue_id = unsafe { (*ctx.ctx).rx_queue_index }; + /// MAP.redirect(queue_id, 0).unwrap_or(xdp_action::XDP_DROP) + /// } + /// ``` + #[inline(always)] + pub fn redirect(&self, index: u32, flags: u64) -> Result { + try_redirect_map(&self.def, index, flags) + } +} diff --git a/test/integration-ebpf/Cargo.toml b/test/integration-ebpf/Cargo.toml index 12b04546..ae938675 100644 --- a/test/integration-ebpf/Cargo.toml +++ b/test/integration-ebpf/Cargo.toml @@ -43,3 +43,15 @@ path = "src/bpf_probe_read.rs" [[bin]] name = "two_progs" path = "src/two_progs.rs" + +[[bin]] +name = "redirect" +path = "src/redirect.rs" + +[[bin]] +name = "xdp_sec" +path = "src/xdp_sec.rs" + +[[bin]] +name = "stack_argument" +path = "src/stack_argument.rs" \ No newline at end of file diff --git a/test/integration-ebpf/src/redirect.rs b/test/integration-ebpf/src/redirect.rs new file mode 100644 index 00000000..41812cd0 --- /dev/null +++ b/test/integration-ebpf/src/redirect.rs @@ -0,0 +1,73 @@ +#![no_std] +#![no_main] + +use aya_bpf::{ + bindings::xdp_action, + macros::{map, xdp}, + maps::{Array, CpuMap, DevMap, DevMapHash, XskMap}, + programs::XdpContext, +}; + +#[map] +static SOCKS: XskMap = XskMap::with_max_entries(1, 0); +#[map] +static DEVS: DevMap = DevMap::with_max_entries(1, 0); +#[map] +static DEVS_HASH: DevMapHash = DevMapHash::with_max_entries(1, 0); +#[map] +static CPUS: CpuMap = CpuMap::with_max_entries(1, 0); + +/// Hits of a probe, used to test program chaining through CpuMap/DevMap. +/// The first slot counts how many times the "raw" xdp program got executed, while the second slot +/// counts how many times the map programs got executed. +/// This allows the test harness to assert that a specific step got executed. +#[map] +static mut HITS: Array = Array::with_max_entries(2, 0); + +#[xdp] +pub fn redirect_sock(_ctx: XdpContext) -> u32 { + SOCKS.redirect(0, 0).unwrap_or(xdp_action::XDP_ABORTED) +} + +#[xdp] +pub fn redirect_dev(_ctx: XdpContext) -> u32 { + inc_hit(0); + DEVS.redirect(0, 0).unwrap_or(xdp_action::XDP_ABORTED) +} + +#[xdp] +pub fn redirect_dev_hash(_ctx: XdpContext) -> u32 { + inc_hit(0); + DEVS_HASH.redirect(10, 0).unwrap_or(xdp_action::XDP_ABORTED) +} + +#[xdp] +pub fn redirect_cpu(_ctx: XdpContext) -> u32 { + inc_hit(0); + CPUS.redirect(0, 0).unwrap_or(xdp_action::XDP_ABORTED) +} + +#[xdp(map = "cpumap")] +pub fn redirect_cpu_chain(_ctx: XdpContext) -> u32 { + inc_hit(1); + xdp_action::XDP_PASS +} + +#[xdp(map = "devmap")] +pub fn redirect_dev_chain(_ctx: XdpContext) -> u32 { + inc_hit(1); + xdp_action::XDP_PASS +} + +#[inline(always)] +fn inc_hit(index: u32) { + if let Some(hit) = unsafe { HITS.get_ptr_mut(index) } { + unsafe { *hit += 1 }; + } +} + +#[cfg(not(test))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/test/integration-ebpf/src/xdp_sec.rs b/test/integration-ebpf/src/xdp_sec.rs new file mode 100644 index 00000000..5e64f56a --- /dev/null +++ b/test/integration-ebpf/src/xdp_sec.rs @@ -0,0 +1,26 @@ +#![no_std] +#![no_main] + +use aya_bpf::{bindings::xdp_action::XDP_PASS, macros::xdp, programs::XdpContext}; + +macro_rules! probe { + ($name:ident, ($($arg:ident $(= $value:literal)?),*) ) => { + #[xdp($($arg $(= $value)?),*)] + pub fn $name(_ctx: XdpContext) -> u32 { + XDP_PASS + } + }; +} + +probe!(xdp_plain, ()); +probe!(xdp_frags, (frags)); +probe!(xdp_cpumap, (map = "cpumap")); +probe!(xdp_devmap, (map = "devmap")); +probe!(xdp_frags_cpumap, (frags, map = "cpumap")); +probe!(xdp_frags_devmap, (frags, map = "devmap")); + +#[cfg(not(test))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/test/integration-test/bpf/multimap-btf.bpf.c b/test/integration-test/bpf/multimap-btf.bpf.c index 2bd7978b..f6d34bcf 100644 --- a/test/integration-test/bpf/multimap-btf.bpf.c +++ b/test/integration-test/bpf/multimap-btf.bpf.c @@ -17,7 +17,7 @@ struct { __uint(max_entries, 1); } map_2 SEC(".maps"); -SEC("tracepoint") +SEC("uprobe") int bpf_prog(void *ctx) { __u32 key = 0; __u64 twenty_four = 24; diff --git a/test/integration-test/src/lib.rs b/test/integration-test/src/lib.rs index 1c8e2f9d..6fd4049c 100644 --- a/test/integration-test/src/lib.rs +++ b/test/integration-test/src/lib.rs @@ -21,6 +21,8 @@ pub const RELOCATIONS: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), " pub const TWO_PROGS: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/two_progs")); pub const BPF_PROBE_READ: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/bpf_probe_read")); +pub const REDIRECT: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/redirect")); +pub const XDP_SEC: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/xdp_sec")); #[cfg(test)] mod tests; diff --git a/test/integration-test/src/tests.rs b/test/integration-test/src/tests.rs index b6cb63e7..f359f400 100644 --- a/test/integration-test/src/tests.rs +++ b/test/integration-test/src/tests.rs @@ -7,3 +7,4 @@ mod rbpf; mod relocations; mod smoke; mod stack_argument; +mod xdp; diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs index 0b0d1532..795f396d 100644 --- a/test/integration-test/src/tests/load.rs +++ b/test/integration-test/src/tests/load.rs @@ -1,4 +1,8 @@ -use std::{convert::TryInto as _, thread, time}; +use std::{ + convert::TryInto as _, + thread, + time::{Duration, SystemTime}, +}; use aya::{ maps::Array, @@ -9,9 +13,10 @@ use aya::{ util::KernelVersion, Bpf, }; +use aya_obj::programs::XdpAttachType; const MAX_RETRIES: usize = 100; -const RETRY_DURATION: time::Duration = time::Duration::from_millis(10); +const RETRY_DURATION: Duration = Duration::from_millis(10); #[test] fn long_name() { @@ -36,11 +41,12 @@ fn multiple_btf_maps() { let map_1: Array<_, u64> = bpf.take_map("map_1").unwrap().try_into().unwrap(); let map_2: Array<_, u64> = bpf.take_map("map_2").unwrap().try_into().unwrap(); - let prog: &mut TracePoint = bpf.program_mut("bpf_prog").unwrap().try_into().unwrap(); + let prog: &mut UProbe = bpf.program_mut("bpf_prog").unwrap().try_into().unwrap(); prog.load().unwrap(); - prog.attach("sched", "sched_switch").unwrap(); + prog.attach(Some("trigger_bpf_program"), 0, "/proc/self/exe", None) + .unwrap(); - thread::sleep(time::Duration::from_secs(3)); + trigger_bpf_program(); let key = 0; let val_1 = map_1.get(&key, 0).unwrap(); @@ -50,6 +56,12 @@ fn multiple_btf_maps() { assert_eq!(val_2, 42); } +#[no_mangle] +#[inline(never)] +pub extern "C" fn trigger_bpf_program() { + core::hint::black_box(trigger_bpf_program); +} + fn poll_loaded_program_id(name: &str) -> impl Iterator> + '_ { std::iter::once(true) .chain(std::iter::repeat(false)) @@ -138,6 +150,28 @@ fn unload_xdp() { assert_unloaded("pass"); } +#[test] +fn test_loaded_at() { + let mut bpf = Bpf::load(crate::TEST).unwrap(); + let prog: &mut Xdp = bpf.program_mut("pass").unwrap().try_into().unwrap(); + let t1 = SystemTime::now(); + prog.load().unwrap(); + let t2 = SystemTime::now(); + assert_loaded("pass"); + + let loaded_at = prog.info().unwrap().loaded_at(); + + let range = t1..t2; + assert!( + range.contains(&loaded_at), + "{range:?}.contains({loaded_at:?})" + ); + + prog.unload().unwrap(); + + assert_unloaded("pass"); +} + #[test] fn unload_kprobe() { let mut bpf = Bpf::load(crate::TEST).unwrap(); @@ -276,7 +310,7 @@ fn pin_lifecycle() { // 2. Load program from bpffs but don't attach it { - let _ = Xdp::from_pin("/sys/fs/bpf/aya-xdp-test-prog").unwrap(); + let _ = Xdp::from_pin("/sys/fs/bpf/aya-xdp-test-prog", XdpAttachType::Interface).unwrap(); } // should still be loaded since prog was pinned @@ -284,7 +318,8 @@ fn pin_lifecycle() { // 3. Load program from bpffs and attach { - let mut prog = Xdp::from_pin("/sys/fs/bpf/aya-xdp-test-prog").unwrap(); + let mut prog = + Xdp::from_pin("/sys/fs/bpf/aya-xdp-test-prog", XdpAttachType::Interface).unwrap(); let link_id = prog.attach("lo", XdpFlags::default()).unwrap(); let link = prog.take_link(link_id).unwrap(); let fd_link: FdLink = link.try_into().unwrap(); diff --git a/test/integration-test/src/tests/rbpf.rs b/test/integration-test/src/tests/rbpf.rs index 0a85adbf..3d2c0c97 100644 --- a/test/integration-test/src/tests/rbpf.rs +++ b/test/integration-test/src/tests/rbpf.rs @@ -2,7 +2,7 @@ use core::{mem::size_of, ptr::null_mut, slice::from_raw_parts}; use std::collections::HashMap; use assert_matches::assert_matches; -use aya_obj::{generated::bpf_insn, Object, ProgramSection}; +use aya_obj::{generated::bpf_insn, programs::XdpAttachType, Object, ProgramSection}; #[test] fn run_with_rbpf() { @@ -11,7 +11,10 @@ fn run_with_rbpf() { assert_eq!(object.programs.len(), 1); assert_matches!( object.programs["pass"].section, - ProgramSection::Xdp { frags: true } + ProgramSection::Xdp { + frags: true, + attach_type: XdpAttachType::Interface + } ); let instructions = &object @@ -40,7 +43,7 @@ fn use_map_with_rbpf() { assert_eq!(object.programs.len(), 1); assert_matches!( object.programs["bpf_prog"].section, - ProgramSection::TracePoint { .. } + ProgramSection::UProbe { .. } ); // Initialize maps: @@ -58,7 +61,7 @@ fn use_map_with_rbpf() { ); let map_id = if name == "map_1" { 0 } else { 1 }; - let fd = map_id as i32 | 0xCAFE00; + let fd = map_id as std::os::fd::RawFd | 0xCAFE00; maps.insert(name.to_owned(), (fd, map.clone())); unsafe { diff --git a/test/integration-test/src/tests/relocations.rs b/test/integration-test/src/tests/relocations.rs index 1b550e9f..9e7d5719 100644 --- a/test/integration-test/src/tests/relocations.rs +++ b/test/integration-test/src/tests/relocations.rs @@ -1,5 +1,3 @@ -use std::time::Duration; - use aya::{programs::UProbe, Bpf}; #[test] @@ -7,7 +5,6 @@ fn relocations() { let bpf = load_and_attach("test_64_32_call_relocs", crate::RELOCATIONS); trigger_relocations_program(); - std::thread::sleep(Duration::from_millis(100)); let m = aya::maps::Array::<_, u64>::try_from(bpf.map("RESULTS").unwrap()).unwrap(); assert_eq!(m.get(&0, 0).unwrap(), 1); @@ -24,7 +21,6 @@ fn text_64_64_reloc() { m.set(1, 2, 0).unwrap(); trigger_relocations_program(); - std::thread::sleep(Duration::from_millis(100)); assert_eq!(m.get(&0, 0).unwrap(), 2); assert_eq!(m.get(&1, 0).unwrap(), 3); diff --git a/test/integration-test/src/tests/xdp.rs b/test/integration-test/src/tests/xdp.rs new file mode 100644 index 00000000..88423fe9 --- /dev/null +++ b/test/integration-test/src/tests/xdp.rs @@ -0,0 +1,98 @@ +use std::{net::UdpSocket, time::Duration}; + +use aya::{ + maps::{Array, CpuMap}, + programs::{Xdp, XdpFlags}, + Bpf, +}; +use object::{Object, ObjectSection, ObjectSymbol, SymbolSection}; + +use crate::utils::NetNsGuard; + +#[test] +fn prog_sections() { + let obj_file = object::File::parse(crate::XDP_SEC).unwrap(); + + ensure_symbol(&obj_file, "xdp", "xdp_plain"); + ensure_symbol(&obj_file, "xdp.frags", "xdp_frags"); + ensure_symbol(&obj_file, "xdp/cpumap", "xdp_cpumap"); + ensure_symbol(&obj_file, "xdp/devmap", "xdp_devmap"); + ensure_symbol(&obj_file, "xdp.frags/cpumap", "xdp_frags_cpumap"); + ensure_symbol(&obj_file, "xdp.frags/devmap", "xdp_frags_devmap"); +} + +#[track_caller] +fn ensure_symbol(obj_file: &object::File, sec_name: &str, sym_name: &str) { + let sec = obj_file.section_by_name(sec_name).unwrap_or_else(|| { + let secs = obj_file + .sections() + .flat_map(|sec| sec.name().ok().map(|name| name.to_owned())) + .collect::>(); + panic!("section {sec_name} not found. available sections: {secs:?}"); + }); + let sec = SymbolSection::Section(sec.index()); + + let syms = obj_file + .symbols() + .filter(|sym| sym.section() == sec) + .filter_map(|sym| sym.name().ok()) + .collect::>(); + assert!( + syms.contains(&sym_name), + "symbol not found. available symbols in section: {syms:?}" + ); +} + +#[test] +fn map_load() { + let bpf = Bpf::load(crate::XDP_SEC).unwrap(); + + bpf.program("xdp_plain").unwrap(); + bpf.program("xdp_frags").unwrap(); + bpf.program("xdp_cpumap").unwrap(); + bpf.program("xdp_devmap").unwrap(); + bpf.program("xdp_frags_cpumap").unwrap(); + bpf.program("xdp_frags_devmap").unwrap(); +} + +#[test] +fn cpumap_chain() { + let _netns = NetNsGuard::new(); + + let mut bpf = Bpf::load(crate::REDIRECT).unwrap(); + + // Load our cpumap and our canary map + let mut cpus: CpuMap<_> = bpf.take_map("CPUS").unwrap().try_into().unwrap(); + let hits: Array<_, u32> = bpf.take_map("HITS").unwrap().try_into().unwrap(); + + let xdp_chain_fd = { + // Load the chained program to run on the target CPU + let xdp: &mut Xdp = bpf + .program_mut("redirect_cpu_chain") + .unwrap() + .try_into() + .unwrap(); + xdp.load().unwrap(); + xdp.fd().unwrap() + }; + cpus.set(0, 2048, Some(xdp_chain_fd), 0).unwrap(); + + // Load the main program + let xdp: &mut Xdp = bpf.program_mut("redirect_cpu").unwrap().try_into().unwrap(); + xdp.load().unwrap(); + xdp.attach("lo", XdpFlags::default()).unwrap(); + + let sock = UdpSocket::bind("127.0.0.1:1777").unwrap(); + sock.set_read_timeout(Some(Duration::from_millis(1))) + .unwrap(); + sock.send_to(b"hello cpumap", "127.0.0.1:1777").unwrap(); + + // Read back the packet to ensure it wenth through the entire network stack, including our two + // probes. + let mut buf = vec![0u8; 1000]; + let n = sock.recv(&mut buf).unwrap(); + + assert_eq!(&buf[..n], b"hello cpumap"); + assert_eq!(hits.get(&0, 0).unwrap(), 1); + assert_eq!(hits.get(&1, 0).unwrap(), 1); +} diff --git a/xtask/public-api/aya-bpf.txt b/xtask/public-api/aya-bpf.txt index 4d4aa0f7..e221d2cc 100644 --- a/xtask/public-api/aya-bpf.txt +++ b/xtask/public-api/aya-bpf.txt @@ -563,6 +563,114 @@ impl core::borrow::BorrowMut for aya_bpf::maps::stack_trace::StackTrace wh pub fn aya_bpf::maps::stack_trace::StackTrace::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya_bpf::maps::stack_trace::StackTrace pub fn aya_bpf::maps::stack_trace::StackTrace::from(t: T) -> T +pub mod aya_bpf::maps::xdp +#[repr(transparent)] pub struct aya_bpf::maps::xdp::CpuMap +impl aya_bpf::maps::CpuMap +pub const fn aya_bpf::maps::CpuMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap +pub fn aya_bpf::maps::CpuMap::redirect(&self, index: u32, flags: u64) -> core::result::Result +pub const fn aya_bpf::maps::CpuMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap +impl core::marker::Sync for aya_bpf::maps::CpuMap +impl core::marker::Send for aya_bpf::maps::CpuMap +impl core::marker::Unpin for aya_bpf::maps::CpuMap +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::CpuMap +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::CpuMap +impl core::convert::Into for aya_bpf::maps::CpuMap where U: core::convert::From +pub fn aya_bpf::maps::CpuMap::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::CpuMap where U: core::convert::Into +pub type aya_bpf::maps::CpuMap::Error = core::convert::Infallible +pub fn aya_bpf::maps::CpuMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::CpuMap where U: core::convert::TryFrom +pub type aya_bpf::maps::CpuMap::Error = >::Error +pub fn aya_bpf::maps::CpuMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::CpuMap where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::CpuMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::CpuMap where T: core::marker::Sized +pub fn aya_bpf::maps::CpuMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::CpuMap where T: core::marker::Sized +pub fn aya_bpf::maps::CpuMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::CpuMap +pub fn aya_bpf::maps::CpuMap::from(t: T) -> T +#[repr(transparent)] pub struct aya_bpf::maps::xdp::DevMap +impl aya_bpf::maps::DevMap +pub fn aya_bpf::maps::DevMap::get(&self, index: u32) -> core::option::Option +pub const fn aya_bpf::maps::DevMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap +pub fn aya_bpf::maps::DevMap::redirect(&self, index: u32, flags: u64) -> core::result::Result +pub const fn aya_bpf::maps::DevMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap +impl core::marker::Sync for aya_bpf::maps::DevMap +impl core::marker::Send for aya_bpf::maps::DevMap +impl core::marker::Unpin for aya_bpf::maps::DevMap +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::DevMap +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::DevMap +impl core::convert::Into for aya_bpf::maps::DevMap where U: core::convert::From +pub fn aya_bpf::maps::DevMap::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::DevMap where U: core::convert::Into +pub type aya_bpf::maps::DevMap::Error = core::convert::Infallible +pub fn aya_bpf::maps::DevMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::DevMap where U: core::convert::TryFrom +pub type aya_bpf::maps::DevMap::Error = >::Error +pub fn aya_bpf::maps::DevMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::DevMap where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::DevMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::DevMap where T: core::marker::Sized +pub fn aya_bpf::maps::DevMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::DevMap where T: core::marker::Sized +pub fn aya_bpf::maps::DevMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::DevMap +pub fn aya_bpf::maps::DevMap::from(t: T) -> T +#[repr(transparent)] pub struct aya_bpf::maps::xdp::DevMapHash +impl aya_bpf::maps::DevMapHash +pub fn aya_bpf::maps::DevMapHash::get(&self, key: u32) -> core::option::Option +pub const fn aya_bpf::maps::DevMapHash::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash +pub fn aya_bpf::maps::DevMapHash::redirect(&self, key: u32, flags: u64) -> core::result::Result +pub const fn aya_bpf::maps::DevMapHash::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash +impl core::marker::Sync for aya_bpf::maps::DevMapHash +impl core::marker::Send for aya_bpf::maps::DevMapHash +impl core::marker::Unpin for aya_bpf::maps::DevMapHash +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::DevMapHash +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::DevMapHash +impl core::convert::Into for aya_bpf::maps::DevMapHash where U: core::convert::From +pub fn aya_bpf::maps::DevMapHash::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::DevMapHash where U: core::convert::Into +pub type aya_bpf::maps::DevMapHash::Error = core::convert::Infallible +pub fn aya_bpf::maps::DevMapHash::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::DevMapHash where U: core::convert::TryFrom +pub type aya_bpf::maps::DevMapHash::Error = >::Error +pub fn aya_bpf::maps::DevMapHash::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::DevMapHash where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::DevMapHash::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::DevMapHash where T: core::marker::Sized +pub fn aya_bpf::maps::DevMapHash::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::DevMapHash where T: core::marker::Sized +pub fn aya_bpf::maps::DevMapHash::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::DevMapHash +pub fn aya_bpf::maps::DevMapHash::from(t: T) -> T +#[repr(transparent)] pub struct aya_bpf::maps::xdp::XskMap +impl aya_bpf::maps::XskMap +pub fn aya_bpf::maps::XskMap::get(&self, index: u32) -> core::option::Option +pub const fn aya_bpf::maps::XskMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap +pub fn aya_bpf::maps::XskMap::redirect(&self, index: u32, flags: u64) -> core::result::Result +pub const fn aya_bpf::maps::XskMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap +impl core::marker::Sync for aya_bpf::maps::XskMap +impl core::marker::Send for aya_bpf::maps::XskMap +impl core::marker::Unpin for aya_bpf::maps::XskMap +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::XskMap +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::XskMap +impl core::convert::Into for aya_bpf::maps::XskMap where U: core::convert::From +pub fn aya_bpf::maps::XskMap::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::XskMap where U: core::convert::Into +pub type aya_bpf::maps::XskMap::Error = core::convert::Infallible +pub fn aya_bpf::maps::XskMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::XskMap where U: core::convert::TryFrom +pub type aya_bpf::maps::XskMap::Error = >::Error +pub fn aya_bpf::maps::XskMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::XskMap where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::XskMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::XskMap where T: core::marker::Sized +pub fn aya_bpf::maps::XskMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::XskMap where T: core::marker::Sized +pub fn aya_bpf::maps::XskMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::XskMap +pub fn aya_bpf::maps::XskMap::from(t: T) -> T #[repr(transparent)] pub struct aya_bpf::maps::Array impl aya_bpf::maps::array::Array pub fn aya_bpf::maps::array::Array::get(&self, index: u32) -> core::option::Option<&T> @@ -618,6 +726,86 @@ impl core::borrow::BorrowMut for aya_bpf::maps::bloom_filter::BloomFilter< pub fn aya_bpf::maps::bloom_filter::BloomFilter::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya_bpf::maps::bloom_filter::BloomFilter pub fn aya_bpf::maps::bloom_filter::BloomFilter::from(t: T) -> T +#[repr(transparent)] pub struct aya_bpf::maps::CpuMap +impl aya_bpf::maps::CpuMap +pub const fn aya_bpf::maps::CpuMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap +pub fn aya_bpf::maps::CpuMap::redirect(&self, index: u32, flags: u64) -> core::result::Result +pub const fn aya_bpf::maps::CpuMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::CpuMap +impl core::marker::Sync for aya_bpf::maps::CpuMap +impl core::marker::Send for aya_bpf::maps::CpuMap +impl core::marker::Unpin for aya_bpf::maps::CpuMap +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::CpuMap +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::CpuMap +impl core::convert::Into for aya_bpf::maps::CpuMap where U: core::convert::From +pub fn aya_bpf::maps::CpuMap::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::CpuMap where U: core::convert::Into +pub type aya_bpf::maps::CpuMap::Error = core::convert::Infallible +pub fn aya_bpf::maps::CpuMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::CpuMap where U: core::convert::TryFrom +pub type aya_bpf::maps::CpuMap::Error = >::Error +pub fn aya_bpf::maps::CpuMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::CpuMap where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::CpuMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::CpuMap where T: core::marker::Sized +pub fn aya_bpf::maps::CpuMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::CpuMap where T: core::marker::Sized +pub fn aya_bpf::maps::CpuMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::CpuMap +pub fn aya_bpf::maps::CpuMap::from(t: T) -> T +#[repr(transparent)] pub struct aya_bpf::maps::DevMap +impl aya_bpf::maps::DevMap +pub fn aya_bpf::maps::DevMap::get(&self, index: u32) -> core::option::Option +pub const fn aya_bpf::maps::DevMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap +pub fn aya_bpf::maps::DevMap::redirect(&self, index: u32, flags: u64) -> core::result::Result +pub const fn aya_bpf::maps::DevMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMap +impl core::marker::Sync for aya_bpf::maps::DevMap +impl core::marker::Send for aya_bpf::maps::DevMap +impl core::marker::Unpin for aya_bpf::maps::DevMap +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::DevMap +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::DevMap +impl core::convert::Into for aya_bpf::maps::DevMap where U: core::convert::From +pub fn aya_bpf::maps::DevMap::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::DevMap where U: core::convert::Into +pub type aya_bpf::maps::DevMap::Error = core::convert::Infallible +pub fn aya_bpf::maps::DevMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::DevMap where U: core::convert::TryFrom +pub type aya_bpf::maps::DevMap::Error = >::Error +pub fn aya_bpf::maps::DevMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::DevMap where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::DevMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::DevMap where T: core::marker::Sized +pub fn aya_bpf::maps::DevMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::DevMap where T: core::marker::Sized +pub fn aya_bpf::maps::DevMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::DevMap +pub fn aya_bpf::maps::DevMap::from(t: T) -> T +#[repr(transparent)] pub struct aya_bpf::maps::DevMapHash +impl aya_bpf::maps::DevMapHash +pub fn aya_bpf::maps::DevMapHash::get(&self, key: u32) -> core::option::Option +pub const fn aya_bpf::maps::DevMapHash::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash +pub fn aya_bpf::maps::DevMapHash::redirect(&self, key: u32, flags: u64) -> core::result::Result +pub const fn aya_bpf::maps::DevMapHash::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::DevMapHash +impl core::marker::Sync for aya_bpf::maps::DevMapHash +impl core::marker::Send for aya_bpf::maps::DevMapHash +impl core::marker::Unpin for aya_bpf::maps::DevMapHash +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::DevMapHash +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::DevMapHash +impl core::convert::Into for aya_bpf::maps::DevMapHash where U: core::convert::From +pub fn aya_bpf::maps::DevMapHash::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::DevMapHash where U: core::convert::Into +pub type aya_bpf::maps::DevMapHash::Error = core::convert::Infallible +pub fn aya_bpf::maps::DevMapHash::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::DevMapHash where U: core::convert::TryFrom +pub type aya_bpf::maps::DevMapHash::Error = >::Error +pub fn aya_bpf::maps::DevMapHash::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::DevMapHash where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::DevMapHash::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::DevMapHash where T: core::marker::Sized +pub fn aya_bpf::maps::DevMapHash::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::DevMapHash where T: core::marker::Sized +pub fn aya_bpf::maps::DevMapHash::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::DevMapHash +pub fn aya_bpf::maps::DevMapHash::from(t: T) -> T #[repr(transparent)] pub struct aya_bpf::maps::HashMap impl aya_bpf::maps::hash_map::HashMap pub unsafe fn aya_bpf::maps::hash_map::HashMap::get(&self, key: &K) -> core::option::Option<&V> @@ -1014,6 +1202,33 @@ impl core::borrow::BorrowMut for aya_bpf::maps::stack_trace::StackTrace wh pub fn aya_bpf::maps::stack_trace::StackTrace::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya_bpf::maps::stack_trace::StackTrace pub fn aya_bpf::maps::stack_trace::StackTrace::from(t: T) -> T +#[repr(transparent)] pub struct aya_bpf::maps::XskMap +impl aya_bpf::maps::XskMap +pub fn aya_bpf::maps::XskMap::get(&self, index: u32) -> core::option::Option +pub const fn aya_bpf::maps::XskMap::pinned(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap +pub fn aya_bpf::maps::XskMap::redirect(&self, index: u32, flags: u64) -> core::result::Result +pub const fn aya_bpf::maps::XskMap::with_max_entries(max_entries: u32, flags: u32) -> aya_bpf::maps::XskMap +impl core::marker::Sync for aya_bpf::maps::XskMap +impl core::marker::Send for aya_bpf::maps::XskMap +impl core::marker::Unpin for aya_bpf::maps::XskMap +impl !core::panic::unwind_safe::RefUnwindSafe for aya_bpf::maps::XskMap +impl core::panic::unwind_safe::UnwindSafe for aya_bpf::maps::XskMap +impl core::convert::Into for aya_bpf::maps::XskMap where U: core::convert::From +pub fn aya_bpf::maps::XskMap::into(self) -> U +impl core::convert::TryFrom for aya_bpf::maps::XskMap where U: core::convert::Into +pub type aya_bpf::maps::XskMap::Error = core::convert::Infallible +pub fn aya_bpf::maps::XskMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_bpf::maps::XskMap where U: core::convert::TryFrom +pub type aya_bpf::maps::XskMap::Error = >::Error +pub fn aya_bpf::maps::XskMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya_bpf::maps::XskMap where T: 'static + core::marker::Sized +pub fn aya_bpf::maps::XskMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_bpf::maps::XskMap where T: core::marker::Sized +pub fn aya_bpf::maps::XskMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_bpf::maps::XskMap where T: core::marker::Sized +pub fn aya_bpf::maps::XskMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_bpf::maps::XskMap +pub fn aya_bpf::maps::XskMap::from(t: T) -> T pub mod aya_bpf::programs pub mod aya_bpf::programs::device pub struct aya_bpf::programs::device::DeviceContext diff --git a/xtask/public-api/aya-obj.txt b/xtask/public-api/aya-obj.txt index 574862f4..5c361372 100644 --- a/xtask/public-api/aya-obj.txt +++ b/xtask/public-api/aya-obj.txt @@ -1342,6 +1342,8 @@ impl core::convert::From aya_obj::generated::bpf_attach_type impl core::convert::From for aya_obj::generated::bpf_attach_type pub fn aya_obj::generated::bpf_attach_type::from(s: aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType) -> aya_obj::generated::bpf_attach_type +impl core::convert::From for aya_obj::generated::bpf_attach_type +pub fn aya_obj::generated::bpf_attach_type::from(value: aya_obj::programs::xdp::XdpAttachType) -> Self impl core::clone::Clone for aya_obj::generated::bpf_attach_type pub fn aya_obj::generated::bpf_attach_type::clone(&self) -> aya_obj::generated::bpf_attach_type impl core::cmp::Eq for aya_obj::generated::bpf_attach_type @@ -5411,6 +5413,7 @@ pub fn aya_obj::maps::Map::pinning(&self) -> aya_obj::maps::PinningType pub fn aya_obj::maps::Map::section_index(&self) -> usize pub fn aya_obj::maps::Map::section_kind(&self) -> aya_obj::BpfSectionKind pub fn aya_obj::maps::Map::set_max_entries(&mut self, v: u32) +pub fn aya_obj::maps::Map::set_value_size(&mut self, size: u32) pub fn aya_obj::maps::Map::symbol_index(&self) -> core::option::Option pub fn aya_obj::maps::Map::value_size(&self) -> u32 impl core::clone::Clone for aya_obj::maps::Map @@ -5848,6 +5851,7 @@ pub aya_obj::obj::ProgramSection::UProbe::sleepable: bool pub aya_obj::obj::ProgramSection::URetProbe pub aya_obj::obj::ProgramSection::URetProbe::sleepable: bool pub aya_obj::obj::ProgramSection::Xdp +pub aya_obj::obj::ProgramSection::Xdp::attach_type: aya_obj::programs::xdp::XdpAttachType pub aya_obj::obj::ProgramSection::Xdp::frags: bool impl core::str::traits::FromStr for aya_obj::ProgramSection pub type aya_obj::ProgramSection::Err = aya_obj::ParseError @@ -5889,6 +5893,8 @@ pub fn aya_obj::Features::bpf_name(&self) -> bool pub fn aya_obj::Features::bpf_perf_link(&self) -> bool pub fn aya_obj::Features::bpf_probe_read_kernel(&self) -> bool pub fn aya_obj::Features::btf(&self) -> core::option::Option<&aya_obj::btf::BtfFeatures> +pub fn aya_obj::Features::cpumap_prog_id(&self) -> bool +pub fn aya_obj::Features::devmap_prog_id(&self) -> bool impl core::default::Default for aya_obj::Features pub fn aya_obj::Features::default() -> aya_obj::Features impl core::fmt::Debug for aya_obj::Features @@ -5972,7 +5978,7 @@ impl aya_obj::Object pub fn aya_obj::Object::relocate_btf(&mut self, target_btf: &aya_obj::btf::Btf) -> core::result::Result<(), aya_obj::btf::BtfRelocationError> impl aya_obj::Object pub fn aya_obj::Object::relocate_calls(&mut self, text_sections: &std::collections::hash::set::HashSet) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError> -pub fn aya_obj::Object::relocate_maps<'a, I: core::iter::traits::iterator::Iterator>(&mut self, maps: I, text_sections: &std::collections::hash::set::HashSet) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError> +pub fn aya_obj::Object::relocate_maps<'a, I: core::iter::traits::iterator::Iterator>(&mut self, maps: I, text_sections: &std::collections::hash::set::HashSet) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError> impl core::clone::Clone for aya_obj::Object pub fn aya_obj::Object::clone(&self) -> aya_obj::Object impl core::fmt::Debug for aya_obj::Object @@ -6164,6 +6170,43 @@ impl core::borrow::BorrowMut for aya_obj::programs::cgroup_sockopt::Cgroup pub fn aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType pub fn aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType::from(t: T) -> T +pub mod aya_obj::programs::xdp +pub enum aya_obj::programs::xdp::XdpAttachType +pub aya_obj::programs::xdp::XdpAttachType::CpuMap +pub aya_obj::programs::xdp::XdpAttachType::DevMap +pub aya_obj::programs::xdp::XdpAttachType::Interface +impl core::convert::From for aya_obj::generated::bpf_attach_type +pub fn aya_obj::generated::bpf_attach_type::from(value: aya_obj::programs::xdp::XdpAttachType) -> Self +impl core::clone::Clone for aya_obj::programs::xdp::XdpAttachType +pub fn aya_obj::programs::xdp::XdpAttachType::clone(&self) -> aya_obj::programs::xdp::XdpAttachType +impl core::fmt::Debug for aya_obj::programs::xdp::XdpAttachType +pub fn aya_obj::programs::xdp::XdpAttachType::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::marker::Copy for aya_obj::programs::xdp::XdpAttachType +impl core::marker::Send for aya_obj::programs::xdp::XdpAttachType +impl core::marker::Sync for aya_obj::programs::xdp::XdpAttachType +impl core::marker::Unpin for aya_obj::programs::xdp::XdpAttachType +impl core::panic::unwind_safe::RefUnwindSafe for aya_obj::programs::xdp::XdpAttachType +impl core::panic::unwind_safe::UnwindSafe for aya_obj::programs::xdp::XdpAttachType +impl core::convert::Into for aya_obj::programs::xdp::XdpAttachType where U: core::convert::From +pub fn aya_obj::programs::xdp::XdpAttachType::into(self) -> U +impl core::convert::TryFrom for aya_obj::programs::xdp::XdpAttachType where U: core::convert::Into +pub type aya_obj::programs::xdp::XdpAttachType::Error = core::convert::Infallible +pub fn aya_obj::programs::xdp::XdpAttachType::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_obj::programs::xdp::XdpAttachType where U: core::convert::TryFrom +pub type aya_obj::programs::xdp::XdpAttachType::Error = >::Error +pub fn aya_obj::programs::xdp::XdpAttachType::try_into(self) -> core::result::Result>::Error> +impl alloc::borrow::ToOwned for aya_obj::programs::xdp::XdpAttachType where T: core::clone::Clone +pub type aya_obj::programs::xdp::XdpAttachType::Owned = T +pub fn aya_obj::programs::xdp::XdpAttachType::clone_into(&self, target: &mut T) +pub fn aya_obj::programs::xdp::XdpAttachType::to_owned(&self) -> T +impl core::any::Any for aya_obj::programs::xdp::XdpAttachType where T: 'static + core::marker::Sized +pub fn aya_obj::programs::xdp::XdpAttachType::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_obj::programs::xdp::XdpAttachType where T: core::marker::Sized +pub fn aya_obj::programs::xdp::XdpAttachType::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_obj::programs::xdp::XdpAttachType where T: core::marker::Sized +pub fn aya_obj::programs::xdp::XdpAttachType::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_obj::programs::xdp::XdpAttachType +pub fn aya_obj::programs::xdp::XdpAttachType::from(t: T) -> T pub enum aya_obj::programs::CgroupSockAddrAttachType pub aya_obj::programs::CgroupSockAddrAttachType::Bind4 pub aya_obj::programs::CgroupSockAddrAttachType::Bind6 @@ -6283,6 +6326,42 @@ impl core::borrow::BorrowMut for aya_obj::programs::cgroup_sockopt::Cgroup pub fn aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType pub fn aya_obj::programs::cgroup_sockopt::CgroupSockoptAttachType::from(t: T) -> T +pub enum aya_obj::programs::XdpAttachType +pub aya_obj::programs::XdpAttachType::CpuMap +pub aya_obj::programs::XdpAttachType::DevMap +pub aya_obj::programs::XdpAttachType::Interface +impl core::convert::From for aya_obj::generated::bpf_attach_type +pub fn aya_obj::generated::bpf_attach_type::from(value: aya_obj::programs::xdp::XdpAttachType) -> Self +impl core::clone::Clone for aya_obj::programs::xdp::XdpAttachType +pub fn aya_obj::programs::xdp::XdpAttachType::clone(&self) -> aya_obj::programs::xdp::XdpAttachType +impl core::fmt::Debug for aya_obj::programs::xdp::XdpAttachType +pub fn aya_obj::programs::xdp::XdpAttachType::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::marker::Copy for aya_obj::programs::xdp::XdpAttachType +impl core::marker::Send for aya_obj::programs::xdp::XdpAttachType +impl core::marker::Sync for aya_obj::programs::xdp::XdpAttachType +impl core::marker::Unpin for aya_obj::programs::xdp::XdpAttachType +impl core::panic::unwind_safe::RefUnwindSafe for aya_obj::programs::xdp::XdpAttachType +impl core::panic::unwind_safe::UnwindSafe for aya_obj::programs::xdp::XdpAttachType +impl core::convert::Into for aya_obj::programs::xdp::XdpAttachType where U: core::convert::From +pub fn aya_obj::programs::xdp::XdpAttachType::into(self) -> U +impl core::convert::TryFrom for aya_obj::programs::xdp::XdpAttachType where U: core::convert::Into +pub type aya_obj::programs::xdp::XdpAttachType::Error = core::convert::Infallible +pub fn aya_obj::programs::xdp::XdpAttachType::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya_obj::programs::xdp::XdpAttachType where U: core::convert::TryFrom +pub type aya_obj::programs::xdp::XdpAttachType::Error = >::Error +pub fn aya_obj::programs::xdp::XdpAttachType::try_into(self) -> core::result::Result>::Error> +impl alloc::borrow::ToOwned for aya_obj::programs::xdp::XdpAttachType where T: core::clone::Clone +pub type aya_obj::programs::xdp::XdpAttachType::Owned = T +pub fn aya_obj::programs::xdp::XdpAttachType::clone_into(&self, target: &mut T) +pub fn aya_obj::programs::xdp::XdpAttachType::to_owned(&self) -> T +impl core::any::Any for aya_obj::programs::xdp::XdpAttachType where T: 'static + core::marker::Sized +pub fn aya_obj::programs::xdp::XdpAttachType::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya_obj::programs::xdp::XdpAttachType where T: core::marker::Sized +pub fn aya_obj::programs::xdp::XdpAttachType::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya_obj::programs::xdp::XdpAttachType where T: core::marker::Sized +pub fn aya_obj::programs::xdp::XdpAttachType::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya_obj::programs::xdp::XdpAttachType +pub fn aya_obj::programs::xdp::XdpAttachType::from(t: T) -> T pub mod aya_obj::relocation pub enum aya_obj::relocation::RelocationError pub aya_obj::relocation::RelocationError::InvalidRelocationOffset @@ -6420,6 +6499,7 @@ pub fn aya_obj::maps::Map::pinning(&self) -> aya_obj::maps::PinningType pub fn aya_obj::maps::Map::section_index(&self) -> usize pub fn aya_obj::maps::Map::section_kind(&self) -> aya_obj::BpfSectionKind pub fn aya_obj::maps::Map::set_max_entries(&mut self, v: u32) +pub fn aya_obj::maps::Map::set_value_size(&mut self, size: u32) pub fn aya_obj::maps::Map::symbol_index(&self) -> core::option::Option pub fn aya_obj::maps::Map::value_size(&self) -> u32 impl core::clone::Clone for aya_obj::maps::Map @@ -6560,6 +6640,7 @@ pub aya_obj::ProgramSection::UProbe::sleepable: bool pub aya_obj::ProgramSection::URetProbe pub aya_obj::ProgramSection::URetProbe::sleepable: bool pub aya_obj::ProgramSection::Xdp +pub aya_obj::ProgramSection::Xdp::attach_type: aya_obj::programs::xdp::XdpAttachType pub aya_obj::ProgramSection::Xdp::frags: bool impl core::str::traits::FromStr for aya_obj::ProgramSection pub type aya_obj::ProgramSection::Err = aya_obj::ParseError @@ -6601,6 +6682,8 @@ pub fn aya_obj::Features::bpf_name(&self) -> bool pub fn aya_obj::Features::bpf_perf_link(&self) -> bool pub fn aya_obj::Features::bpf_probe_read_kernel(&self) -> bool pub fn aya_obj::Features::btf(&self) -> core::option::Option<&aya_obj::btf::BtfFeatures> +pub fn aya_obj::Features::cpumap_prog_id(&self) -> bool +pub fn aya_obj::Features::devmap_prog_id(&self) -> bool impl core::default::Default for aya_obj::Features pub fn aya_obj::Features::default() -> aya_obj::Features impl core::fmt::Debug for aya_obj::Features @@ -6684,7 +6767,7 @@ impl aya_obj::Object pub fn aya_obj::Object::relocate_btf(&mut self, target_btf: &aya_obj::btf::Btf) -> core::result::Result<(), aya_obj::btf::BtfRelocationError> impl aya_obj::Object pub fn aya_obj::Object::relocate_calls(&mut self, text_sections: &std::collections::hash::set::HashSet) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError> -pub fn aya_obj::Object::relocate_maps<'a, I: core::iter::traits::iterator::Iterator>(&mut self, maps: I, text_sections: &std::collections::hash::set::HashSet) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError> +pub fn aya_obj::Object::relocate_maps<'a, I: core::iter::traits::iterator::Iterator>(&mut self, maps: I, text_sections: &std::collections::hash::set::HashSet) -> core::result::Result<(), aya_obj::relocation::BpfRelocationError> impl core::clone::Clone for aya_obj::Object pub fn aya_obj::Object::clone(&self) -> aya_obj::Object impl core::fmt::Debug for aya_obj::Object diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index dfbdde83..86221498 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -559,7 +559,7 @@ pub fn aya::maps::queue::Queue::from(t: T) -> T pub mod aya::maps::sock pub struct aya::maps::sock::SockHash impl, K: aya::Pod> aya::maps::SockHash -pub fn aya::maps::SockHash::fd(&self) -> core::result::Result +pub fn aya::maps::SockHash::fd(&self) -> &aya::maps::sock::SockMapFd pub fn aya::maps::SockHash::get(&self, key: &K, flags: u64) -> core::result::Result pub fn aya::maps::SockHash::iter(&self) -> aya::maps::MapIter<'_, K, std::os::fd::raw::RawFd, Self> pub fn aya::maps::SockHash::keys(&self) -> aya::maps::MapKeys<'_, K> @@ -601,7 +601,7 @@ impl core::convert::From for aya::maps::SockHash pub fn aya::maps::SockHash::from(t: T) -> T pub struct aya::maps::sock::SockMap impl> aya::maps::SockMap -pub fn aya::maps::SockMap::fd(&self) -> core::result::Result +pub fn aya::maps::SockMap::fd(&self) -> &aya::maps::sock::SockMapFd pub fn aya::maps::SockMap::indices(&self) -> aya::maps::MapKeys<'_, u32> impl> aya::maps::SockMap pub fn aya::maps::SockMap::clear_index(&mut self, index: &u32) -> core::result::Result<(), aya::maps::MapError> @@ -636,12 +636,11 @@ impl core::borrow::BorrowMut for aya::maps::SockMap where T: core::mark pub fn aya::maps::SockMap::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::SockMap pub fn aya::maps::SockMap::from(t: T) -> T -pub struct aya::maps::sock::SockMapFd(_) +#[repr(transparent)] pub struct aya::maps::sock::SockMapFd(_) +impl aya::maps::sock::SockMapFd +pub fn aya::maps::sock::SockMapFd::try_clone(&self) -> std::io::error::Result impl std::os::fd::owned::AsFd for aya::maps::sock::SockMapFd pub fn aya::maps::sock::SockMapFd::as_fd(&self) -> std::os::fd::owned::BorrowedFd<'_> -impl core::clone::Clone for aya::maps::sock::SockMapFd -pub fn aya::maps::sock::SockMapFd::clone(&self) -> aya::maps::sock::SockMapFd -impl core::marker::Copy for aya::maps::sock::SockMapFd impl core::marker::Send for aya::maps::sock::SockMapFd impl core::marker::Sync for aya::maps::sock::SockMapFd impl core::marker::Unpin for aya::maps::sock::SockMapFd @@ -655,10 +654,6 @@ pub fn aya::maps::sock::SockMapFd::try_from(value: U) -> core::result::Result core::convert::TryInto for aya::maps::sock::SockMapFd where U: core::convert::TryFrom pub type aya::maps::sock::SockMapFd::Error = >::Error pub fn aya::maps::sock::SockMapFd::try_into(self) -> core::result::Result>::Error> -impl alloc::borrow::ToOwned for aya::maps::sock::SockMapFd where T: core::clone::Clone -pub type aya::maps::sock::SockMapFd::Owned = T -pub fn aya::maps::sock::SockMapFd::clone_into(&self, target: &mut T) -pub fn aya::maps::sock::SockMapFd::to_owned(&self) -> T impl core::any::Any for aya::maps::sock::SockMapFd where T: 'static + core::marker::Sized pub fn aya::maps::sock::SockMapFd::type_id(&self) -> core::any::TypeId impl core::borrow::Borrow for aya::maps::sock::SockMapFd where T: core::marker::Sized @@ -800,9 +795,194 @@ impl core::borrow::BorrowMut for aya::maps::stack_trace::StackTraceMap pub fn aya::maps::stack_trace::StackTraceMap::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::stack_trace::StackTraceMap pub fn aya::maps::stack_trace::StackTraceMap::from(t: T) -> T +pub mod aya::maps::xdp +pub enum aya::maps::xdp::XdpMapError +pub aya::maps::xdp::XdpMapError::ChainedProgramNotSupported +pub aya::maps::xdp::XdpMapError::MapError(aya::maps::MapError) +impl core::convert::From for aya::maps::xdp::XdpMapError +pub fn aya::maps::xdp::XdpMapError::from(source: aya::maps::MapError) -> Self +impl core::error::Error for aya::maps::xdp::XdpMapError +pub fn aya::maps::xdp::XdpMapError::source(&self) -> core::option::Option<&(dyn core::error::Error + 'static)> +impl core::fmt::Display for aya::maps::xdp::XdpMapError +pub fn aya::maps::xdp::XdpMapError::fmt(&self, __formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::fmt::Debug for aya::maps::xdp::XdpMapError +pub fn aya::maps::xdp::XdpMapError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result +impl core::marker::Send for aya::maps::xdp::XdpMapError +impl core::marker::Sync for aya::maps::xdp::XdpMapError +impl core::marker::Unpin for aya::maps::xdp::XdpMapError +impl !core::panic::unwind_safe::RefUnwindSafe for aya::maps::xdp::XdpMapError +impl !core::panic::unwind_safe::UnwindSafe for aya::maps::xdp::XdpMapError +impl core::convert::Into for aya::maps::xdp::XdpMapError where U: core::convert::From +pub fn aya::maps::xdp::XdpMapError::into(self) -> U +impl core::convert::TryFrom for aya::maps::xdp::XdpMapError where U: core::convert::Into +pub type aya::maps::xdp::XdpMapError::Error = core::convert::Infallible +pub fn aya::maps::xdp::XdpMapError::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::xdp::XdpMapError where U: core::convert::TryFrom +pub type aya::maps::xdp::XdpMapError::Error = >::Error +pub fn aya::maps::xdp::XdpMapError::try_into(self) -> core::result::Result>::Error> +impl alloc::string::ToString for aya::maps::xdp::XdpMapError where T: core::fmt::Display + core::marker::Sized +pub fn aya::maps::xdp::XdpMapError::to_string(&self) -> alloc::string::String +impl core::any::Any for aya::maps::xdp::XdpMapError where T: 'static + core::marker::Sized +pub fn aya::maps::xdp::XdpMapError::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::xdp::XdpMapError where T: core::marker::Sized +pub fn aya::maps::xdp::XdpMapError::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::xdp::XdpMapError where T: core::marker::Sized +pub fn aya::maps::xdp::XdpMapError::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::xdp::XdpMapError +pub fn aya::maps::xdp::XdpMapError::from(t: T) -> T +pub struct aya::maps::xdp::CpuMap +impl> aya::maps::CpuMap +pub fn aya::maps::CpuMap::get(&self, cpu_index: u32, flags: u64) -> core::result::Result +pub fn aya::maps::CpuMap::iter(&self) -> impl core::iter::traits::iterator::Iterator> + '_ +pub fn aya::maps::CpuMap::len(&self) -> u32 +impl> aya::maps::CpuMap +pub fn aya::maps::CpuMap::set(&mut self, cpu_index: u32, queue_size: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> +impl core::convert::TryFrom for aya::maps::CpuMap +pub type aya::maps::CpuMap::Error = aya::maps::MapError +pub fn aya::maps::CpuMap::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::CpuMap<&'a aya::maps::MapData> +pub type aya::maps::CpuMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::CpuMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::CpuMap<&'a mut aya::maps::MapData> +pub type aya::maps::CpuMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::CpuMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::marker::Send for aya::maps::CpuMap where T: core::marker::Send +impl core::marker::Sync for aya::maps::CpuMap where T: core::marker::Sync +impl core::marker::Unpin for aya::maps::CpuMap where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::CpuMap where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::CpuMap where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::CpuMap where U: core::convert::From +pub fn aya::maps::CpuMap::into(self) -> U +impl core::convert::TryFrom for aya::maps::CpuMap where U: core::convert::Into +pub type aya::maps::CpuMap::Error = core::convert::Infallible +pub fn aya::maps::CpuMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::CpuMap where U: core::convert::TryFrom +pub type aya::maps::CpuMap::Error = >::Error +pub fn aya::maps::CpuMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::CpuMap where T: 'static + core::marker::Sized +pub fn aya::maps::CpuMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::CpuMap where T: core::marker::Sized +pub fn aya::maps::CpuMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::CpuMap where T: core::marker::Sized +pub fn aya::maps::CpuMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::CpuMap +pub fn aya::maps::CpuMap::from(t: T) -> T +pub struct aya::maps::xdp::DevMap +impl> aya::maps::DevMap +pub fn aya::maps::DevMap::get(&self, index: u32, flags: u64) -> core::result::Result +pub fn aya::maps::DevMap::iter(&self) -> impl core::iter::traits::iterator::Iterator> + '_ +pub fn aya::maps::DevMap::len(&self) -> u32 +impl> aya::maps::DevMap +pub fn aya::maps::DevMap::set(&mut self, index: u32, target_if_index: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> +impl core::convert::TryFrom for aya::maps::DevMap +pub type aya::maps::DevMap::Error = aya::maps::MapError +pub fn aya::maps::DevMap::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::DevMap<&'a aya::maps::MapData> +pub type aya::maps::DevMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::DevMap<&'a mut aya::maps::MapData> +pub type aya::maps::DevMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::marker::Send for aya::maps::DevMap where T: core::marker::Send +impl core::marker::Sync for aya::maps::DevMap where T: core::marker::Sync +impl core::marker::Unpin for aya::maps::DevMap where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::DevMap where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::DevMap where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::DevMap where U: core::convert::From +pub fn aya::maps::DevMap::into(self) -> U +impl core::convert::TryFrom for aya::maps::DevMap where U: core::convert::Into +pub type aya::maps::DevMap::Error = core::convert::Infallible +pub fn aya::maps::DevMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::DevMap where U: core::convert::TryFrom +pub type aya::maps::DevMap::Error = >::Error +pub fn aya::maps::DevMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::DevMap where T: 'static + core::marker::Sized +pub fn aya::maps::DevMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::DevMap where T: core::marker::Sized +pub fn aya::maps::DevMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::DevMap where T: core::marker::Sized +pub fn aya::maps::DevMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::DevMap +pub fn aya::maps::DevMap::from(t: T) -> T +pub struct aya::maps::xdp::DevMapHash +impl> aya::maps::DevMapHash +pub fn aya::maps::DevMapHash::get(&self, key: u32, flags: u64) -> core::result::Result +pub fn aya::maps::DevMapHash::iter(&self) -> aya::maps::MapIter<'_, u32, DevMapValue, Self> +pub fn aya::maps::DevMapHash::keys(&self) -> aya::maps::MapKeys<'_, u32> +impl> aya::maps::DevMapHash +pub fn aya::maps::DevMapHash::insert(&mut self, key: u32, target_if_index: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> +pub fn aya::maps::DevMapHash::remove(&mut self, key: u32) -> core::result::Result<(), aya::maps::MapError> +impl core::convert::TryFrom for aya::maps::DevMapHash +pub type aya::maps::DevMapHash::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::DevMapHash<&'a aya::maps::MapData> +pub type aya::maps::DevMapHash<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::DevMapHash<&'a mut aya::maps::MapData> +pub type aya::maps::DevMapHash<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::marker::Send for aya::maps::DevMapHash where T: core::marker::Send +impl core::marker::Sync for aya::maps::DevMapHash where T: core::marker::Sync +impl core::marker::Unpin for aya::maps::DevMapHash where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::DevMapHash where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::DevMapHash where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::DevMapHash where U: core::convert::From +pub fn aya::maps::DevMapHash::into(self) -> U +impl core::convert::TryFrom for aya::maps::DevMapHash where U: core::convert::Into +pub type aya::maps::DevMapHash::Error = core::convert::Infallible +pub fn aya::maps::DevMapHash::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::DevMapHash where U: core::convert::TryFrom +pub type aya::maps::DevMapHash::Error = >::Error +pub fn aya::maps::DevMapHash::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::DevMapHash where T: 'static + core::marker::Sized +pub fn aya::maps::DevMapHash::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::DevMapHash where T: core::marker::Sized +pub fn aya::maps::DevMapHash::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::DevMapHash where T: core::marker::Sized +pub fn aya::maps::DevMapHash::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::DevMapHash +pub fn aya::maps::DevMapHash::from(t: T) -> T +pub struct aya::maps::xdp::XskMap +impl> aya::maps::XskMap +pub fn aya::maps::XskMap::len(&self) -> u32 +impl> aya::maps::XskMap +pub fn aya::maps::XskMap::set(&mut self, index: u32, socket_fd: impl std::os::fd::raw::AsRawFd, flags: u64) -> core::result::Result<(), aya::maps::MapError> +impl core::convert::TryFrom for aya::maps::XskMap +pub type aya::maps::XskMap::Error = aya::maps::MapError +pub fn aya::maps::XskMap::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::XskMap<&'a aya::maps::MapData> +pub type aya::maps::XskMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::XskMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::XskMap<&'a mut aya::maps::MapData> +pub type aya::maps::XskMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::XskMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::marker::Send for aya::maps::XskMap where T: core::marker::Send +impl core::marker::Sync for aya::maps::XskMap where T: core::marker::Sync +impl core::marker::Unpin for aya::maps::XskMap where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::XskMap where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::XskMap where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::XskMap where U: core::convert::From +pub fn aya::maps::XskMap::into(self) -> U +impl core::convert::TryFrom for aya::maps::XskMap where U: core::convert::Into +pub type aya::maps::XskMap::Error = core::convert::Infallible +pub fn aya::maps::XskMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::XskMap where U: core::convert::TryFrom +pub type aya::maps::XskMap::Error = >::Error +pub fn aya::maps::XskMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::XskMap where T: 'static + core::marker::Sized +pub fn aya::maps::XskMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::XskMap where T: core::marker::Sized +pub fn aya::maps::XskMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::XskMap where T: core::marker::Sized +pub fn aya::maps::XskMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::XskMap +pub fn aya::maps::XskMap::from(t: T) -> T pub enum aya::maps::Map pub aya::maps::Map::Array(aya::maps::MapData) pub aya::maps::Map::BloomFilter(aya::maps::MapData) +pub aya::maps::Map::CpuMap(aya::maps::MapData) +pub aya::maps::Map::DevMap(aya::maps::MapData) +pub aya::maps::Map::DevMapHash(aya::maps::MapData) pub aya::maps::Map::HashMap(aya::maps::MapData) pub aya::maps::Map::LpmTrie(aya::maps::MapData) pub aya::maps::Map::LruHashMap(aya::maps::MapData) @@ -817,12 +997,25 @@ pub aya::maps::Map::SockMap(aya::maps::MapData) pub aya::maps::Map::Stack(aya::maps::MapData) pub aya::maps::Map::StackTraceMap(aya::maps::MapData) pub aya::maps::Map::Unsupported(aya::maps::MapData) +pub aya::maps::Map::XskMap(aya::maps::MapData) +impl core::convert::TryFrom for aya::maps::CpuMap +pub type aya::maps::CpuMap::Error = aya::maps::MapError +pub fn aya::maps::CpuMap::try_from(map: aya::maps::Map) -> core::result::Result +impl core::convert::TryFrom for aya::maps::DevMap +pub type aya::maps::DevMap::Error = aya::maps::MapError +pub fn aya::maps::DevMap::try_from(map: aya::maps::Map) -> core::result::Result +impl core::convert::TryFrom for aya::maps::DevMapHash +pub type aya::maps::DevMapHash::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::ProgramArray pub type aya::maps::ProgramArray::Error = aya::maps::MapError pub fn aya::maps::ProgramArray::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::SockMap pub type aya::maps::SockMap::Error = aya::maps::MapError pub fn aya::maps::SockMap::try_from(map: aya::maps::Map) -> core::result::Result +impl core::convert::TryFrom for aya::maps::XskMap +pub type aya::maps::XskMap::Error = aya::maps::MapError +pub fn aya::maps::XskMap::try_from(map: aya::maps::Map) -> core::result::Result impl core::convert::TryFrom for aya::maps::perf::AsyncPerfEventArray pub type aya::maps::perf::AsyncPerfEventArray::Error = aya::maps::MapError pub fn aya::maps::perf::AsyncPerfEventArray::try_from(map: aya::maps::Map) -> core::result::Result @@ -886,12 +1079,24 @@ pub fn aya::maps::queue::Queue<&'a mut aya::maps::MapData, V>::try_from(map: &'a impl<'a, V: aya::Pod> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::stack::Stack<&'a mut aya::maps::MapData, V> pub type aya::maps::stack::Stack<&'a mut aya::maps::MapData, V>::Error = aya::maps::MapError pub fn aya::maps::stack::Stack<&'a mut aya::maps::MapData, V>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::CpuMap<&'a aya::maps::MapData> +pub type aya::maps::CpuMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::CpuMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::DevMap<&'a aya::maps::MapData> +pub type aya::maps::DevMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::DevMapHash<&'a aya::maps::MapData> +pub type aya::maps::DevMapHash<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::ProgramArray<&'a aya::maps::MapData> pub type aya::maps::ProgramArray<&'a aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::ProgramArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::SockMap<&'a aya::maps::MapData> pub type aya::maps::SockMap<&'a aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::SockMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::XskMap<&'a aya::maps::MapData> +pub type aya::maps::XskMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::XskMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData> pub type aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::perf::AsyncPerfEventArray<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result @@ -901,12 +1106,24 @@ pub fn aya::maps::perf::PerfEventArray<&'a aya::maps::MapData>::try_from(map: &' impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData> pub type aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::stack_trace::StackTraceMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::CpuMap<&'a mut aya::maps::MapData> +pub type aya::maps::CpuMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::CpuMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::DevMap<&'a mut aya::maps::MapData> +pub type aya::maps::DevMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::DevMapHash<&'a mut aya::maps::MapData> +pub type aya::maps::DevMapHash<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::ProgramArray<&'a mut aya::maps::MapData> pub type aya::maps::ProgramArray<&'a mut aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::ProgramArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::SockMap<&'a mut aya::maps::MapData> pub type aya::maps::SockMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::SockMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::XskMap<&'a mut aya::maps::MapData> +pub type aya::maps::XskMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::XskMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData> pub type aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData>::Error = aya::maps::MapError pub fn aya::maps::perf::AsyncPerfEventArray<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result @@ -989,12 +1206,15 @@ pub aya::maps::MapError::OutOfBounds::max_entries: u32 pub aya::maps::MapError::PinError pub aya::maps::MapError::PinError::error: aya::pin::PinError pub aya::maps::MapError::PinError::name: core::option::Option +pub aya::maps::MapError::ProgIdNotSupported pub aya::maps::MapError::ProgramNotLoaded pub aya::maps::MapError::SyscallError(crate::sys::SyscallError) pub aya::maps::MapError::Unsupported pub aya::maps::MapError::Unsupported::map_type: u32 impl core::convert::From for aya::BpfError pub fn aya::BpfError::from(source: aya::maps::MapError) -> Self +impl core::convert::From for aya::maps::xdp::XdpMapError +pub fn aya::maps::xdp::XdpMapError::from(source: aya::maps::MapError) -> Self impl core::convert::From for aya::programs::ProgramError pub fn aya::programs::ProgramError::from(source: aya::maps::MapError) -> Self impl core::error::Error for aya::maps::MapError @@ -1136,6 +1356,118 @@ impl core::borrow::BorrowMut for aya::maps::bloom_filter::BloomFilter::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::bloom_filter::BloomFilter pub fn aya::maps::bloom_filter::BloomFilter::from(t: T) -> T +pub struct aya::maps::CpuMap +impl> aya::maps::CpuMap +pub fn aya::maps::CpuMap::get(&self, cpu_index: u32, flags: u64) -> core::result::Result +pub fn aya::maps::CpuMap::iter(&self) -> impl core::iter::traits::iterator::Iterator> + '_ +pub fn aya::maps::CpuMap::len(&self) -> u32 +impl> aya::maps::CpuMap +pub fn aya::maps::CpuMap::set(&mut self, cpu_index: u32, queue_size: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> +impl core::convert::TryFrom for aya::maps::CpuMap +pub type aya::maps::CpuMap::Error = aya::maps::MapError +pub fn aya::maps::CpuMap::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::CpuMap<&'a aya::maps::MapData> +pub type aya::maps::CpuMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::CpuMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::CpuMap<&'a mut aya::maps::MapData> +pub type aya::maps::CpuMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::CpuMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::marker::Send for aya::maps::CpuMap where T: core::marker::Send +impl core::marker::Sync for aya::maps::CpuMap where T: core::marker::Sync +impl core::marker::Unpin for aya::maps::CpuMap where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::CpuMap where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::CpuMap where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::CpuMap where U: core::convert::From +pub fn aya::maps::CpuMap::into(self) -> U +impl core::convert::TryFrom for aya::maps::CpuMap where U: core::convert::Into +pub type aya::maps::CpuMap::Error = core::convert::Infallible +pub fn aya::maps::CpuMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::CpuMap where U: core::convert::TryFrom +pub type aya::maps::CpuMap::Error = >::Error +pub fn aya::maps::CpuMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::CpuMap where T: 'static + core::marker::Sized +pub fn aya::maps::CpuMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::CpuMap where T: core::marker::Sized +pub fn aya::maps::CpuMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::CpuMap where T: core::marker::Sized +pub fn aya::maps::CpuMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::CpuMap +pub fn aya::maps::CpuMap::from(t: T) -> T +pub struct aya::maps::DevMap +impl> aya::maps::DevMap +pub fn aya::maps::DevMap::get(&self, index: u32, flags: u64) -> core::result::Result +pub fn aya::maps::DevMap::iter(&self) -> impl core::iter::traits::iterator::Iterator> + '_ +pub fn aya::maps::DevMap::len(&self) -> u32 +impl> aya::maps::DevMap +pub fn aya::maps::DevMap::set(&mut self, index: u32, target_if_index: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> +impl core::convert::TryFrom for aya::maps::DevMap +pub type aya::maps::DevMap::Error = aya::maps::MapError +pub fn aya::maps::DevMap::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::DevMap<&'a aya::maps::MapData> +pub type aya::maps::DevMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::DevMap<&'a mut aya::maps::MapData> +pub type aya::maps::DevMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::marker::Send for aya::maps::DevMap where T: core::marker::Send +impl core::marker::Sync for aya::maps::DevMap where T: core::marker::Sync +impl core::marker::Unpin for aya::maps::DevMap where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::DevMap where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::DevMap where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::DevMap where U: core::convert::From +pub fn aya::maps::DevMap::into(self) -> U +impl core::convert::TryFrom for aya::maps::DevMap where U: core::convert::Into +pub type aya::maps::DevMap::Error = core::convert::Infallible +pub fn aya::maps::DevMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::DevMap where U: core::convert::TryFrom +pub type aya::maps::DevMap::Error = >::Error +pub fn aya::maps::DevMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::DevMap where T: 'static + core::marker::Sized +pub fn aya::maps::DevMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::DevMap where T: core::marker::Sized +pub fn aya::maps::DevMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::DevMap where T: core::marker::Sized +pub fn aya::maps::DevMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::DevMap +pub fn aya::maps::DevMap::from(t: T) -> T +pub struct aya::maps::DevMapHash +impl> aya::maps::DevMapHash +pub fn aya::maps::DevMapHash::get(&self, key: u32, flags: u64) -> core::result::Result +pub fn aya::maps::DevMapHash::iter(&self) -> aya::maps::MapIter<'_, u32, DevMapValue, Self> +pub fn aya::maps::DevMapHash::keys(&self) -> aya::maps::MapKeys<'_, u32> +impl> aya::maps::DevMapHash +pub fn aya::maps::DevMapHash::insert(&mut self, key: u32, target_if_index: u32, program: core::option::Option<&aya::programs::ProgramFd>, flags: u64) -> core::result::Result<(), aya::maps::xdp::XdpMapError> +pub fn aya::maps::DevMapHash::remove(&mut self, key: u32) -> core::result::Result<(), aya::maps::MapError> +impl core::convert::TryFrom for aya::maps::DevMapHash +pub type aya::maps::DevMapHash::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::DevMapHash<&'a aya::maps::MapData> +pub type aya::maps::DevMapHash<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::DevMapHash<&'a mut aya::maps::MapData> +pub type aya::maps::DevMapHash<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::DevMapHash<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::marker::Send for aya::maps::DevMapHash where T: core::marker::Send +impl core::marker::Sync for aya::maps::DevMapHash where T: core::marker::Sync +impl core::marker::Unpin for aya::maps::DevMapHash where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::DevMapHash where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::DevMapHash where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::DevMapHash where U: core::convert::From +pub fn aya::maps::DevMapHash::into(self) -> U +impl core::convert::TryFrom for aya::maps::DevMapHash where U: core::convert::Into +pub type aya::maps::DevMapHash::Error = core::convert::Infallible +pub fn aya::maps::DevMapHash::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::DevMapHash where U: core::convert::TryFrom +pub type aya::maps::DevMapHash::Error = >::Error +pub fn aya::maps::DevMapHash::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::DevMapHash where T: 'static + core::marker::Sized +pub fn aya::maps::DevMapHash::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::DevMapHash where T: core::marker::Sized +pub fn aya::maps::DevMapHash::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::DevMapHash where T: core::marker::Sized +pub fn aya::maps::DevMapHash::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::DevMapHash +pub fn aya::maps::DevMapHash::from(t: T) -> T pub struct aya::maps::HashMap impl, K: aya::Pod, V: aya::Pod> aya::maps::hash_map::HashMap pub fn aya::maps::hash_map::HashMap::get(&self, key: &K, flags: u64) -> core::result::Result @@ -1223,16 +1555,12 @@ pub fn aya::maps::lpm_trie::LpmTrie::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::lpm_trie::LpmTrie pub fn aya::maps::lpm_trie::LpmTrie::from(t: T) -> T pub struct aya::maps::MapData -pub aya::maps::MapData::pinned: bool impl aya::maps::MapData pub fn aya::maps::MapData::create(obj: aya_obj::maps::Map, name: &str, btf_fd: core::option::Option>) -> core::result::Result -pub fn aya::maps::MapData::fd(&self) -> aya::maps::MapFd +pub fn aya::maps::MapData::fd(&self) -> &aya::maps::MapFd pub fn aya::maps::MapData::from_fd(fd: std::os::fd::owned::OwnedFd) -> core::result::Result pub fn aya::maps::MapData::from_pin>(path: P) -> core::result::Result -impl core::clone::Clone for aya::maps::MapData -pub fn aya::maps::MapData::clone(&self) -> Self -impl core::ops::drop::Drop for aya::maps::MapData -pub fn aya::maps::MapData::drop(&mut self) +pub fn aya::maps::MapData::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> impl core::fmt::Debug for aya::maps::MapData pub fn aya::maps::MapData::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::marker::Send for aya::maps::MapData @@ -1248,10 +1576,6 @@ pub fn aya::maps::MapData::try_from(value: U) -> core::result::Result core::convert::TryInto for aya::maps::MapData where U: core::convert::TryFrom pub type aya::maps::MapData::Error = >::Error pub fn aya::maps::MapData::try_into(self) -> core::result::Result>::Error> -impl alloc::borrow::ToOwned for aya::maps::MapData where T: core::clone::Clone -pub type aya::maps::MapData::Owned = T -pub fn aya::maps::MapData::clone_into(&self, target: &mut T) -pub fn aya::maps::MapData::to_owned(&self) -> T impl core::any::Any for aya::maps::MapData where T: 'static + core::marker::Sized pub fn aya::maps::MapData::type_id(&self) -> core::any::TypeId impl core::borrow::Borrow for aya::maps::MapData where T: core::marker::Sized @@ -1261,8 +1585,10 @@ pub fn aya::maps::MapData::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::MapData pub fn aya::maps::MapData::from(t: T) -> T pub struct aya::maps::MapFd(_) -impl std::os::fd::raw::AsRawFd for aya::maps::MapFd -pub fn aya::maps::MapFd::as_raw_fd(&self) -> std::os::fd::raw::RawFd +impl std::os::fd::owned::AsFd for aya::maps::MapFd +pub fn aya::maps::MapFd::as_fd(&self) -> std::os::fd::owned::BorrowedFd<'_> +impl core::fmt::Debug for aya::maps::MapFd +pub fn aya::maps::MapFd::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::marker::Send for aya::maps::MapFd impl core::marker::Sync for aya::maps::MapFd impl core::marker::Unpin for aya::maps::MapFd @@ -1566,7 +1892,7 @@ impl core::convert::From for aya::maps::queue::Queue pub fn aya::maps::queue::Queue::from(t: T) -> T pub struct aya::maps::SockHash impl, K: aya::Pod> aya::maps::SockHash -pub fn aya::maps::SockHash::fd(&self) -> core::result::Result +pub fn aya::maps::SockHash::fd(&self) -> &aya::maps::sock::SockMapFd pub fn aya::maps::SockHash::get(&self, key: &K, flags: u64) -> core::result::Result pub fn aya::maps::SockHash::iter(&self) -> aya::maps::MapIter<'_, K, std::os::fd::raw::RawFd, Self> pub fn aya::maps::SockHash::keys(&self) -> aya::maps::MapKeys<'_, K> @@ -1608,7 +1934,7 @@ impl core::convert::From for aya::maps::SockHash pub fn aya::maps::SockHash::from(t: T) -> T pub struct aya::maps::SockMap impl> aya::maps::SockMap -pub fn aya::maps::SockMap::fd(&self) -> core::result::Result +pub fn aya::maps::SockMap::fd(&self) -> &aya::maps::sock::SockMapFd pub fn aya::maps::SockMap::indices(&self) -> aya::maps::MapKeys<'_, u32> impl> aya::maps::SockMap pub fn aya::maps::SockMap::clear_index(&mut self, index: &u32) -> core::result::Result<(), aya::maps::MapError> @@ -1723,6 +2049,41 @@ impl core::borrow::BorrowMut for aya::maps::stack_trace::StackTraceMap pub fn aya::maps::stack_trace::StackTraceMap::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::maps::stack_trace::StackTraceMap pub fn aya::maps::stack_trace::StackTraceMap::from(t: T) -> T +pub struct aya::maps::XskMap +impl> aya::maps::XskMap +pub fn aya::maps::XskMap::len(&self) -> u32 +impl> aya::maps::XskMap +pub fn aya::maps::XskMap::set(&mut self, index: u32, socket_fd: impl std::os::fd::raw::AsRawFd, flags: u64) -> core::result::Result<(), aya::maps::MapError> +impl core::convert::TryFrom for aya::maps::XskMap +pub type aya::maps::XskMap::Error = aya::maps::MapError +pub fn aya::maps::XskMap::try_from(map: aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a aya::maps::Map> for aya::maps::XskMap<&'a aya::maps::MapData> +pub type aya::maps::XskMap<&'a aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::XskMap<&'a aya::maps::MapData>::try_from(map: &'a aya::maps::Map) -> core::result::Result +impl<'a> core::convert::TryFrom<&'a mut aya::maps::Map> for aya::maps::XskMap<&'a mut aya::maps::MapData> +pub type aya::maps::XskMap<&'a mut aya::maps::MapData>::Error = aya::maps::MapError +pub fn aya::maps::XskMap<&'a mut aya::maps::MapData>::try_from(map: &'a mut aya::maps::Map) -> core::result::Result +impl core::marker::Send for aya::maps::XskMap where T: core::marker::Send +impl core::marker::Sync for aya::maps::XskMap where T: core::marker::Sync +impl core::marker::Unpin for aya::maps::XskMap where T: core::marker::Unpin +impl core::panic::unwind_safe::RefUnwindSafe for aya::maps::XskMap where T: core::panic::unwind_safe::RefUnwindSafe +impl core::panic::unwind_safe::UnwindSafe for aya::maps::XskMap where T: core::panic::unwind_safe::UnwindSafe +impl core::convert::Into for aya::maps::XskMap where U: core::convert::From +pub fn aya::maps::XskMap::into(self) -> U +impl core::convert::TryFrom for aya::maps::XskMap where U: core::convert::Into +pub type aya::maps::XskMap::Error = core::convert::Infallible +pub fn aya::maps::XskMap::try_from(value: U) -> core::result::Result>::Error> +impl core::convert::TryInto for aya::maps::XskMap where U: core::convert::TryFrom +pub type aya::maps::XskMap::Error = >::Error +pub fn aya::maps::XskMap::try_into(self) -> core::result::Result>::Error> +impl core::any::Any for aya::maps::XskMap where T: 'static + core::marker::Sized +pub fn aya::maps::XskMap::type_id(&self) -> core::any::TypeId +impl core::borrow::Borrow for aya::maps::XskMap where T: core::marker::Sized +pub fn aya::maps::XskMap::borrow(&self) -> &T +impl core::borrow::BorrowMut for aya::maps::XskMap where T: core::marker::Sized +pub fn aya::maps::XskMap::borrow_mut(&mut self) -> &mut T +impl core::convert::From for aya::maps::XskMap +pub fn aya::maps::XskMap::from(t: T) -> T pub trait aya::maps::IterableMap pub fn aya::maps::IterableMap::get(&self, key: &K) -> core::result::Result pub fn aya::maps::IterableMap::map(&self) -> &aya::maps::MapData @@ -1749,8 +2110,6 @@ pub fn aya::maps::stack_trace::StackTraceMap::get(&self, index: &u32) -> core pub fn aya::maps::stack_trace::StackTraceMap::map(&self) -> &aya::maps::MapData pub mod aya::pin pub enum aya::pin::PinError -pub aya::pin::PinError::AlreadyPinned -pub aya::pin::PinError::AlreadyPinned::name: alloc::string::String pub aya::pin::PinError::InvalidPinPath pub aya::pin::PinError::InvalidPinPath::error: alloc::ffi::c_str::NulError pub aya::pin::PinError::InvalidPinPath::path: std::path::PathBuf @@ -1802,11 +2161,11 @@ pub fn aya::programs::cgroup_device::CgroupDevice::fd(&self) -> core::result::Re impl aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::from_pin>(path: P) -> core::result::Result impl aya::programs::cgroup_device::CgroupDevice +pub fn aya::programs::cgroup_device::CgroupDevice::info(&self) -> core::result::Result +impl aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_device::CgroupDevice::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_device::CgroupDevice -pub fn aya::programs::cgroup_device::CgroupDevice::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::drop(&mut self) @@ -1945,11 +2304,11 @@ pub fn aya::programs::cgroup_skb::CgroupSkb::take_link(&mut self, link_id: aya:: impl aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::cgroup_skb::CgroupSkb +pub fn aya::programs::cgroup_skb::CgroupSkb::info(&self) -> core::result::Result +impl aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_skb::CgroupSkb::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_skb::CgroupSkb -pub fn aya::programs::cgroup_skb::CgroupSkb::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::drop(&mut self) @@ -2055,11 +2414,11 @@ pub fn aya::programs::cgroup_sock::CgroupSock::take_link(&mut self, link_id: aya impl aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::cgroup_sock::CgroupSock +pub fn aya::programs::cgroup_sock::CgroupSock::info(&self) -> core::result::Result +impl aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_sock::CgroupSock::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_sock::CgroupSock -pub fn aya::programs::cgroup_sock::CgroupSock::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::drop(&mut self) @@ -2165,11 +2524,11 @@ pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::take_link(&mut self, lin impl aya::programs::cgroup_sock_addr::CgroupSockAddr pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::cgroup_sock_addr::CgroupSockAddr +pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::info(&self) -> core::result::Result +impl aya::programs::cgroup_sock_addr::CgroupSockAddr pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_sock_addr::CgroupSockAddr -pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_sock_addr::CgroupSockAddr pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_sock_addr::CgroupSockAddr pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::drop(&mut self) @@ -2275,11 +2634,11 @@ pub fn aya::programs::cgroup_sockopt::CgroupSockopt::take_link(&mut self, link_i impl aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::cgroup_sockopt::CgroupSockopt +pub fn aya::programs::cgroup_sockopt::CgroupSockopt::info(&self) -> core::result::Result +impl aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_sockopt::CgroupSockopt::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_sockopt::CgroupSockopt -pub fn aya::programs::cgroup_sockopt::CgroupSockopt::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::drop(&mut self) @@ -2385,11 +2744,11 @@ pub fn aya::programs::cgroup_sysctl::CgroupSysctl::fd(&self) -> core::result::Re impl aya::programs::cgroup_sysctl::CgroupSysctl pub fn aya::programs::cgroup_sysctl::CgroupSysctl::from_pin>(path: P) -> core::result::Result impl aya::programs::cgroup_sysctl::CgroupSysctl +pub fn aya::programs::cgroup_sysctl::CgroupSysctl::info(&self) -> core::result::Result +impl aya::programs::cgroup_sysctl::CgroupSysctl pub fn aya::programs::cgroup_sysctl::CgroupSysctl::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_sysctl::CgroupSysctl::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_sysctl::CgroupSysctl -pub fn aya::programs::cgroup_sysctl::CgroupSysctl::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_sysctl::CgroupSysctl pub fn aya::programs::cgroup_sysctl::CgroupSysctl::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_sysctl::CgroupSysctl pub fn aya::programs::cgroup_sysctl::CgroupSysctl::drop(&mut self) @@ -2528,11 +2887,11 @@ pub fn aya::programs::extension::Extension::fd(&self) -> core::result::Result<&a impl aya::programs::extension::Extension pub fn aya::programs::extension::Extension::from_pin>(path: P) -> core::result::Result impl aya::programs::extension::Extension +pub fn aya::programs::extension::Extension::info(&self) -> core::result::Result +impl aya::programs::extension::Extension pub fn aya::programs::extension::Extension::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::extension::Extension::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::extension::Extension -pub fn aya::programs::extension::Extension::program_info(&self) -> core::result::Result -impl aya::programs::extension::Extension pub fn aya::programs::extension::Extension::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::extension::Extension pub fn aya::programs::extension::Extension::drop(&mut self) @@ -2642,11 +3001,11 @@ pub fn aya::programs::fentry::FEntry::fd(&self) -> core::result::Result<&aya::pr impl aya::programs::fentry::FEntry pub fn aya::programs::fentry::FEntry::from_pin>(path: P) -> core::result::Result impl aya::programs::fentry::FEntry +pub fn aya::programs::fentry::FEntry::info(&self) -> core::result::Result +impl aya::programs::fentry::FEntry pub fn aya::programs::fentry::FEntry::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::fentry::FEntry::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::fentry::FEntry -pub fn aya::programs::fentry::FEntry::program_info(&self) -> core::result::Result -impl aya::programs::fentry::FEntry pub fn aya::programs::fentry::FEntry::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::fentry::FEntry pub fn aya::programs::fentry::FEntry::drop(&mut self) @@ -2756,11 +3115,11 @@ pub fn aya::programs::fexit::FExit::fd(&self) -> core::result::Result<&aya::prog impl aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::from_pin>(path: P) -> core::result::Result impl aya::programs::fexit::FExit +pub fn aya::programs::fexit::FExit::info(&self) -> core::result::Result +impl aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::fexit::FExit::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::fexit::FExit -pub fn aya::programs::fexit::FExit::program_info(&self) -> core::result::Result -impl aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::drop(&mut self) @@ -2905,11 +3264,11 @@ pub fn aya::programs::kprobe::KProbe::take_link(&mut self, link_id: aya::program impl aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::kprobe::KProbe +pub fn aya::programs::kprobe::KProbe::info(&self) -> core::result::Result +impl aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::kprobe::KProbe::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::kprobe::KProbe -pub fn aya::programs::kprobe::KProbe::program_info(&self) -> core::result::Result -impl aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::drop(&mut self) @@ -3405,11 +3764,11 @@ pub fn aya::programs::lirc_mode2::LircMode2::fd(&self) -> core::result::Result<& impl aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::from_pin>(path: P) -> core::result::Result impl aya::programs::lirc_mode2::LircMode2 +pub fn aya::programs::lirc_mode2::LircMode2::info(&self) -> core::result::Result +impl aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::lirc_mode2::LircMode2::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::lirc_mode2::LircMode2 -pub fn aya::programs::lirc_mode2::LircMode2::program_info(&self) -> core::result::Result -impl aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::drop(&mut self) @@ -3454,11 +3813,11 @@ pub fn aya::programs::lsm::Lsm::fd(&self) -> core::result::Result<&aya::programs impl aya::programs::lsm::Lsm pub fn aya::programs::lsm::Lsm::from_pin>(path: P) -> core::result::Result impl aya::programs::lsm::Lsm +pub fn aya::programs::lsm::Lsm::info(&self) -> core::result::Result +impl aya::programs::lsm::Lsm pub fn aya::programs::lsm::Lsm::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::lsm::Lsm::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::lsm::Lsm -pub fn aya::programs::lsm::Lsm::program_info(&self) -> core::result::Result -impl aya::programs::lsm::Lsm pub fn aya::programs::lsm::Lsm::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::lsm::Lsm pub fn aya::programs::lsm::Lsm::drop(&mut self) @@ -3741,11 +4100,11 @@ pub fn aya::programs::perf_event::PerfEvent::fd(&self) -> core::result::Result<& impl aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::from_pin>(path: P) -> core::result::Result impl aya::programs::perf_event::PerfEvent +pub fn aya::programs::perf_event::PerfEvent::info(&self) -> core::result::Result +impl aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::perf_event::PerfEvent::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::perf_event::PerfEvent -pub fn aya::programs::perf_event::PerfEvent::program_info(&self) -> core::result::Result -impl aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::drop(&mut self) @@ -3933,11 +4292,11 @@ pub fn aya::programs::tc::SchedClassifier::take_link(&mut self, link_id: aya::pr impl aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::tc::SchedClassifier +pub fn aya::programs::tc::SchedClassifier::info(&self) -> core::result::Result +impl aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::tc::SchedClassifier::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::tc::SchedClassifier -pub fn aya::programs::tc::SchedClassifier::program_info(&self) -> core::result::Result -impl aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::drop(&mut self) @@ -4075,11 +4434,11 @@ pub fn aya::programs::tp_btf::BtfTracePoint::fd(&self) -> core::result::Result<& impl aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::from_pin>(path: P) -> core::result::Result impl aya::programs::tp_btf::BtfTracePoint +pub fn aya::programs::tp_btf::BtfTracePoint::info(&self) -> core::result::Result +impl aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::tp_btf::BtfTracePoint::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::tp_btf::BtfTracePoint -pub fn aya::programs::tp_btf::BtfTracePoint::program_info(&self) -> core::result::Result -impl aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::drop(&mut self) @@ -4224,11 +4583,11 @@ pub fn aya::programs::trace_point::TracePoint::fd(&self) -> core::result::Result impl aya::programs::trace_point::TracePoint pub fn aya::programs::trace_point::TracePoint::from_pin>(path: P) -> core::result::Result impl aya::programs::trace_point::TracePoint +pub fn aya::programs::trace_point::TracePoint::info(&self) -> core::result::Result +impl aya::programs::trace_point::TracePoint pub fn aya::programs::trace_point::TracePoint::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::trace_point::TracePoint::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::trace_point::TracePoint -pub fn aya::programs::trace_point::TracePoint::program_info(&self) -> core::result::Result -impl aya::programs::trace_point::TracePoint pub fn aya::programs::trace_point::TracePoint::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::trace_point::TracePoint pub fn aya::programs::trace_point::TracePoint::drop(&mut self) @@ -4382,11 +4741,11 @@ pub fn aya::programs::uprobe::UProbe::take_link(&mut self, link_id: aya::program impl aya::programs::uprobe::UProbe pub fn aya::programs::uprobe::UProbe::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::uprobe::UProbe +pub fn aya::programs::uprobe::UProbe::info(&self) -> core::result::Result +impl aya::programs::uprobe::UProbe pub fn aya::programs::uprobe::UProbe::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::uprobe::UProbe::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::uprobe::UProbe -pub fn aya::programs::uprobe::UProbe::program_info(&self) -> core::result::Result -impl aya::programs::uprobe::UProbe pub fn aya::programs::uprobe::UProbe::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::uprobe::UProbe pub fn aya::programs::uprobe::UProbe::drop(&mut self) @@ -4527,18 +4886,17 @@ pub fn aya::programs::xdp::Xdp::attach(&mut self, interface: &str, flags: aya::p pub fn aya::programs::xdp::Xdp::attach_to_if_index(&mut self, if_index: u32, flags: aya::programs::xdp::XdpFlags) -> core::result::Result pub fn aya::programs::xdp::Xdp::attach_to_link(&mut self, link: aya::programs::xdp::XdpLink) -> core::result::Result pub fn aya::programs::xdp::Xdp::detach(&mut self, link_id: aya::programs::xdp::XdpLinkId) -> core::result::Result<(), aya::programs::ProgramError> +pub fn aya::programs::xdp::Xdp::from_pin>(path: P, attach_type: aya_obj::programs::xdp::XdpAttachType) -> core::result::Result pub fn aya::programs::xdp::Xdp::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::xdp::Xdp::take_link(&mut self, link_id: aya::programs::xdp::XdpLinkId) -> core::result::Result impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::xdp::Xdp -pub fn aya::programs::xdp::Xdp::from_pin>(path: P) -> core::result::Result +pub fn aya::programs::xdp::Xdp::info(&self) -> core::result::Result impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::xdp::Xdp::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::xdp::Xdp -pub fn aya::programs::xdp::Xdp::program_info(&self) -> core::result::Result -impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::drop(&mut self) @@ -4986,6 +5344,7 @@ pub aya::programs::Program::UProbe(aya::programs::uprobe::UProbe) pub aya::programs::Program::Xdp(aya::programs::xdp::Xdp) impl aya::programs::Program pub fn aya::programs::Program::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> +pub fn aya::programs::Program::info(&self) -> core::result::Result pub fn aya::programs::Program::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::Program::prog_type(&self) -> aya_obj::generated::linux_bindings_x86_64::bpf_prog_type pub fn aya::programs::Program::unload(self) -> core::result::Result<(), aya::programs::ProgramError> @@ -5528,11 +5887,11 @@ pub fn aya::programs::tp_btf::BtfTracePoint::fd(&self) -> core::result::Result<& impl aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::from_pin>(path: P) -> core::result::Result impl aya::programs::tp_btf::BtfTracePoint +pub fn aya::programs::tp_btf::BtfTracePoint::info(&self) -> core::result::Result +impl aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::tp_btf::BtfTracePoint::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::tp_btf::BtfTracePoint -pub fn aya::programs::tp_btf::BtfTracePoint::program_info(&self) -> core::result::Result -impl aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::tp_btf::BtfTracePoint pub fn aya::programs::tp_btf::BtfTracePoint::drop(&mut self) @@ -5576,11 +5935,11 @@ pub fn aya::programs::cgroup_device::CgroupDevice::fd(&self) -> core::result::Re impl aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::from_pin>(path: P) -> core::result::Result impl aya::programs::cgroup_device::CgroupDevice +pub fn aya::programs::cgroup_device::CgroupDevice::info(&self) -> core::result::Result +impl aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_device::CgroupDevice::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_device::CgroupDevice -pub fn aya::programs::cgroup_device::CgroupDevice::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_device::CgroupDevice pub fn aya::programs::cgroup_device::CgroupDevice::drop(&mut self) @@ -5624,11 +5983,11 @@ pub fn aya::programs::cgroup_skb::CgroupSkb::take_link(&mut self, link_id: aya:: impl aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::cgroup_skb::CgroupSkb +pub fn aya::programs::cgroup_skb::CgroupSkb::info(&self) -> core::result::Result +impl aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_skb::CgroupSkb::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_skb::CgroupSkb -pub fn aya::programs::cgroup_skb::CgroupSkb::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_skb::CgroupSkb pub fn aya::programs::cgroup_skb::CgroupSkb::drop(&mut self) @@ -5671,11 +6030,11 @@ pub fn aya::programs::cgroup_sock::CgroupSock::take_link(&mut self, link_id: aya impl aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::cgroup_sock::CgroupSock +pub fn aya::programs::cgroup_sock::CgroupSock::info(&self) -> core::result::Result +impl aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_sock::CgroupSock::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_sock::CgroupSock -pub fn aya::programs::cgroup_sock::CgroupSock::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_sock::CgroupSock pub fn aya::programs::cgroup_sock::CgroupSock::drop(&mut self) @@ -5718,11 +6077,11 @@ pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::take_link(&mut self, lin impl aya::programs::cgroup_sock_addr::CgroupSockAddr pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::cgroup_sock_addr::CgroupSockAddr +pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::info(&self) -> core::result::Result +impl aya::programs::cgroup_sock_addr::CgroupSockAddr pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_sock_addr::CgroupSockAddr -pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_sock_addr::CgroupSockAddr pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_sock_addr::CgroupSockAddr pub fn aya::programs::cgroup_sock_addr::CgroupSockAddr::drop(&mut self) @@ -5765,11 +6124,11 @@ pub fn aya::programs::cgroup_sockopt::CgroupSockopt::take_link(&mut self, link_i impl aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::cgroup_sockopt::CgroupSockopt +pub fn aya::programs::cgroup_sockopt::CgroupSockopt::info(&self) -> core::result::Result +impl aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_sockopt::CgroupSockopt::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_sockopt::CgroupSockopt -pub fn aya::programs::cgroup_sockopt::CgroupSockopt::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_sockopt::CgroupSockopt pub fn aya::programs::cgroup_sockopt::CgroupSockopt::drop(&mut self) @@ -5813,11 +6172,11 @@ pub fn aya::programs::cgroup_sysctl::CgroupSysctl::fd(&self) -> core::result::Re impl aya::programs::cgroup_sysctl::CgroupSysctl pub fn aya::programs::cgroup_sysctl::CgroupSysctl::from_pin>(path: P) -> core::result::Result impl aya::programs::cgroup_sysctl::CgroupSysctl +pub fn aya::programs::cgroup_sysctl::CgroupSysctl::info(&self) -> core::result::Result +impl aya::programs::cgroup_sysctl::CgroupSysctl pub fn aya::programs::cgroup_sysctl::CgroupSysctl::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::cgroup_sysctl::CgroupSysctl::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::cgroup_sysctl::CgroupSysctl -pub fn aya::programs::cgroup_sysctl::CgroupSysctl::program_info(&self) -> core::result::Result -impl aya::programs::cgroup_sysctl::CgroupSysctl pub fn aya::programs::cgroup_sysctl::CgroupSysctl::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::cgroup_sysctl::CgroupSysctl pub fn aya::programs::cgroup_sysctl::CgroupSysctl::drop(&mut self) @@ -5862,11 +6221,11 @@ pub fn aya::programs::extension::Extension::fd(&self) -> core::result::Result<&a impl aya::programs::extension::Extension pub fn aya::programs::extension::Extension::from_pin>(path: P) -> core::result::Result impl aya::programs::extension::Extension +pub fn aya::programs::extension::Extension::info(&self) -> core::result::Result +impl aya::programs::extension::Extension pub fn aya::programs::extension::Extension::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::extension::Extension::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::extension::Extension -pub fn aya::programs::extension::Extension::program_info(&self) -> core::result::Result -impl aya::programs::extension::Extension pub fn aya::programs::extension::Extension::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::extension::Extension pub fn aya::programs::extension::Extension::drop(&mut self) @@ -5910,11 +6269,11 @@ pub fn aya::programs::fentry::FEntry::fd(&self) -> core::result::Result<&aya::pr impl aya::programs::fentry::FEntry pub fn aya::programs::fentry::FEntry::from_pin>(path: P) -> core::result::Result impl aya::programs::fentry::FEntry +pub fn aya::programs::fentry::FEntry::info(&self) -> core::result::Result +impl aya::programs::fentry::FEntry pub fn aya::programs::fentry::FEntry::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::fentry::FEntry::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::fentry::FEntry -pub fn aya::programs::fentry::FEntry::program_info(&self) -> core::result::Result -impl aya::programs::fentry::FEntry pub fn aya::programs::fentry::FEntry::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::fentry::FEntry pub fn aya::programs::fentry::FEntry::drop(&mut self) @@ -5958,11 +6317,11 @@ pub fn aya::programs::fexit::FExit::fd(&self) -> core::result::Result<&aya::prog impl aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::from_pin>(path: P) -> core::result::Result impl aya::programs::fexit::FExit +pub fn aya::programs::fexit::FExit::info(&self) -> core::result::Result +impl aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::fexit::FExit::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::fexit::FExit -pub fn aya::programs::fexit::FExit::program_info(&self) -> core::result::Result -impl aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::fexit::FExit pub fn aya::programs::fexit::FExit::drop(&mut self) @@ -6006,11 +6365,11 @@ pub fn aya::programs::kprobe::KProbe::take_link(&mut self, link_id: aya::program impl aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::kprobe::KProbe +pub fn aya::programs::kprobe::KProbe::info(&self) -> core::result::Result +impl aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::kprobe::KProbe::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::kprobe::KProbe -pub fn aya::programs::kprobe::KProbe::program_info(&self) -> core::result::Result -impl aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::kprobe::KProbe pub fn aya::programs::kprobe::KProbe::drop(&mut self) @@ -6055,11 +6414,11 @@ pub fn aya::programs::lirc_mode2::LircMode2::fd(&self) -> core::result::Result<& impl aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::from_pin>(path: P) -> core::result::Result impl aya::programs::lirc_mode2::LircMode2 +pub fn aya::programs::lirc_mode2::LircMode2::info(&self) -> core::result::Result +impl aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::lirc_mode2::LircMode2::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::lirc_mode2::LircMode2 -pub fn aya::programs::lirc_mode2::LircMode2::program_info(&self) -> core::result::Result -impl aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::lirc_mode2::LircMode2 pub fn aya::programs::lirc_mode2::LircMode2::drop(&mut self) @@ -6103,11 +6462,11 @@ pub fn aya::programs::lsm::Lsm::fd(&self) -> core::result::Result<&aya::programs impl aya::programs::lsm::Lsm pub fn aya::programs::lsm::Lsm::from_pin>(path: P) -> core::result::Result impl aya::programs::lsm::Lsm +pub fn aya::programs::lsm::Lsm::info(&self) -> core::result::Result +impl aya::programs::lsm::Lsm pub fn aya::programs::lsm::Lsm::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::lsm::Lsm::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::lsm::Lsm -pub fn aya::programs::lsm::Lsm::program_info(&self) -> core::result::Result -impl aya::programs::lsm::Lsm pub fn aya::programs::lsm::Lsm::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::lsm::Lsm pub fn aya::programs::lsm::Lsm::drop(&mut self) @@ -6151,11 +6510,11 @@ pub fn aya::programs::perf_event::PerfEvent::fd(&self) -> core::result::Result<& impl aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::from_pin>(path: P) -> core::result::Result impl aya::programs::perf_event::PerfEvent +pub fn aya::programs::perf_event::PerfEvent::info(&self) -> core::result::Result +impl aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::perf_event::PerfEvent::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::perf_event::PerfEvent -pub fn aya::programs::perf_event::PerfEvent::program_info(&self) -> core::result::Result -impl aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::drop(&mut self) @@ -6190,7 +6549,7 @@ impl core::convert::From for aya::programs::perf_event::PerfEvent pub fn aya::programs::perf_event::PerfEvent::from(t: T) -> T pub struct aya::programs::ProgramFd(_) impl aya::programs::ProgramFd -pub fn aya::programs::ProgramFd::try_clone(&self) -> core::result::Result +pub fn aya::programs::ProgramFd::try_clone(&self) -> std::io::error::Result impl std::os::fd::owned::AsFd for aya::programs::ProgramFd pub fn aya::programs::ProgramFd::as_fd(&self) -> std::os::fd::owned::BorrowedFd<'_> impl core::fmt::Debug for aya::programs::ProgramFd @@ -6267,11 +6626,11 @@ pub fn aya::programs::RawTracePoint::fd(&self) -> core::result::Result<&aya::pro impl aya::programs::RawTracePoint pub fn aya::programs::RawTracePoint::from_pin>(path: P) -> core::result::Result impl aya::programs::RawTracePoint +pub fn aya::programs::RawTracePoint::info(&self) -> core::result::Result +impl aya::programs::RawTracePoint pub fn aya::programs::RawTracePoint::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::RawTracePoint::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::RawTracePoint -pub fn aya::programs::RawTracePoint::program_info(&self) -> core::result::Result -impl aya::programs::RawTracePoint pub fn aya::programs::RawTracePoint::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::RawTracePoint pub fn aya::programs::RawTracePoint::drop(&mut self) @@ -6315,11 +6674,11 @@ pub fn aya::programs::tc::SchedClassifier::take_link(&mut self, link_id: aya::pr impl aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::tc::SchedClassifier +pub fn aya::programs::tc::SchedClassifier::info(&self) -> core::result::Result +impl aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::tc::SchedClassifier::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::tc::SchedClassifier -pub fn aya::programs::tc::SchedClassifier::program_info(&self) -> core::result::Result -impl aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::tc::SchedClassifier pub fn aya::programs::tc::SchedClassifier::drop(&mut self) @@ -6363,11 +6722,11 @@ pub fn aya::programs::SkLookup::fd(&self) -> core::result::Result<&aya::programs impl aya::programs::SkLookup pub fn aya::programs::SkLookup::from_pin>(path: P) -> core::result::Result impl aya::programs::SkLookup +pub fn aya::programs::SkLookup::info(&self) -> core::result::Result +impl aya::programs::SkLookup pub fn aya::programs::SkLookup::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::SkLookup::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::SkLookup -pub fn aya::programs::SkLookup::program_info(&self) -> core::result::Result -impl aya::programs::SkLookup pub fn aya::programs::SkLookup::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::SkLookup pub fn aya::programs::SkLookup::drop(&mut self) @@ -6402,7 +6761,7 @@ impl core::convert::From for aya::programs::SkLookup pub fn aya::programs::SkLookup::from(t: T) -> T pub struct aya::programs::SkMsg impl aya::programs::SkMsg -pub fn aya::programs::SkMsg::attach(&mut self, map: aya::maps::sock::SockMapFd) -> core::result::Result +pub fn aya::programs::SkMsg::attach(&mut self, map: &aya::maps::sock::SockMapFd) -> core::result::Result pub fn aya::programs::SkMsg::detach(&mut self, link_id: SkMsgLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::SkMsg::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::SkMsg::take_link(&mut self, link_id: SkMsgLinkId) -> core::result::Result @@ -6411,11 +6770,11 @@ pub fn aya::programs::SkMsg::fd(&self) -> core::result::Result<&aya::programs::P impl aya::programs::SkMsg pub fn aya::programs::SkMsg::from_pin>(path: P) -> core::result::Result impl aya::programs::SkMsg +pub fn aya::programs::SkMsg::info(&self) -> core::result::Result +impl aya::programs::SkMsg pub fn aya::programs::SkMsg::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::SkMsg::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::SkMsg -pub fn aya::programs::SkMsg::program_info(&self) -> core::result::Result -impl aya::programs::SkMsg pub fn aya::programs::SkMsg::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::SkMsg pub fn aya::programs::SkMsg::drop(&mut self) @@ -6450,7 +6809,7 @@ impl core::convert::From for aya::programs::SkMsg pub fn aya::programs::SkMsg::from(t: T) -> T pub struct aya::programs::SkSkb impl aya::programs::SkSkb -pub fn aya::programs::SkSkb::attach(&mut self, map: aya::maps::sock::SockMapFd) -> core::result::Result +pub fn aya::programs::SkSkb::attach(&mut self, map: &aya::maps::sock::SockMapFd) -> core::result::Result pub fn aya::programs::SkSkb::detach(&mut self, link_id: SkSkbLinkId) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::SkSkb::from_pin>(path: P, kind: aya::programs::SkSkbKind) -> core::result::Result pub fn aya::programs::SkSkb::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> @@ -6458,11 +6817,11 @@ pub fn aya::programs::SkSkb::take_link(&mut self, link_id: SkSkbLinkId) -> core: impl aya::programs::SkSkb pub fn aya::programs::SkSkb::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::SkSkb +pub fn aya::programs::SkSkb::info(&self) -> core::result::Result +impl aya::programs::SkSkb pub fn aya::programs::SkSkb::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::SkSkb::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::SkSkb -pub fn aya::programs::SkSkb::program_info(&self) -> core::result::Result -impl aya::programs::SkSkb pub fn aya::programs::SkSkb::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::SkSkb pub fn aya::programs::SkSkb::drop(&mut self) @@ -6506,11 +6865,11 @@ pub fn aya::programs::SockOps::fd(&self) -> core::result::Result<&aya::programs: impl aya::programs::SockOps pub fn aya::programs::SockOps::from_pin>(path: P) -> core::result::Result impl aya::programs::SockOps +pub fn aya::programs::SockOps::info(&self) -> core::result::Result +impl aya::programs::SockOps pub fn aya::programs::SockOps::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::SockOps::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::SockOps -pub fn aya::programs::SockOps::program_info(&self) -> core::result::Result -impl aya::programs::SockOps pub fn aya::programs::SockOps::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::SockOps pub fn aya::programs::SockOps::drop(&mut self) @@ -6554,11 +6913,11 @@ pub fn aya::programs::SocketFilter::fd(&self) -> core::result::Result<&aya::prog impl aya::programs::SocketFilter pub fn aya::programs::SocketFilter::from_pin>(path: P) -> core::result::Result impl aya::programs::SocketFilter +pub fn aya::programs::SocketFilter::info(&self) -> core::result::Result +impl aya::programs::SocketFilter pub fn aya::programs::SocketFilter::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::SocketFilter::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::SocketFilter -pub fn aya::programs::SocketFilter::program_info(&self) -> core::result::Result -impl aya::programs::SocketFilter pub fn aya::programs::SocketFilter::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::SocketFilter pub fn aya::programs::SocketFilter::drop(&mut self) @@ -6602,11 +6961,11 @@ pub fn aya::programs::trace_point::TracePoint::fd(&self) -> core::result::Result impl aya::programs::trace_point::TracePoint pub fn aya::programs::trace_point::TracePoint::from_pin>(path: P) -> core::result::Result impl aya::programs::trace_point::TracePoint +pub fn aya::programs::trace_point::TracePoint::info(&self) -> core::result::Result +impl aya::programs::trace_point::TracePoint pub fn aya::programs::trace_point::TracePoint::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::trace_point::TracePoint::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::trace_point::TracePoint -pub fn aya::programs::trace_point::TracePoint::program_info(&self) -> core::result::Result -impl aya::programs::trace_point::TracePoint pub fn aya::programs::trace_point::TracePoint::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::trace_point::TracePoint pub fn aya::programs::trace_point::TracePoint::drop(&mut self) @@ -6650,11 +7009,11 @@ pub fn aya::programs::uprobe::UProbe::take_link(&mut self, link_id: aya::program impl aya::programs::uprobe::UProbe pub fn aya::programs::uprobe::UProbe::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::uprobe::UProbe +pub fn aya::programs::uprobe::UProbe::info(&self) -> core::result::Result +impl aya::programs::uprobe::UProbe pub fn aya::programs::uprobe::UProbe::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::uprobe::UProbe::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::uprobe::UProbe -pub fn aya::programs::uprobe::UProbe::program_info(&self) -> core::result::Result -impl aya::programs::uprobe::UProbe pub fn aya::programs::uprobe::UProbe::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::uprobe::UProbe pub fn aya::programs::uprobe::UProbe::drop(&mut self) @@ -6693,18 +7052,17 @@ pub fn aya::programs::xdp::Xdp::attach(&mut self, interface: &str, flags: aya::p pub fn aya::programs::xdp::Xdp::attach_to_if_index(&mut self, if_index: u32, flags: aya::programs::xdp::XdpFlags) -> core::result::Result pub fn aya::programs::xdp::Xdp::attach_to_link(&mut self, link: aya::programs::xdp::XdpLink) -> core::result::Result pub fn aya::programs::xdp::Xdp::detach(&mut self, link_id: aya::programs::xdp::XdpLinkId) -> core::result::Result<(), aya::programs::ProgramError> +pub fn aya::programs::xdp::Xdp::from_pin>(path: P, attach_type: aya_obj::programs::xdp::XdpAttachType) -> core::result::Result pub fn aya::programs::xdp::Xdp::load(&mut self) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::xdp::Xdp::take_link(&mut self, link_id: aya::programs::xdp::XdpLinkId) -> core::result::Result impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::fd(&self) -> core::result::Result<&aya::programs::ProgramFd, aya::programs::ProgramError> impl aya::programs::xdp::Xdp -pub fn aya::programs::xdp::Xdp::from_pin>(path: P) -> core::result::Result +pub fn aya::programs::xdp::Xdp::info(&self) -> core::result::Result impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::pin>(&mut self, path: P) -> core::result::Result<(), aya::pin::PinError> pub fn aya::programs::xdp::Xdp::unpin(self) -> core::result::Result<(), std::io::error::Error> impl aya::programs::xdp::Xdp -pub fn aya::programs::xdp::Xdp::program_info(&self) -> core::result::Result -impl aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::unload(&mut self) -> core::result::Result<(), aya::programs::ProgramError> impl core::ops::drop::Drop for aya::programs::xdp::Xdp pub fn aya::programs::xdp::Xdp::drop(&mut self) @@ -7246,6 +7604,8 @@ pub fn aya::VerifierLogLevel::borrow_mut(&mut self) -> &mut T impl core::convert::From for aya::VerifierLogLevel pub fn aya::VerifierLogLevel::from(t: T) -> T pub unsafe trait aya::Pod: core::marker::Copy + 'static +impl aya::Pod for aya_obj::generated::linux_bindings_x86_64::bpf_cpumap_val +impl aya::Pod for aya_obj::generated::linux_bindings_x86_64::bpf_devmap_val impl aya::Pod for i128 impl aya::Pod for i16 impl aya::Pod for i32