aya_metrics_mocks/
lib.rs

1//! This crate contains mocks for the aya crate.
2//!
3//! These are very crude implementations that mimic the signatures of many Aya structs/functions.
4//! They can be used as drop in replacements.
5//!
6//! This approach is very dirty and should be used sparingly. Better mocks would be welcome.
7//! Hopefully in the future this may be something offered by Aya: https://github.com/aya-rs/aya/issues/999
8
9// GRCOV_STOP_COVERAGE
10
11use std::collections::HashMap;
12use std::hash::Hash;
13use std::sync::{Arc, Mutex};
14
15use std::borrow::{Borrow, Cow};
16
17use aya::maps::lpm_trie::Key;
18use aya::{
19    maps::{MapError, PerCpuValues},
20    programs::Program,
21    util::nr_cpus,
22    Btf, EbpfError, Pod, VerifierLogLevel,
23};
24
25pub struct Map {}
26
27pub struct EbpfLoader<'a> {
28    btf: Option<Cow<'a, Btf>>,
29    verifier_log_level: VerifierLogLevel,
30}
31
32impl<'a> EbpfLoader<'a> {
33    pub fn new() -> Self {
34        Self {
35            btf: Btf::from_sys_fs().ok().map(Cow::Owned),
36            verifier_log_level: VerifierLogLevel::default(),
37        }
38    }
39
40    pub fn load(&mut self, data: &[u8]) -> Result<Ebpf, EbpfError> {
41        Ebpf::load(&[])
42    }
43
44    pub fn btf(&mut self, btf: Option<&'a Btf>) -> &mut Self {
45        self.btf = btf.map(Cow::Borrowed);
46        self
47    }
48
49    pub fn verifier_log_level(&mut self, level: VerifierLogLevel) -> &mut Self {
50        self.verifier_log_level = level;
51        self
52    }
53
54    pub fn set_max_entries(&mut self, name: &'a str, size: u32) -> &mut Self {
55        self
56    }
57}
58
59pub struct Ebpf {}
60
61impl Ebpf {
62    pub fn load(_data: &[u8]) -> Result<Ebpf, EbpfError> {
63        Ok(Self {})
64    }
65
66    pub fn program_mut(&mut self, _name: &str) -> Option<&mut Program> {
67        None
68    }
69
70    pub fn map_mut(&mut self, _name: &str) -> Option<&mut aya::maps::Map> {
71        None
72    }
73
74    pub fn take_map(&mut self, _name: &str) -> Option<Map> {
75        Some(Map {})
76    }
77}
78
79pub struct EbpfLogger;
80
81impl EbpfLogger {
82    pub fn init(_bpf: &mut Ebpf) -> Result<EbpfLogger, aya_log::Error> {
83        Ok(Self {})
84    }
85}
86
87#[derive(Clone)]
88pub struct PerCpuArray<V: Pod> {
89    inner: Arc<Mutex<Vec<Vec<V>>>>,
90    _v: std::marker::PhantomData<V>,
91}
92
93impl<V: Pod> PerCpuArray<V> {
94    pub fn new(len: usize, val: V) -> Self {
95        let arr = vec![val.clone(); nr_cpus().unwrap()];
96        PerCpuArray {
97            inner: Arc::new(Mutex::new(vec![arr.clone(); len])),
98            _v: core::marker::PhantomData,
99        }
100    }
101}
102
103impl TryFrom<Map> for PerCpuArray<u64> {
104    type Error = MapError;
105
106    fn try_from(_map: Map) -> Result<PerCpuArray<u64>, MapError> {
107        Ok(PerCpuArray::new(1, 0u64))
108    }
109}
110
111impl<V: Pod> PerCpuArray<V> {
112    pub fn get(&self, index: &u32, _flags: u64) -> Result<PerCpuValues<V>, MapError> {
113        let guard = self.inner.lock().unwrap();
114        let values = guard.get(*index as usize).ok_or(MapError::OutOfBounds {
115            index: *index,
116            max_entries: guard.len() as u32,
117        })?;
118        PerCpuValues::try_from(values.clone()).map_err(|_| MapError::KeyNotFound)
119    }
120
121    pub fn set(&mut self, index: u32, values: PerCpuValues<V>, _flags: u64) -> Result<(), MapError> {
122        let arr = (0..nr_cpus().unwrap())
123            .map(|i| values.get(i).unwrap().clone())
124            .collect::<Vec<V>>();
125        let mut guard = self.inner.lock().unwrap();
126        guard[index as usize] = arr;
127        Ok(())
128    }
129}
130
131#[derive(Debug, PartialEq, Eq)]
132pub struct LpmTrie<K: Eq + Hash, V: Eq + Copy> {
133    // shameless plug, doesn't actually use a trie or suport LPM
134    inner: HashMap<K, V>,
135    _k: std::marker::PhantomData<K>,
136    _v: std::marker::PhantomData<V>,
137}
138
139impl<K: Eq + Hash + Pod, V: Eq + Copy + Pod> LpmTrie<K, V> {
140    pub fn new() -> Self {
141        Self {
142            inner: Default::default(),
143            _k: std::marker::PhantomData,
144            _v: std::marker::PhantomData,
145        }
146    }
147
148    pub fn size(&self) -> usize {
149        self.inner.len()
150    }
151}
152
153impl TryFrom<Map> for LpmTrie<u32, u32> {
154    type Error = MapError;
155
156    fn try_from(_map: Map) -> Result<LpmTrie<u32, u32>, MapError> {
157        Ok(LpmTrie::new())
158    }
159}
160
161impl<K: Eq + Hash + Pod, V: Eq + Copy + Pod> LpmTrie<K, V> {
162    /// Inserts a key value pair into the map.
163    pub fn insert(&mut self, key: &Key<K>, value: impl Borrow<V>, _flags: u64) -> Result<(), MapError> {
164        // shameless plug, ignores the prefix require for LPM
165        self.inner.insert(key.data(), *value.borrow());
166        Ok(())
167    }
168}
169
170#[derive(Debug, PartialEq, Eq)]
171pub struct Array<V: Pod> {
172    inner: Vec<V>,
173    size: usize,
174    _v: core::marker::PhantomData<V>,
175}
176
177impl<V: Pod + Default> Array<V> {
178    pub fn new(size: usize) -> Self {
179        Self {
180            inner: vec![Default::default(); size],
181            size,
182            _v: core::marker::PhantomData,
183        }
184    }
185
186    pub fn set(&mut self, index: u32, value: impl Borrow<V>, _flags: u64) -> Result<(), MapError> {
187        let ind: usize = index.try_into().map_err(|_| MapError::KeyNotFound)?;
188        if ind >= self.size {
189            return Err(MapError::OutOfBounds {
190                index,
191                max_entries: self.size as u32,
192            });
193        }
194        self.inner[ind] = value.borrow().clone();
195        Ok(())
196    }
197
198    pub fn get(&self, index: &u32, _flags: u64) -> Result<V, MapError> {
199        let ind: usize = (*index).try_into().map_err(|_| MapError::KeyNotFound)?;
200        if ind >= self.size {
201            return Err(MapError::OutOfBounds {
202                index: *index,
203                max_entries: self.size as u32,
204            });
205        }
206        Ok(self.inner[ind].clone())
207    }
208}
209
210impl<V: Pod + Default> TryFrom<Map> for Array<V> {
211    type Error = MapError;
212    fn try_from(_value: Map) -> Result<Array<V>, MapError> {
213        Ok(Array::new(1))
214    }
215}