Skip to main content

aya_obj/
maps.rs

1//! Map struct and type bindings.
2
3use crate::{EbpfSectionKind, InvalidTypeBinding, generated::bpf_map_type};
4
5impl TryFrom<u32> for bpf_map_type {
6    type Error = InvalidTypeBinding<u32>;
7
8    fn try_from(map_type: u32) -> Result<Self, Self::Error> {
9        Ok(match map_type {
10            x if x == Self::BPF_MAP_TYPE_UNSPEC as u32 => Self::BPF_MAP_TYPE_UNSPEC,
11            x if x == Self::BPF_MAP_TYPE_HASH as u32 => Self::BPF_MAP_TYPE_HASH,
12            x if x == Self::BPF_MAP_TYPE_ARRAY as u32 => Self::BPF_MAP_TYPE_ARRAY,
13            x if x == Self::BPF_MAP_TYPE_PROG_ARRAY as u32 => Self::BPF_MAP_TYPE_PROG_ARRAY,
14            x if x == Self::BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 => {
15                Self::BPF_MAP_TYPE_PERF_EVENT_ARRAY
16            }
17            x if x == Self::BPF_MAP_TYPE_PERCPU_HASH as u32 => Self::BPF_MAP_TYPE_PERCPU_HASH,
18            x if x == Self::BPF_MAP_TYPE_PERCPU_ARRAY as u32 => Self::BPF_MAP_TYPE_PERCPU_ARRAY,
19            x if x == Self::BPF_MAP_TYPE_STACK_TRACE as u32 => Self::BPF_MAP_TYPE_STACK_TRACE,
20            x if x == Self::BPF_MAP_TYPE_CGROUP_ARRAY as u32 => Self::BPF_MAP_TYPE_CGROUP_ARRAY,
21            x if x == Self::BPF_MAP_TYPE_LRU_HASH as u32 => Self::BPF_MAP_TYPE_LRU_HASH,
22            x if x == Self::BPF_MAP_TYPE_LRU_PERCPU_HASH as u32 => {
23                Self::BPF_MAP_TYPE_LRU_PERCPU_HASH
24            }
25            x if x == Self::BPF_MAP_TYPE_LPM_TRIE as u32 => Self::BPF_MAP_TYPE_LPM_TRIE,
26            x if x == Self::BPF_MAP_TYPE_ARRAY_OF_MAPS as u32 => Self::BPF_MAP_TYPE_ARRAY_OF_MAPS,
27            x if x == Self::BPF_MAP_TYPE_HASH_OF_MAPS as u32 => Self::BPF_MAP_TYPE_HASH_OF_MAPS,
28            x if x == Self::BPF_MAP_TYPE_DEVMAP as u32 => Self::BPF_MAP_TYPE_DEVMAP,
29            x if x == Self::BPF_MAP_TYPE_SOCKMAP as u32 => Self::BPF_MAP_TYPE_SOCKMAP,
30            x if x == Self::BPF_MAP_TYPE_CPUMAP as u32 => Self::BPF_MAP_TYPE_CPUMAP,
31            x if x == Self::BPF_MAP_TYPE_XSKMAP as u32 => Self::BPF_MAP_TYPE_XSKMAP,
32            x if x == Self::BPF_MAP_TYPE_SOCKHASH as u32 => Self::BPF_MAP_TYPE_SOCKHASH,
33            x if x == Self::BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED as u32 => {
34                Self::BPF_MAP_TYPE_CGROUP_STORAGE_DEPRECATED
35            }
36            x if x == Self::BPF_MAP_TYPE_REUSEPORT_SOCKARRAY as u32 => {
37                Self::BPF_MAP_TYPE_REUSEPORT_SOCKARRAY
38            }
39            x if x == Self::BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE_DEPRECATED as u32 => {
40                Self::BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE_DEPRECATED
41            }
42            x if x == Self::BPF_MAP_TYPE_QUEUE as u32 => Self::BPF_MAP_TYPE_QUEUE,
43            x if x == Self::BPF_MAP_TYPE_STACK as u32 => Self::BPF_MAP_TYPE_STACK,
44            x if x == Self::BPF_MAP_TYPE_SK_STORAGE as u32 => Self::BPF_MAP_TYPE_SK_STORAGE,
45            x if x == Self::BPF_MAP_TYPE_DEVMAP_HASH as u32 => Self::BPF_MAP_TYPE_DEVMAP_HASH,
46            x if x == Self::BPF_MAP_TYPE_STRUCT_OPS as u32 => Self::BPF_MAP_TYPE_STRUCT_OPS,
47            x if x == Self::BPF_MAP_TYPE_RINGBUF as u32 => Self::BPF_MAP_TYPE_RINGBUF,
48            x if x == Self::BPF_MAP_TYPE_INODE_STORAGE as u32 => Self::BPF_MAP_TYPE_INODE_STORAGE,
49            x if x == Self::BPF_MAP_TYPE_TASK_STORAGE as u32 => Self::BPF_MAP_TYPE_TASK_STORAGE,
50            x if x == Self::BPF_MAP_TYPE_BLOOM_FILTER as u32 => Self::BPF_MAP_TYPE_BLOOM_FILTER,
51            x if x == Self::BPF_MAP_TYPE_USER_RINGBUF as u32 => Self::BPF_MAP_TYPE_USER_RINGBUF,
52            x if x == Self::BPF_MAP_TYPE_CGRP_STORAGE as u32 => Self::BPF_MAP_TYPE_CGRP_STORAGE,
53            x if x == Self::BPF_MAP_TYPE_ARENA as u32 => Self::BPF_MAP_TYPE_ARENA,
54            _ => return Err(InvalidTypeBinding { value: map_type }),
55        })
56    }
57}
58
59/// BTF definition of a map
60#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
61pub struct BtfMapDef {
62    pub(crate) map_type: u32,
63    pub(crate) key_size: u32,
64    pub(crate) value_size: u32,
65    pub(crate) max_entries: u32,
66    pub(crate) map_flags: u32,
67    pub(crate) map_extra: u64,
68    pub(crate) pinning: PinningType,
69    /// BTF type id of the map key
70    pub btf_key_type_id: u32,
71    /// BTF type id of the map value
72    pub btf_value_type_id: u32,
73}
74
75/// The pinning type
76///
77/// Upon pinning a map, a file representation is created for the map,
78/// so that the map can be alive and retrievable across sessions.
79#[repr(u32)]
80#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
81pub enum PinningType {
82    /// No pinning
83    #[default]
84    None = 0,
85    /// Pin by the name
86    ByName = 1,
87}
88
89/// The error type returned when failing to parse a [`PinningType`].
90#[derive(Debug, thiserror::Error)]
91pub enum PinningError {
92    /// Unsupported pinning type
93    #[error("unsupported pinning type `{pinning_type}`")]
94    Unsupported {
95        /// The unsupported pinning type
96        pinning_type: u32,
97    },
98}
99
100impl TryFrom<u32> for PinningType {
101    type Error = PinningError;
102
103    fn try_from(value: u32) -> Result<Self, Self::Error> {
104        match value {
105            0 => Ok(Self::None),
106            1 => Ok(Self::ByName),
107            pinning_type => Err(PinningError::Unsupported { pinning_type }),
108        }
109    }
110}
111
112/// Map definition in legacy BPF map declaration style
113#[repr(C)]
114#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
115pub struct bpf_map_def {
116    // minimum features required by old BPF programs
117    /// The map type
118    pub map_type: u32,
119    /// The key size
120    pub key_size: u32,
121    /// The value size
122    pub value_size: u32,
123    /// Max entry number
124    pub max_entries: u32,
125    /// Map flags
126    pub map_flags: u32,
127    // optional features
128    /// Id
129    pub id: u32,
130    /// Pinning type
131    pub pinning: PinningType,
132}
133
134/// The first five __u32 of `bpf_map_def` must be defined.
135pub(crate) const MINIMUM_MAP_SIZE: usize = size_of::<u32>() * 5;
136
137/// Map data defined in `maps` or `.maps` sections
138#[derive(Debug, Clone)]
139pub enum Map {
140    /// A map defined in the `maps` section
141    Legacy(LegacyMap),
142    /// A map defined in the `.maps` section
143    Btf(BtfMap),
144}
145
146impl Map {
147    /// Returns the map type
148    pub const fn map_type(&self) -> u32 {
149        match self {
150            Self::Legacy(m) => m.def.map_type,
151            Self::Btf(m) => m.def.map_type,
152        }
153    }
154
155    /// Returns the key size in bytes
156    pub const fn key_size(&self) -> u32 {
157        match self {
158            Self::Legacy(m) => m.def.key_size,
159            Self::Btf(m) => m.def.key_size,
160        }
161    }
162
163    /// Returns the value size in bytes
164    pub const fn value_size(&self) -> u32 {
165        match self {
166            Self::Legacy(m) => m.def.value_size,
167            Self::Btf(m) => m.def.value_size,
168        }
169    }
170
171    /// Set the value size in bytes
172    pub const fn set_value_size(&mut self, size: u32) {
173        match self {
174            Self::Legacy(m) => m.def.value_size = size,
175            Self::Btf(m) => m.def.value_size = size,
176        }
177    }
178
179    /// Returns the max entry number
180    pub const fn max_entries(&self) -> u32 {
181        match self {
182            Self::Legacy(m) => m.def.max_entries,
183            Self::Btf(m) => m.def.max_entries,
184        }
185    }
186
187    /// Sets the max entry number
188    pub const fn set_max_entries(&mut self, v: u32) {
189        match self {
190            Self::Legacy(m) => m.def.max_entries = v,
191            Self::Btf(m) => m.def.max_entries = v,
192        }
193    }
194
195    /// Returns the map flags
196    pub const fn map_flags(&self) -> u32 {
197        match self {
198            Self::Legacy(m) => m.def.map_flags,
199            Self::Btf(m) => m.def.map_flags,
200        }
201    }
202
203    /// Returns per-map-type extra fields.
204    pub const fn map_extra(&self) -> u64 {
205        match self {
206            Self::Legacy(_) => 0,
207            Self::Btf(m) => m.def.map_extra,
208        }
209    }
210
211    /// Returns the pinning type of the map
212    pub const fn pinning(&self) -> PinningType {
213        match self {
214            Self::Legacy(m) => m.def.pinning,
215            Self::Btf(m) => m.def.pinning,
216        }
217    }
218
219    /// Returns the map data
220    pub fn data(&self) -> &[u8] {
221        match self {
222            Self::Legacy(m) => &m.data,
223            Self::Btf(m) => &m.data,
224        }
225    }
226
227    /// Returns the map data as mutable
228    pub fn data_mut(&mut self) -> &mut Vec<u8> {
229        match self {
230            Self::Legacy(m) => m.data.as_mut(),
231            Self::Btf(m) => m.data.as_mut(),
232        }
233    }
234
235    /// Returns the section index
236    pub const fn section_index(&self) -> usize {
237        match self {
238            Self::Legacy(m) => m.section_index,
239            Self::Btf(m) => m.section_index,
240        }
241    }
242
243    /// Returns the section kind.
244    pub const fn section_kind(&self) -> EbpfSectionKind {
245        match self {
246            Self::Legacy(m) => m.section_kind,
247            Self::Btf(_) => EbpfSectionKind::BtfMaps,
248        }
249    }
250
251    /// Returns the symbol index.
252    ///
253    /// This is `None` for data maps (.bss, .data and .rodata) since those don't
254    /// need symbols in order to be relocated.
255    pub const fn symbol_index(&self) -> Option<usize> {
256        match self {
257            Self::Legacy(m) => m.symbol_index,
258            Self::Btf(m) => Some(m.symbol_index),
259        }
260    }
261
262    /// Returns the inner map definition, in case of a map of maps.
263    ///
264    /// The inner map is a synthetic object with no ELF presence of its own,
265    /// so neutral metadata values are used.
266    pub fn inner(&self) -> Option<Self> {
267        match self {
268            Self::Legacy(m) => m.inner_def.as_ref().map(|inner_def| {
269                Self::Legacy(LegacyMap {
270                    def: *inner_def,
271                    inner_def: None,
272                    section_index: 0,
273                    section_kind: EbpfSectionKind::Undefined,
274                    symbol_index: None,
275                    data: Vec::new(),
276                })
277            }),
278            Self::Btf(m) => m.inner_def.as_ref().map(|inner_def| {
279                Self::Btf(BtfMap {
280                    def: *inner_def,
281                    inner_def: None,
282                    section_index: 0,
283                    symbol_index: 0,
284                    data: Vec::new(),
285                })
286            }),
287        }
288    }
289
290    /// Creates a new map definition from raw parameters.
291    pub const fn new_from_params(
292        map_type: u32,
293        key_size: u32,
294        value_size: u32,
295        max_entries: u32,
296        flags: u32,
297    ) -> Self {
298        Self::Legacy(LegacyMap {
299            def: bpf_map_def {
300                map_type,
301                key_size,
302                value_size,
303                max_entries,
304                map_flags: flags,
305                id: 0,
306                pinning: PinningType::None,
307            },
308            inner_def: None,
309            section_index: 0,
310            section_kind: EbpfSectionKind::Undefined,
311            symbol_index: None,
312            data: Vec::new(),
313        })
314    }
315}
316
317/// A map declared with legacy BPF map declaration style, most likely from a `maps` section.
318///
319/// 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)
320/// for more info.
321#[derive(Debug, Clone)]
322pub struct LegacyMap {
323    /// The definition of the map
324    pub def: bpf_map_def,
325    /// The definition of the inner map, in case of a map of maps.
326    pub inner_def: Option<bpf_map_def>,
327    /// The section index
328    pub section_index: usize,
329    /// The section kind
330    pub section_kind: EbpfSectionKind,
331    /// The symbol index.
332    ///
333    /// This is None for data maps (.bss .data and .rodata).  We don't need
334    /// symbols to relocate those since they don't contain multiple maps, but
335    /// are just a flat array of bytes.
336    pub symbol_index: Option<usize>,
337    /// The map data
338    pub data: Vec<u8>,
339}
340
341/// A BTF-defined map, most likely from a `.maps` section.
342#[derive(Debug, Clone)]
343pub struct BtfMap {
344    /// The definition of the map
345    pub def: BtfMapDef,
346    /// The definition of the inner map, in case of a map of maps.
347    pub(crate) inner_def: Option<BtfMapDef>,
348    pub(crate) section_index: usize,
349    pub(crate) symbol_index: usize,
350    pub(crate) data: Vec<u8>,
351}