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}