Skip to main content

profile_bee_aya_obj/
maps.rs

1//! Map struct and type bindings.
2
3use 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/// BTF definition of a map
62#[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    /// BTF type id of the map key
71    pub btf_key_type_id: u32,
72    /// BTF type id of the map value
73    pub btf_value_type_id: u32,
74}
75
76/// The pinning type
77///
78/// Upon pinning a map, a file representation is created for the map,
79/// so that the map can be alive and retrievable across sessions.
80#[repr(u32)]
81#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
82pub enum PinningType {
83    /// No pinning
84    #[default]
85    None = 0,
86    /// Pin by the name
87    ByName = 1,
88}
89
90/// The error type returned when failing to parse a [`PinningType`].
91#[derive(Debug, thiserror::Error)]
92pub enum PinningError {
93    /// Unsupported pinning type
94    #[error("unsupported pinning type `{pinning_type}`")]
95    Unsupported {
96        /// The unsupported pinning type
97        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/// Map definition in legacy BPF map declaration style
114#[repr(C)]
115#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
116pub struct bpf_map_def {
117    // minimum features required by old BPF programs
118    /// The map type
119    pub map_type: u32,
120    /// The key size
121    pub key_size: u32,
122    /// The value size
123    pub value_size: u32,
124    /// Max entry number
125    pub max_entries: u32,
126    /// Map flags
127    pub map_flags: u32,
128    // optional features
129    /// Id
130    pub id: u32,
131    /// Pinning type
132    pub pinning: PinningType,
133}
134
135/// The first five __u32 of `bpf_map_def` must be defined.
136pub(crate) const MINIMUM_MAP_SIZE: usize = size_of::<u32>() * 5;
137
138/// Map data defined in `maps` or `.maps` sections
139#[derive(Debug, Clone)]
140pub enum Map {
141    /// A map defined in the `maps` section
142    Legacy(LegacyMap),
143    /// A map defined in the `.maps` section
144    Btf(BtfMap),
145}
146
147impl Map {
148    /// Returns the map type
149    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    /// Returns the key size in bytes
157    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    /// Returns the value size in bytes
165    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    /// Set the value size in bytes
173    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    /// Returns the max entry number
181    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    /// Sets the max entry number
189    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    /// Returns the map flags
197    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    /// Returns the pinning type of the map
205    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    /// Returns the map data
213    pub fn data(&self) -> &[u8] {
214        match self {
215            Self::Legacy(m) => &m.data,
216            Self::Btf(m) => &m.data,
217        }
218    }
219
220    /// Returns the map data as mutable
221    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    /// Returns the section index
229    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    /// Returns the section kind.
237    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    /// Returns the symbol index.
245    ///
246    /// This is `None` for data maps (.bss, .data and .rodata) since those don't
247    /// need symbols in order to be relocated.
248    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    /// Returns the inner map definition, in case of a map of maps.
256    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                    // The inner map is a synthetic object with no ELF presence
263                    // of its own, so use neutral metadata values.
264                    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                    // The inner map is a synthetic object with no ELF presence
275                    // of its own, so use neutral metadata values.
276                    section_index: 0,
277                    symbol_index: 0,
278                    data: Vec::new(),
279                })
280            }),
281        }
282    }
283
284    /// Creates a new map definition from raw parameters.
285    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/// A map declared with legacy BPF map declaration style, most likely from a `maps` section.
312///
313/// See [Drop support for legacy BPF map declaration syntax - Libbpf: the road to v1.0](https://github.com/libbpf/libbpf/wiki/Libbpf:-the-road-to-v1.0#drop-support-for-legacy-bpf-map-declaration-syntax)
314/// for more info.
315#[derive(Debug, Clone)]
316pub struct LegacyMap {
317    /// The definition of the map
318    pub def: bpf_map_def,
319    /// The definition of the inner map, in case of a map of maps.
320    pub inner_def: Option<bpf_map_def>,
321    /// The section index
322    pub section_index: usize,
323    /// The section kind
324    pub section_kind: EbpfSectionKind,
325    /// The symbol index.
326    ///
327    /// This is None for data maps (.bss .data and .rodata).  We don't need
328    /// symbols to relocate those since they don't contain multiple maps, but
329    /// are just a flat array of bytes.
330    pub symbol_index: Option<usize>,
331    /// The map data
332    pub data: Vec<u8>,
333}
334
335/// A BTF-defined map, most likely from a `.maps` section.
336#[derive(Debug, Clone)]
337pub struct BtfMap {
338    /// The definition of the map
339    pub def: BtfMapDef,
340    /// The definition of the inner map, in case of a map of maps.
341    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}