aya_ebpf/maps/
queue.rs

1use core::{cell::UnsafeCell, marker::PhantomData, mem};
2
3use crate::{
4    bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_QUEUE},
5    helpers::{bpf_map_pop_elem, bpf_map_push_elem},
6    maps::PinningType,
7};
8
9#[repr(transparent)]
10pub struct Queue<T> {
11    def: UnsafeCell<bpf_map_def>,
12    _t: PhantomData<T>,
13}
14
15unsafe impl<T: Sync> Sync for Queue<T> {}
16
17impl<T> Queue<T> {
18    pub const fn with_max_entries(max_entries: u32, flags: u32) -> Queue<T> {
19        Queue {
20            def: UnsafeCell::new(bpf_map_def {
21                type_: BPF_MAP_TYPE_QUEUE,
22                key_size: 0,
23                value_size: mem::size_of::<T>() as u32,
24                max_entries,
25                map_flags: flags,
26                id: 0,
27                pinning: PinningType::None as u32,
28            }),
29            _t: PhantomData,
30        }
31    }
32
33    pub const fn pinned(max_entries: u32, flags: u32) -> Queue<T> {
34        Queue {
35            def: UnsafeCell::new(bpf_map_def {
36                type_: BPF_MAP_TYPE_QUEUE,
37                key_size: 0,
38                value_size: mem::size_of::<T>() as u32,
39                max_entries,
40                map_flags: flags,
41                id: 0,
42                pinning: PinningType::ByName as u32,
43            }),
44            _t: PhantomData,
45        }
46    }
47
48    pub fn push(&self, value: &T, flags: u64) -> Result<(), i64> {
49        let ret = unsafe {
50            bpf_map_push_elem(
51                self.def.get() as *mut _,
52                value as *const _ as *const _,
53                flags,
54            )
55        };
56        (ret == 0).then_some(()).ok_or(ret)
57    }
58
59    pub fn pop(&self) -> Option<T> {
60        unsafe {
61            let mut value = mem::MaybeUninit::uninit();
62            let ret = bpf_map_pop_elem(self.def.get() as *mut _, value.as_mut_ptr() as *mut _);
63            (ret == 0).then_some(value.assume_init())
64        }
65    }
66}