ebpf_user/
skeleton.rs

1use std::ptr;
2use super::kind;
3
4pub struct MapRef {
5    name: &'static str,
6    inner: *mut libbpf_sys::bpf_map,
7}
8
9impl kind::AppItem for MapRef {
10    const MAP: usize = 1;
11    const PROG: usize = 0;
12
13    fn named(name: &'static str) -> Self {
14        MapRef {
15            name,
16            inner: ptr::null_mut(),
17        }
18    }
19
20    fn kind_mut(&mut self) -> kind::AppItemKindMut<'_> {
21        kind::AppItemKindMut::Map(self)
22    }
23}
24
25impl MapRef {
26    pub fn fd(&self) -> i32 {
27        unsafe { libbpf_sys::bpf_map__fd(self.inner) }
28    }
29}
30
31pub struct ProgRef {
32    name: &'static str,
33    prog: *mut libbpf_sys::bpf_program,
34    link: *mut libbpf_sys::bpf_link,
35}
36
37impl kind::AppItem for ProgRef {
38    const MAP: usize = 0;
39    const PROG: usize = 1;
40
41    fn named(name: &'static str) -> Self {
42        ProgRef {
43            name,
44            prog: ptr::null_mut(),
45            link: ptr::null_mut(),
46        }
47    }
48
49    fn kind_mut(&mut self) -> kind::AppItemKindMut<'_> {
50        kind::AppItemKindMut::Prog(self)
51    }
52}
53
54pub struct Skeleton<App>
55where
56    App: BpfApp,
57{
58    inner: libbpf_sys::bpf_object_skeleton,
59    obj: Box<*mut libbpf_sys::bpf_object>,
60    pub app: Box<App>,
61}
62
63pub trait BpfApp {
64    const MAP_CNT: usize;
65    const PROG_CNT: usize;
66
67    fn instance() -> Self;
68    fn as_mut_map(&mut self, index: usize) -> Option<&mut MapRef>;
69    fn as_mut_prog(&mut self, index: usize) -> Option<&mut ProgRef>;
70}
71
72impl<App> Skeleton<App>
73where
74    App: BpfApp,
75{
76    pub fn open(name: &'static str, code: &'static [u8]) -> Result<Self, i32> {
77        use std::{
78            mem, slice,
79            alloc::{Layout, alloc_zeroed},
80        };
81
82        let mut app = Box::new(App::instance());
83        let mut obj = Box::<*mut libbpf_sys::bpf_object>::new(ptr::null_mut());
84
85        let opts = libbpf_sys::bpf_object_open_opts {
86            sz: mem::size_of::<libbpf_sys::bpf_object_open_opts>() as libbpf_sys::size_t,
87            object_name: ptr::null(),
88            relaxed_maps: false,
89            relaxed_core_relocs: false,
90            __bindgen_padding_0: [0; 6],
91            pin_root_path: ptr::null(),
92            attach_prog_fd: 0,
93            __bindgen_padding_1: [0; 4],
94            kconfig: ptr::null(),
95            btf_custom_path: ptr::null(),
96            kernel_log_buf: ptr::null_mut(),
97            kernel_log_size: 0,
98            kernel_log_level: 0,
99            __bindgen_padding_2: [0; 4],
100        };
101
102        let map_l = Layout::array::<libbpf_sys::bpf_map_skeleton>(App::MAP_CNT).unwrap();
103        let prog_l = Layout::array::<libbpf_sys::bpf_prog_skeleton>(App::PROG_CNT).unwrap();
104
105        let mut s = libbpf_sys::bpf_object_skeleton {
106            sz: mem::size_of::<libbpf_sys::bpf_object_skeleton>() as _,
107            name: name.as_ptr() as _,
108            data: code.as_ptr() as *const _ as *mut _,
109            data_sz: code.len() as _,
110            obj: obj.as_mut(),
111            map_cnt: App::MAP_CNT as _,
112            map_skel_sz: mem::size_of::<libbpf_sys::bpf_map_skeleton>() as _,
113            maps: unsafe { alloc_zeroed(map_l) } as *mut libbpf_sys::bpf_map_skeleton,
114            prog_cnt: App::PROG_CNT as _,
115            prog_skel_sz: mem::size_of::<libbpf_sys::bpf_prog_skeleton>() as _,
116            progs: unsafe { alloc_zeroed(prog_l) } as *mut libbpf_sys::bpf_prog_skeleton,
117        };
118
119        let maps = unsafe { slice::from_raw_parts_mut(s.maps, App::MAP_CNT) };
120        for (i, s_map) in maps.iter_mut().enumerate() {
121            let map = app.as_mut_map(i).unwrap();
122            s_map.name = map.name.as_ptr() as _;
123            s_map.map = &mut map.inner;
124            s_map.mmaped = ptr::null_mut();
125        }
126
127        let progs = unsafe { slice::from_raw_parts_mut(s.progs, App::PROG_CNT) };
128        for (i, s_prog) in progs.iter_mut().enumerate() {
129            let prog = app.as_mut_prog(i).unwrap();
130            s_prog.name = prog.name.as_ptr() as _;
131            s_prog.prog = &mut prog.prog;
132            s_prog.link = &mut prog.link;
133        }
134
135        let c = unsafe { libbpf_sys::bpf_object__open_skeleton(&mut s, &opts) };
136
137        if c == 0 {
138            Ok(Skeleton { inner: s, obj, app })
139        } else {
140            Err(c)
141        }
142    }
143
144    pub fn load(&mut self) -> Result<(), i32> {
145        let c = unsafe { libbpf_sys::bpf_object__load_skeleton(&mut self.inner) };
146
147        let _ = self.obj.as_mut();
148        if c == 0 {
149            Ok(())
150        } else {
151            Err(c)
152        }
153    }
154
155    pub fn attach(&mut self) -> Result<(), i32> {
156        let c = unsafe { libbpf_sys::bpf_object__attach_skeleton(&mut self.inner) };
157
158        if c == 0 {
159            Ok(())
160        } else {
161            Err(c)
162        }
163    }
164}
165
166impl<App> Drop for Skeleton<App>
167where
168    App: BpfApp,
169{
170    fn drop(&mut self) {
171        let s = Box::new(self.inner);
172        unsafe { libbpf_sys::bpf_object__destroy_skeleton(Box::leak(s)) }
173    }
174}