bpf_rs/
map.rs

1use bpf_rs_macros::Display;
2#[cfg(feature = "serde")]
3use bpf_rs_macros::SerializeFromDisplay;
4
5use crate::{Error, StaticName};
6use libbpf_sys::libbpf_probe_bpf_map_type;
7use num_enum::{IntoPrimitive, TryFromPrimitive};
8use std::{fmt::Debug, ptr};
9
10/// eBPF map type variants. Based off of [kernel header's](https://github.com/torvalds/linux/blob/b253435746d9a4a701b5f09211b9c14d3370d0da/include/uapi/linux/bpf.h#L880)
11/// `enum bpf_map_type`
12#[non_exhaustive]
13#[repr(u32)]
14#[derive(Debug, Display, TryFromPrimitive, IntoPrimitive, Clone, Copy, PartialEq, Eq, Hash)]
15#[cfg_attr(feature = "serde", derive(SerializeFromDisplay))]
16pub enum MapType {
17    Unspec = 0,
18    Hash,
19    Array,
20    ProgArray,
21    PerfEventArray,
22    PerCpuHash,
23    PerCpuArray,
24    StackTrace,
25    CgroupArray,
26    LruHash,
27    LruPerCpuHash,
28    LpmTrie,
29    ArrayOfMaps,
30    HashOfMaps,
31    DevMap,
32    SockMap,
33    CpuMap,
34    XskMap,
35    SockHash,
36    CgroupStorage,
37    ReusePortSockArray,
38    PerCpuCgroupStorage,
39    Queue,
40    Stack,
41    SkStorage,
42    DevMapHash,
43    StructOps,
44    RingBuf,
45    InodeStorage,
46    TaskStorage,
47    BloomFilter,
48}
49
50impl MapType {
51    /// Determines if the eBPF map type is supported on the current platform
52    pub fn probe(&self) -> Result<bool, Error> {
53        match unsafe { libbpf_probe_bpf_map_type((*self).into(), ptr::null()) } {
54            negative if negative < 0 => Err(Error::Code(negative)),
55            0 => Ok(false),
56            1 => Ok(true),
57            positive if positive > 1 => Err(Error::Unknown(positive)),
58            _ => unreachable!(),
59        }
60    }
61
62    /// Returns an ordered iterator over the MapType variants. The order is determined by the kernel
63    /// header's [enum values](https://github.com/torvalds/linux/blob/b253435746d9a4a701b5f09211b9c14d3370d0da/include/uapi/linux/bpf.h#L880).
64    ///
65    /// **Note**: Skips [`MapType::Unspec`] since it's an invalid map type
66    pub fn iter() -> impl Iterator<Item = MapType> {
67        MapTypeIter(1)
68    }
69}
70
71impl StaticName for MapType {
72    /// Based off of bpftool's
73    /// [`map_type_name`](https://github.com/libbpf/bpftool/blob/9443d42430017ed2d04d7ab411131525ced62d6a/src/map.c#L25),
74    /// returns a human-readable name of the eBPF map type.
75    fn name(&self) -> &'static str {
76        match *self {
77            MapType::Unspec => "unspec",
78            MapType::Hash => "hash",
79            MapType::Array => "array",
80            MapType::ProgArray => "prog_array",
81            MapType::PerfEventArray => "perf_event_array",
82            MapType::PerCpuHash => "percpu_hash",
83            MapType::PerCpuArray => "percpu_array",
84            MapType::StackTrace => "stack_trace",
85            MapType::CgroupArray => "cgroup_array",
86            MapType::LruHash => "lru_hash",
87            MapType::LruPerCpuHash => "lru_percpu_hash",
88            MapType::LpmTrie => "lpm_trie",
89            MapType::ArrayOfMaps => "array_of_maps",
90            MapType::HashOfMaps => "hash_of_maps",
91            MapType::DevMap => "devmap",
92            MapType::SockMap => "sockmap",
93            MapType::CpuMap => "cpumap",
94            MapType::XskMap => "xskmap",
95            MapType::SockHash => "sockhash",
96            MapType::CgroupStorage => "cgroup_storage",
97            MapType::ReusePortSockArray => "reuseport_sockarray",
98            MapType::PerCpuCgroupStorage => "percpu_cgroup_storage",
99            MapType::Queue => "queue",
100            MapType::Stack => "stack",
101            MapType::SkStorage => "sk_storage",
102            MapType::DevMapHash => "devmap_hash",
103            MapType::StructOps => "struct_ops",
104            MapType::RingBuf => "ringbuf",
105            MapType::InodeStorage => "inode_storage",
106            MapType::TaskStorage => "task_storage",
107            MapType::BloomFilter => "bloom_filter",
108        }
109    }
110}
111
112struct MapTypeIter(u32);
113
114impl Iterator for MapTypeIter {
115    type Item = MapType;
116
117    fn next(&mut self) -> Option<Self::Item> {
118        let next = self.0;
119        if next > MapType::BloomFilter.into() {
120            None
121        } else {
122            self.0 += 1;
123            MapType::try_from_primitive(next).ok()
124        }
125    }
126}