Skip to main content

push_packet/
ebpf.rs

1use aya::{
2    Ebpf, Pod,
3    maps::{Array, Map, MapData},
4    programs::Xdp,
5};
6
7use crate::{Loader, error::Error};
8
9pub struct EbpfVar<T: Pod> {
10    value: T,
11    map: Array<MapData, T>,
12    name: String,
13}
14
15impl<T: Pod> EbpfVar<T> {
16    /// Set the `EbpfVar` value
17    pub fn update(&mut self, value: T) -> Result<(), Error> {
18        self.value = value;
19        self.map
20            .set(0, value, 0)
21            .map_err(|e| Error::map(&self.name, e))
22    }
23    /// Get the `EbpfVar` value
24    pub fn get(&self) -> &T {
25        &self.value
26    }
27    /// Creates a new `EbpfVar` with a given name and value
28    pub fn new(ebpf: &mut Ebpf, name: &str, value: T) -> Result<Self, Error> {
29        let mut map = array_owned(ebpf, name)?;
30        map.set(0, value, 0).map_err(|e| Error::map(name, e))?;
31        Ok(Self {
32            value,
33            map,
34            name: name.into(),
35        })
36    }
37}
38
39impl<T: Pod> Loader for (T, &str) {
40    type Component = EbpfVar<T>;
41    fn load(self, ebpf: &mut Ebpf) -> Result<Self::Component, Error> {
42        EbpfVar::new(ebpf, self.1, self.0)
43    }
44}
45
46pub(crate) fn map_owned<T>(ebpf: &mut Ebpf, name: &str) -> Result<T, Error>
47where
48    T: TryFrom<Map, Error = aya::maps::MapError>,
49{
50    let map = ebpf
51        .take_map(name)
52        .ok_or_else(|| Error::MissingMap(name.into()))?;
53    T::try_from(map).map_err(|e| Error::map(name, e))
54}
55
56pub(crate) fn array_owned<T: Pod>(ebpf: &mut Ebpf, name: &str) -> Result<Array<MapData, T>, Error> {
57    map_owned(ebpf, name)
58}
59
60/// Get an un-loaded xdp program
61pub(crate) fn xdp_program<'a>(ebpf: &'a mut Ebpf, name: &str) -> Result<&'a mut Xdp, Error> {
62    ebpf.program_mut(name)
63        .ok_or_else(|| Error::MissingProgram(name.into()))?
64        .try_into()
65        .map_err(|e| Error::InvalidProgramType {
66            program_name: name.into(),
67            e,
68        })
69}
70
71/// Get a loaded xdp program
72pub(crate) fn load_xdp_program<'a>(ebpf: &'a mut Ebpf, name: &str) -> Result<&'a mut Xdp, Error> {
73    let program = xdp_program(ebpf, name)?;
74    program.load().map_err(|e| Error::load_program(name, e))?;
75    Ok(program)
76}