浏览代码

Merge pull request #520 from astoycos/unsupported-map

Add Unsupported Map type
Alessandro Decina 1 年之前
父节点
当前提交
eb60d65613
共有 2 个文件被更改,包括 71 次插入25 次删除
  1. 61 25
      aya/src/bpf.rs
  2. 10 0
      aya/src/maps/mod.rs

+ 61 - 25
aya/src/bpf.rs

@@ -13,7 +13,7 @@ use aya_obj::{
     relocation::BpfRelocationError,
     BpfSectionKind, Features,
 };
-use log::debug;
+use log::{debug, warn};
 use thiserror::Error;
 
 use crate::{
@@ -129,6 +129,7 @@ pub struct BpfLoader<'a> {
     max_entries: HashMap<&'a str, u32>,
     extensions: HashSet<&'a str>,
     verifier_log_level: VerifierLogLevel,
+    allow_unsupported_maps: bool,
 }
 
 bitflags! {
@@ -162,6 +163,7 @@ impl<'a> BpfLoader<'a> {
             max_entries: HashMap::new(),
             extensions: HashSet::new(),
             verifier_log_level: VerifierLogLevel::default(),
+            allow_unsupported_maps: false,
         }
     }
 
@@ -187,6 +189,30 @@ impl<'a> BpfLoader<'a> {
         self
     }
 
+    /// Allows programs containing unsupported maps to be loaded.
+    ///
+    /// By default programs containing unsupported maps will fail to load. This
+    /// method can be used to configure the loader so that unsupported maps will
+    /// be loaded, but won't be accessible from userspace. Can be useful when
+    /// using unsupported maps that are only accessed from eBPF code and don't
+    /// require any userspace interaction.
+    ///
+    /// # Example
+    ///
+    /// ```no_run
+    /// use aya::BpfLoader;
+    ///
+    /// let bpf = BpfLoader::new()
+    ///     .allow_unsupported_maps()
+    ///     .load_file("file.o")?;
+    /// # Ok::<(), aya::BpfError>(())
+    /// ```
+    ///
+    pub fn allow_unsupported_maps(&mut self) -> &mut BpfLoader<'a> {
+        self.allow_unsupported_maps = true;
+        self
+    }
+
     /// Sets the base directory path for pinned maps.
     ///
     /// Pinned maps will be loaded from `path/MAP_NAME`.
@@ -616,12 +642,21 @@ impl<'a> BpfLoader<'a> {
                 (name, program)
             })
             .collect();
-        let maps: Result<HashMap<String, Map>, BpfError> = maps.drain().map(parse_map).collect();
+        let maps = maps
+            .drain()
+            .map(parse_map)
+            .collect::<Result<HashMap<String, Map>, BpfError>>()?;
+
+        if !self.allow_unsupported_maps {
+            maps.iter().try_for_each(|(_, x)| match x {
+                Map::Unsupported(map) => Err(BpfError::MapError(MapError::Unsupported {
+                    map_type: map.obj.map_type(),
+                })),
+                _ => Ok(()),
+            })?;
+        };
 
-        Ok(Bpf {
-            maps: maps?,
-            programs,
-        })
+        Ok(Bpf { maps, programs })
     }
 }
 
@@ -633,25 +668,26 @@ fn parse_map(data: (String, MapData)) -> Result<(String, Map), BpfError> {
             map_type: e.map_type,
         })?;
     let map = match map_type {
-        BPF_MAP_TYPE_ARRAY => Ok(Map::Array(map)),
-        BPF_MAP_TYPE_PERCPU_ARRAY => Ok(Map::PerCpuArray(map)),
-        BPF_MAP_TYPE_PROG_ARRAY => Ok(Map::ProgramArray(map)),
-        BPF_MAP_TYPE_HASH => Ok(Map::HashMap(map)),
-        BPF_MAP_TYPE_LRU_HASH => Ok(Map::LruHashMap(map)),
-        BPF_MAP_TYPE_PERCPU_HASH => Ok(Map::PerCpuHashMap(map)),
-        BPF_MAP_TYPE_LRU_PERCPU_HASH => Ok(Map::PerCpuLruHashMap(map)),
-        BPF_MAP_TYPE_PERF_EVENT_ARRAY => Ok(Map::PerfEventArray(map)),
-        BPF_MAP_TYPE_SOCKHASH => Ok(Map::SockHash(map)),
-        BPF_MAP_TYPE_SOCKMAP => Ok(Map::SockMap(map)),
-        BPF_MAP_TYPE_BLOOM_FILTER => Ok(Map::BloomFilter(map)),
-        BPF_MAP_TYPE_LPM_TRIE => Ok(Map::LpmTrie(map)),
-        BPF_MAP_TYPE_STACK => Ok(Map::Stack(map)),
-        BPF_MAP_TYPE_STACK_TRACE => Ok(Map::StackTraceMap(map)),
-        BPF_MAP_TYPE_QUEUE => Ok(Map::Queue(map)),
-        m => Err(BpfError::MapError(MapError::InvalidMapType {
-            map_type: m as u32,
-        })),
-    }?;
+        BPF_MAP_TYPE_ARRAY => Map::Array(map),
+        BPF_MAP_TYPE_PERCPU_ARRAY => Map::PerCpuArray(map),
+        BPF_MAP_TYPE_PROG_ARRAY => Map::ProgramArray(map),
+        BPF_MAP_TYPE_HASH => Map::HashMap(map),
+        BPF_MAP_TYPE_LRU_HASH => Map::LruHashMap(map),
+        BPF_MAP_TYPE_PERCPU_HASH => Map::PerCpuHashMap(map),
+        BPF_MAP_TYPE_LRU_PERCPU_HASH => Map::PerCpuLruHashMap(map),
+        BPF_MAP_TYPE_PERF_EVENT_ARRAY => Map::PerfEventArray(map),
+        BPF_MAP_TYPE_SOCKHASH => Map::SockHash(map),
+        BPF_MAP_TYPE_SOCKMAP => Map::SockMap(map),
+        BPF_MAP_TYPE_BLOOM_FILTER => Map::BloomFilter(map),
+        BPF_MAP_TYPE_LPM_TRIE => Map::LpmTrie(map),
+        BPF_MAP_TYPE_STACK => Map::Stack(map),
+        BPF_MAP_TYPE_STACK_TRACE => Map::StackTraceMap(map),
+        BPF_MAP_TYPE_QUEUE => Map::Queue(map),
+        m => {
+            warn!("The map {name} is of type {:#?} which is currently unsupported in Aya, use `allow_unsupported_maps()` to load it anyways", m);
+            Map::Unsupported(map)
+        }
+    };
 
     Ok((name, map))
 }

+ 10 - 0
aya/src/maps/mod.rs

@@ -183,6 +183,13 @@ pub enum MapError {
         #[source]
         error: PinError,
     },
+
+    /// Unsupported Map type
+    #[error("Unsupported map type found {map_type}")]
+    Unsupported {
+        /// The map type
+        map_type: u32,
+    },
 }
 
 /// A map file descriptor.
@@ -262,6 +269,8 @@ pub enum Map {
     StackTraceMap(MapData),
     /// A [`Queue`] map
     Queue(MapData),
+    /// An unsupported map type
+    Unsupported(MapData),
 }
 
 impl Map {
@@ -283,6 +292,7 @@ impl Map {
             Map::Stack(map) => map.obj.map_type(),
             Map::StackTraceMap(map) => map.obj.map_type(),
             Map::Queue(map) => map.obj.map_type(),
+            Map::Unsupported(map) => map.obj.map_type(),
         }
     }
 }