1use alloc::vec::Vec;
4
5use crate::{EbpfSectionKind, InvalidTypeBinding, generated::bpf_map_type};
6
7impl TryFrom<u32> for bpf_map_type {
8 type Error = InvalidTypeBinding<u32>;
9
10 fn try_from(map_type: u32) -> Result<Self, Self::Error> {
11 Ok(match map_type {
12 x if x == Self::BPF_MAP_TYPE_UNSPEC as u32 => Self::BPF_MAP_TYPE_UNSPEC,
13 x if x == Self::BPF_MAP_TYPE_HASH as u32 => Self::BPF_MAP_TYPE_HASH,
14 x if x == Self::BPF_MAP_TYPE_ARRAY as u32 => Self::BPF_MAP_TYPE_ARRAY,
15 x if x == Self::BPF_MAP_TYPE_PROG_ARRAY as u32 => Self::BPF_MAP_TYPE_PROG_ARRAY,
16 x if x == Self::BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 => {
17 Self::BPF_MAP_TYPE_PERF_EVENT_ARRAY
18 }
19 x if x == Self::BPF_MAP_TYPE_PERCPU_HASH as u32 => Self::BPF_MAP_TYPE_PERCPU_HASH,
20 x if x == Self::BPF_MAP_TYPE_PERCPU_ARRAY as u32 => Self::BPF_MAP_TYPE_PERCPU_ARRAY,
21 x if x == Self::BPF_MAP_TYPE_STACK_TRACE as u32 => Self::BPF_MAP_TYPE_STACK_TRACE,
22 x if x == Self::BPF_MAP_TYPE_CGROUP_ARRAY as u32 => Self::BPF_MAP_TYPE_CGROUP_ARRAY,
23 x if x == Self::BPF_MAP_TYPE_LRU_HASH as u32 => Self::BPF_MAP_TYPE_LRU_HASH,
24 x if x == Self::BPF_MAP_TYPE_LRU_PERCPU_HASH as u32 => {
25 Self::BPF_MAP_TYPE_LRU_PERCPU_HASH
26 }
27 x if x == Self::BPF_MAP_TYPE_LPM_TRIE as u32 => Self::BPF_MAP_TYPE_LPM_TRIE,
28 x if x == Self::BPF_MAP_TYPE_ARRAY_OF_MAPS as u32 => Self::BPF_MAP_TYPE_ARRAY_OF_MAPS,
29 x if x == Self::BPF_MAP_TYPE_HASH_OF_MAPS as u32 => Self::BPF_MAP_TYPE_HASH_OF_MAPS,
30 x if x == Self::BPF_MAP_TYPE_DEVMAP as u32 => Self::BPF_MAP_TYPE_DEVMAP,
31 x if x == Self::BPF_MAP_TYPE_SOCKMAP as u32 => Self::BPF_MAP_TYPE_SOCKMAP,
32 x if x == Self::BPF_MAP_TYPE_CPUMAP as u32 => Self::BPF_MAP_TYPE_CPUMAP,
33 x if x == Self::BPF_MAP_TYPE_XSKMAP as u32 => Self::BPF_MAP_TYPE_XSKMAP,
34 x if x == Self::BPF_MAP_TYPE_SOCKHASH as u32 => Self::BPF_MAP_TYPE_SOCKHASH,
35 x if x == Self::BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED as u32 => {
36 Self::BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED
37 }
38 x if x == Self::BPF_MAP_TYPE_REUSEPORT_SOCKARRAY as u32 => {
39 Self::BPF_MAP_TYPE_REUSEPORT_SOCKARRAY
40 }
41 x if x == Self::BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE_DEPRECATED as u32 => {
42 Self::BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE_DEPRECATED
43 }
44 x if x == Self::BPF_MAP_TYPE_QUEUE as u32 => Self::BPF_MAP_TYPE_QUEUE,
45 x if x == Self::BPF_MAP_TYPE_STACK as u32 => Self::BPF_MAP_TYPE_STACK,
46 x if x == Self::BPF_MAP_TYPE_SK_STORAGE as u32 => Self::BPF_MAP_TYPE_SK_STORAGE,
47 x if x == Self::BPF_MAP_TYPE_DEVMAP_HASH as u32 => Self::BPF_MAP_TYPE_DEVMAP_HASH,
48 x if x == Self::BPF_MAP_TYPE_STRUCT_OPS as u32 => Self::BPF_MAP_TYPE_STRUCT_OPS,
49 x if x == Self::BPF_MAP_TYPE_RINGBUF as u32 => Self::BPF_MAP_TYPE_RINGBUF,
50 x if x == Self::BPF_MAP_TYPE_INODE_STORAGE as u32 => Self::BPF_MAP_TYPE_INODE_STORAGE,
51 x if x == Self::BPF_MAP_TYPE_TASK_STORAGE as u32 => Self::BPF_MAP_TYPE_TASK_STORAGE,
52 x if x == Self::BPF_MAP_TYPE_BLOOM_FILTER as u32 => Self::BPF_MAP_TYPE_BLOOM_FILTER,
53 x if x == Self::BPF_MAP_TYPE_USER_RINGBUF as u32 => Self::BPF_MAP_TYPE_USER_RINGBUF,
54 x if x == Self::BPF_MAP_TYPE_CGRP_STORAGE as u32 => Self::BPF_MAP_TYPE_CGRP_STORAGE,
55 x if x == Self::BPF_MAP_TYPE_ARENA as u32 => Self::BPF_MAP_TYPE_ARENA,
56 _ => return Err(InvalidTypeBinding { value: map_type }),
57 })
58 }
59}
60
61#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
63pub struct BtfMapDef {
64 pub(crate) map_type: u32,
65 pub(crate) key_size: u32,
66 pub(crate) value_size: u32,
67 pub(crate) max_entries: u32,
68 pub(crate) map_flags: u32,
69 pub(crate) pinning: PinningType,
70 pub btf_key_type_id: u32,
72 pub btf_value_type_id: u32,
74}
75
76#[repr(u32)]
81#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
82pub enum PinningType {
83 #[default]
85 None = 0,
86 ByName = 1,
88}
89
90#[derive(Debug, thiserror::Error)]
92pub enum PinningError {
93 #[error("unsupported pinning type `{pinning_type}`")]
95 Unsupported {
96 pinning_type: u32,
98 },
99}
100
101impl TryFrom<u32> for PinningType {
102 type Error = PinningError;
103
104 fn try_from(value: u32) -> Result<Self, Self::Error> {
105 match value {
106 0 => Ok(Self::None),
107 1 => Ok(Self::ByName),
108 pinning_type => Err(PinningError::Unsupported { pinning_type }),
109 }
110 }
111}
112
113#[repr(C)]
115#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
116pub struct bpf_map_def {
117 pub map_type: u32,
120 pub key_size: u32,
122 pub value_size: u32,
124 pub max_entries: u32,
126 pub map_flags: u32,
128 pub id: u32,
131 pub pinning: PinningType,
133}
134
135pub(crate) const MINIMUM_MAP_SIZE: usize = size_of::<u32>() * 5;
137
138#[derive(Debug, Clone)]
140pub enum Map {
141 Legacy(LegacyMap),
143 Btf(BtfMap),
145}
146
147impl Map {
148 pub const fn map_type(&self) -> u32 {
150 match self {
151 Self::Legacy(m) => m.def.map_type,
152 Self::Btf(m) => m.def.map_type,
153 }
154 }
155
156 pub const fn key_size(&self) -> u32 {
158 match self {
159 Self::Legacy(m) => m.def.key_size,
160 Self::Btf(m) => m.def.key_size,
161 }
162 }
163
164 pub const fn value_size(&self) -> u32 {
166 match self {
167 Self::Legacy(m) => m.def.value_size,
168 Self::Btf(m) => m.def.value_size,
169 }
170 }
171
172 pub const fn set_value_size(&mut self, size: u32) {
174 match self {
175 Self::Legacy(m) => m.def.value_size = size,
176 Self::Btf(m) => m.def.value_size = size,
177 }
178 }
179
180 pub const fn max_entries(&self) -> u32 {
182 match self {
183 Self::Legacy(m) => m.def.max_entries,
184 Self::Btf(m) => m.def.max_entries,
185 }
186 }
187
188 pub const fn set_max_entries(&mut self, v: u32) {
190 match self {
191 Self::Legacy(m) => m.def.max_entries = v,
192 Self::Btf(m) => m.def.max_entries = v,
193 }
194 }
195
196 pub const fn map_flags(&self) -> u32 {
198 match self {
199 Self::Legacy(m) => m.def.map_flags,
200 Self::Btf(m) => m.def.map_flags,
201 }
202 }
203
204 pub const fn pinning(&self) -> PinningType {
206 match self {
207 Self::Legacy(m) => m.def.pinning,
208 Self::Btf(m) => m.def.pinning,
209 }
210 }
211
212 pub fn data(&self) -> &[u8] {
214 match self {
215 Self::Legacy(m) => &m.data,
216 Self::Btf(m) => &m.data,
217 }
218 }
219
220 pub fn data_mut(&mut self) -> &mut Vec<u8> {
222 match self {
223 Self::Legacy(m) => m.data.as_mut(),
224 Self::Btf(m) => m.data.as_mut(),
225 }
226 }
227
228 pub const fn section_index(&self) -> usize {
230 match self {
231 Self::Legacy(m) => m.section_index,
232 Self::Btf(m) => m.section_index,
233 }
234 }
235
236 pub const fn section_kind(&self) -> EbpfSectionKind {
238 match self {
239 Self::Legacy(m) => m.section_kind,
240 Self::Btf(_) => EbpfSectionKind::BtfMaps,
241 }
242 }
243
244 pub const fn symbol_index(&self) -> Option<usize> {
249 match self {
250 Self::Legacy(m) => m.symbol_index,
251 Self::Btf(m) => Some(m.symbol_index),
252 }
253 }
254
255 pub fn inner(&self) -> Option<Self> {
257 match self {
258 Self::Legacy(m) => m.inner_def.as_ref().map(|inner_def| {
259 Self::Legacy(LegacyMap {
260 def: *inner_def,
261 inner_def: None,
262 section_index: 0,
265 section_kind: EbpfSectionKind::Undefined,
266 symbol_index: None,
267 data: Vec::new(),
268 })
269 }),
270 Self::Btf(m) => m.inner_def.as_ref().map(|inner_def| {
271 Self::Btf(BtfMap {
272 def: *inner_def,
273 inner_def: None,
274 section_index: 0,
277 symbol_index: 0,
278 data: Vec::new(),
279 })
280 }),
281 }
282 }
283
284 pub const fn new_from_params(
286 map_type: u32,
287 key_size: u32,
288 value_size: u32,
289 max_entries: u32,
290 flags: u32,
291 ) -> Self {
292 Self::Legacy(LegacyMap {
293 def: bpf_map_def {
294 map_type,
295 key_size,
296 value_size,
297 max_entries,
298 map_flags: flags,
299 id: 0,
300 pinning: PinningType::None,
301 },
302 inner_def: None,
303 section_index: 0,
304 section_kind: EbpfSectionKind::Undefined,
305 symbol_index: None,
306 data: Vec::new(),
307 })
308 }
309}
310
311#[derive(Debug, Clone)]
316pub struct LegacyMap {
317 pub def: bpf_map_def,
319 pub inner_def: Option<bpf_map_def>,
321 pub section_index: usize,
323 pub section_kind: EbpfSectionKind,
325 pub symbol_index: Option<usize>,
331 pub data: Vec<u8>,
333}
334
335#[derive(Debug, Clone)]
337pub struct BtfMap {
338 pub def: BtfMapDef,
340 pub(crate) inner_def: Option<BtfMapDef>,
342 pub(crate) section_index: usize,
343 pub(crate) symbol_index: usize,
344 pub(crate) data: Vec<u8>,
345}