aya_obj/
maps.rs

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