Skip to content

Commit

Permalink
Merge pull request #783 from astoycos/map_pin2
Browse files Browse the repository at this point in the history
aya: Implement dedicated map pinning
  • Loading branch information
astoycos committed Oct 10, 2023
2 parents 66bd85a + 8203914 commit ef27bce
Show file tree
Hide file tree
Showing 21 changed files with 293 additions and 37 deletions.
38 changes: 31 additions & 7 deletions aya/src/bpf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ impl<'a> BpfLoader<'a> {
if let Some(btf) = obj.fixup_and_sanitize_btf(features)? {
match load_btf(btf.to_bytes(), *verifier_log_level) {
Ok(btf_fd) => Some(Arc::new(btf_fd)),
// Only report an error here if the BTF is truely needed, otherwise proceed without.
// Only report an error here if the BTF is truly needed, otherwise proceed without.
Err(err) => {
for program in obj.programs.values() {
match program.section {
Expand Down Expand Up @@ -492,8 +492,13 @@ impl<'a> BpfLoader<'a> {
let mut map = match obj.pinning() {
PinningType::None => MapData::create(obj, &name, btf_fd)?,
PinningType::ByName => {
let path = map_pin_path.as_ref().ok_or(BpfError::NoPinPath)?;
MapData::create_pinned(path, obj, &name, btf_fd)?
// pin maps in /sys/fs/bpf by default to align with libbpf
// behavior https://github.com/libbpf/libbpf/blob/v1.2.2/src/libbpf.c#L2161.
let path = map_pin_path
.as_deref()
.unwrap_or_else(|| Path::new("/sys/fs/bpf"));

MapData::create_pinned_by_name(path, obj, &name, btf_fd)?
}
};
map.finalize()?;
Expand Down Expand Up @@ -856,6 +861,29 @@ impl Bpf {
self.maps.iter().map(|(name, map)| (name.as_str(), map))
}

/// A mutable iterator over all the maps.
///
/// # Examples
/// ```no_run
/// # use std::path::Path;
/// # #[derive(thiserror::Error, Debug)]
/// # enum Error {
/// # #[error(transparent)]
/// # Bpf(#[from] aya::BpfError),
/// # #[error(transparent)]
/// # Pin(#[from] aya::pin::PinError)
/// # }
/// # let mut bpf = aya::Bpf::load(&[])?;
/// # let pin_path = Path::new("/tmp/pin_path");
/// for (_, map) in bpf.maps_mut() {
/// map.pin(pin_path)?;
/// }
/// # Ok::<(), Error>(())
/// ```
pub fn maps_mut(&mut self) -> impl Iterator<Item = (&str, &mut Map)> {
self.maps.iter_mut().map(|(name, map)| (name.as_str(), map))
}

/// Returns a reference to the program with the given name.
///
/// You can use this to inspect a program and its properties. To load and attach a program, use
Expand Down Expand Up @@ -951,10 +979,6 @@ pub enum BpfError {
error: io::Error,
},

/// Pinning requested but no path provided
#[error("pinning requested but no path provided")]
NoPinPath,

/// Unexpected pinning type
#[error("unexpected pinning type {name}")]
UnexpectedPinningType {
Expand Down
2 changes: 1 addition & 1 deletion aya/src/maps/array/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use crate::{
/// ```
#[doc(alias = "BPF_MAP_TYPE_ARRAY")]
pub struct Array<T, V: Pod> {
inner: T,
pub(crate) inner: T,
_v: PhantomData<V>,
}

Expand Down
2 changes: 1 addition & 1 deletion aya/src/maps/array/per_cpu_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ use crate::{
/// ```
#[doc(alias = "BPF_MAP_TYPE_PERCPU_ARRAY")]
pub struct PerCpuArray<T, V: Pod> {
inner: T,
pub(crate) inner: T,
_v: PhantomData<V>,
}

Expand Down
2 changes: 1 addition & 1 deletion aya/src/maps/array/program_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ use crate::{
/// ```
#[doc(alias = "BPF_MAP_TYPE_PROG_ARRAY")]
pub struct ProgramArray<T> {
inner: T,
pub(crate) inner: T,
}

impl<T: Borrow<MapData>> ProgramArray<T> {
Expand Down
2 changes: 1 addition & 1 deletion aya/src/maps/bloom_filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use crate::{
#[doc(alias = "BPF_MAP_TYPE_BLOOM_FILTER")]
#[derive(Debug)]
pub struct BloomFilter<T, V: Pod> {
inner: T,
pub(crate) inner: T,
_v: PhantomData<V>,
}

Expand Down
2 changes: 1 addition & 1 deletion aya/src/maps/hash_map/hash_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use crate::{
#[doc(alias = "BPF_MAP_TYPE_LRU_HASH")]
#[derive(Debug)]
pub struct HashMap<T, K, V> {
inner: T,
pub(crate) inner: T,
_k: PhantomData<K>,
_v: PhantomData<V>,
}
Expand Down
2 changes: 1 addition & 1 deletion aya/src/maps/hash_map/per_cpu_hash_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ use crate::{
#[doc(alias = "BPF_MAP_TYPE_LRU_PERCPU_HASH")]
#[doc(alias = "BPF_MAP_TYPE_PERCPU_HASH")]
pub struct PerCpuHashMap<T, K: Pod, V: Pod> {
inner: T,
pub(crate) inner: T,
_k: PhantomData<K>,
_v: PhantomData<V>,
}
Expand Down
2 changes: 1 addition & 1 deletion aya/src/maps/lpm_trie.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ use crate::{
#[doc(alias = "BPF_MAP_TYPE_LPM_TRIE")]
#[derive(Debug)]
pub struct LpmTrie<T, K, V> {
inner: T,
pub(crate) inner: T,
_k: PhantomData<K>,
_v: PhantomData<V>,
}
Expand Down
89 changes: 85 additions & 4 deletions aya/src/maps/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
//! versa. Because of that, all map values must be plain old data and therefore
//! implement the [Pod] trait.
use std::{
borrow::BorrowMut,
ffi::CString,
fmt, io,
marker::PhantomData,
Expand Down Expand Up @@ -170,8 +171,8 @@ pub enum MapError {
#[error(transparent)]
SyscallError(#[from] SyscallError),

/// Could not pin map by name
#[error("map `{name:?}` requested pinning by name. pinning failed")]
/// Could not pin map
#[error("map `{name:?}` requested pinning. pinning failed")]
PinError {
/// The map name
name: Option<String>,
Expand Down Expand Up @@ -308,8 +309,89 @@ impl Map {
Self::Unsupported(map) => map.obj.map_type(),
}
}

/// Pins the map to a BPF filesystem.
///
/// When a map is pinned it will remain loaded until the corresponding file
/// is deleted. All parent directories in the given `path` must already exist.
pub fn pin<P: AsRef<Path>>(&mut self, path: P) -> Result<(), PinError> {
match self {
Self::Array(map) => map.pin(path),
Self::PerCpuArray(map) => map.pin(path),
Self::ProgramArray(map) => map.pin(path),
Self::HashMap(map) => map.pin(path),
Self::LruHashMap(map) => map.pin(path),
Self::PerCpuHashMap(map) => map.pin(path),
Self::PerCpuLruHashMap(map) => map.pin(path),
Self::PerfEventArray(map) => map.pin(path),
Self::SockHash(map) => map.pin(path),
Self::SockMap(map) => map.pin(path),
Self::BloomFilter(map) => map.pin(path),
Self::LpmTrie(map) => map.pin(path),
Self::Stack(map) => map.pin(path),
Self::StackTraceMap(map) => map.pin(path),
Self::Queue(map) => map.pin(path),
Self::CpuMap(map) => map.pin(path),
Self::DevMap(map) => map.pin(path),
Self::DevMapHash(map) => map.pin(path),
Self::XskMap(map) => map.pin(path),
Self::Unsupported(map) => map.pin(path),
}
}
}

// Implements map pinning for different map implementations
// TODO add support for PerfEventArrays and AsyncPerfEventArrays
macro_rules! impl_map_pin {
($ty_param:tt {
$($ty:ident),+ $(,)?
}) => {
$(impl_map_pin!(<$ty_param> $ty);)+
};
(
<($($ty_param:ident),*)>
$ty:ident
) => {
impl<T: BorrowMut<MapData>, $($ty_param: Pod),*> $ty<T, $($ty_param),*>
{
/// Pins the map to a BPF filesystem.
///
/// When a map is pinned it will remain loaded until the corresponding file
/// is deleted. All parent directories in the given `path` must already exist.
pub fn pin<P: AsRef<Path>>(&mut self, path: P) -> Result<(), PinError> {
let data = self.inner.borrow_mut();
data.pin(path)
}
}

};
}

impl_map_pin!(() {
ProgramArray,
SockMap,
StackTraceMap,
CpuMap,
DevMap,
DevMapHash,
XskMap,
});

impl_map_pin!((V) {
Array,
PerCpuArray,
SockHash,
BloomFilter,
Queue,
Stack,
});

impl_map_pin!((K, V) {
HashMap,
PerCpuHashMap,
LpmTrie,
});

// Implements TryFrom<Map> for different map implementations. Different map implementations can be
// constructed from different variants of the map enum. Also, the implementation may have type
// parameters (which we assume all have the bound `Pod` and nothing else).
Expand Down Expand Up @@ -461,7 +543,7 @@ impl MapData {
Ok(Self { obj, fd })
}

pub(crate) fn create_pinned<P: AsRef<Path>>(
pub(crate) fn create_pinned_by_name<P: AsRef<Path>>(
path: P,
obj: obj::Map,
name: &str,
Expand Down Expand Up @@ -490,7 +572,6 @@ impl MapData {
}
Err(_) => {
let mut map = Self::create(obj, name, btf_fd)?;
let path = path.join(name);
map.pin(&path).map_err(|error| MapError::PinError {
name: Some(name.into()),
error,
Expand Down
2 changes: 1 addition & 1 deletion aya/src/maps/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use crate::{
/// ```
#[doc(alias = "BPF_MAP_TYPE_QUEUE")]
pub struct Queue<T, V: Pod> {
inner: T,
pub(crate) inner: T,
_v: PhantomData<V>,
}

Expand Down
2 changes: 1 addition & 1 deletion aya/src/maps/sock/sock_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ use crate::{
/// ```
#[doc(alias = "BPF_MAP_TYPE_SOCKHASH")]
pub struct SockHash<T, K> {
inner: T,
pub(crate) inner: T,
_k: PhantomData<K>,
}

Expand Down
2 changes: 1 addition & 1 deletion aya/src/maps/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use crate::{
/// ```
#[doc(alias = "BPF_MAP_TYPE_STACK")]
pub struct Stack<T, V: Pod> {
inner: T,
pub(crate) inner: T,
_v: PhantomData<V>,
}

Expand Down
2 changes: 1 addition & 1 deletion aya/src/maps/stack_trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ use crate::{
#[derive(Debug)]
#[doc(alias = "BPF_MAP_TYPE_STACK_TRACE")]
pub struct StackTraceMap<T> {
inner: T,
pub(crate) inner: T,
max_stack_depth: usize,
}

Expand Down
2 changes: 1 addition & 1 deletion aya/src/maps/xdp/cpu_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ use crate::{
/// Kernel documentation: <https://docs.kernel.org/next/bpf/map_cpumap.html>
#[doc(alias = "BPF_MAP_TYPE_CPUMAP")]
pub struct CpuMap<T> {
inner: T,
pub(crate) inner: T,
}

impl<T: Borrow<MapData>> CpuMap<T> {
Expand Down
2 changes: 1 addition & 1 deletion aya/src/maps/xdp/dev_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use crate::{
/// Kernel documentation: <https://docs.kernel.org/next/bpf/map_devmap.html>
#[doc(alias = "BPF_MAP_TYPE_DEVMAP")]
pub struct DevMap<T> {
inner: T,
pub(crate) inner: T,
}

impl<T: Borrow<MapData>> DevMap<T> {
Expand Down
2 changes: 1 addition & 1 deletion aya/src/maps/xdp/dev_map_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use crate::{
/// Kernel documentation: <https://docs.kernel.org/next/bpf/map_devmap.html>
#[doc(alias = "BPF_MAP_TYPE_DEVMAP_HASH")]
pub struct DevMapHash<T> {
inner: T,
pub(crate) inner: T,
}

impl<T: Borrow<MapData>> DevMapHash<T> {
Expand Down
2 changes: 1 addition & 1 deletion aya/src/maps/xdp/xsk_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use crate::{
/// Kernel documentation: <https://docs.kernel.org/next/bpf/map_xskmap.html>
#[doc(alias = "BPF_MAP_TYPE_XSKMAP")]
pub struct XskMap<T> {
inner: T,
pub(crate) inner: T,
}

impl<T: Borrow<MapData>> XskMap<T> {
Expand Down
11 changes: 11 additions & 0 deletions test/integration-test/bpf/multimap-btf.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,24 @@ struct {
__uint(max_entries, 1);
} map_2 SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, __u32);
__type(value, __u64);
__uint(max_entries, 1);
__uint(pinning, LIBBPF_PIN_BY_NAME);
} map_pin_by_name SEC(".maps");

SEC("uprobe")
int bpf_prog(void *ctx) {
__u32 key = 0;
__u64 twenty_four = 24;
__u64 forty_two = 42;
__u64 forty_four = 44;

bpf_map_update_elem(&map_1, &key, &twenty_four, BPF_ANY);
bpf_map_update_elem(&map_2, &key, &forty_two, BPF_ANY);
bpf_map_update_elem(&map_pin_by_name, &key, &forty_four, BPF_ANY);
return 0;
}

Expand Down
Loading

0 comments on commit ef27bce

Please sign in to comment.