ソースを参照

fix(aya): Set PerfEventArray max_entries to nCPUs

Both libbpf and cilium/ebpf have will set the max_entries of a
BPF_MAP_TYPE_PERF_EVENT_ARRAY to the number of online CPUs if
it was omitted at map definition time. This adds that same
logic to Aya.

Signed-off-by: Dave Tucker <[email protected]>
Dave Tucker 7 ヶ月 前
コミット
25d986a26d
3 ファイル変更27 行追加11 行削除
  1. 3 5
      aya/src/maps/bloom_filter.rs
  2. 3 5
      aya/src/maps/lpm_trie.rs
  3. 21 1
      aya/src/sys/bpf.rs

+ 3 - 5
aya/src/maps/bloom_filter.rs

@@ -88,7 +88,7 @@ mod tests {
     use crate::{
         generated::{
             bpf_cmd,
-            bpf_map_type::{BPF_MAP_TYPE_BLOOM_FILTER, BPF_MAP_TYPE_PERF_EVENT_ARRAY},
+            bpf_map_type::{BPF_MAP_TYPE_ARRAY, BPF_MAP_TYPE_BLOOM_FILTER},
         },
         maps::{
             test_utils::{self, new_map},
@@ -120,10 +120,8 @@ mod tests {
 
     #[test]
     fn test_try_from_wrong_map() {
-        let map = new_map(test_utils::new_obj_map::<u32>(
-            BPF_MAP_TYPE_PERF_EVENT_ARRAY,
-        ));
-        let map = Map::PerfEventArray(map);
+        let map = new_map(test_utils::new_obj_map::<u32>(BPF_MAP_TYPE_ARRAY));
+        let map = Map::Array(map);
 
         assert_matches!(
             BloomFilter::<_, u32>::try_from(&map),

+ 3 - 5
aya/src/maps/lpm_trie.rs

@@ -205,7 +205,7 @@ mod tests {
     use crate::{
         generated::{
             bpf_cmd,
-            bpf_map_type::{BPF_MAP_TYPE_LPM_TRIE, BPF_MAP_TYPE_PERF_EVENT_ARRAY},
+            bpf_map_type::{BPF_MAP_TYPE_ARRAY, BPF_MAP_TYPE_LPM_TRIE},
         },
         maps::{
             test_utils::{self, new_map},
@@ -249,10 +249,8 @@ mod tests {
 
     #[test]
     fn test_try_from_wrong_map() {
-        let map = new_map(test_utils::new_obj_map::<u32>(
-            BPF_MAP_TYPE_PERF_EVENT_ARRAY,
-        ));
-        let map = Map::PerfEventArray(map);
+        let map = new_map(test_utils::new_obj_map::<u32>(BPF_MAP_TYPE_ARRAY));
+        let map = Map::Array(map);
 
         assert_matches!(
             LpmTrie::<_, u32, u32>::try_from(&map),

+ 21 - 1
aya/src/sys/bpf.rs

@@ -30,7 +30,7 @@ use crate::{
         copy_instructions,
     },
     sys::{syscall, SysResult, Syscall, SyscallError},
-    util::KernelVersion,
+    util::{nr_cpus, KernelVersion},
     Btf, Pod, VerifierLogLevel, BPF_OBJ_NAME_LEN,
 };
 
@@ -46,6 +46,26 @@ pub(crate) fn bpf_create_map(
     u.map_type = def.map_type();
     u.key_size = def.key_size();
     u.value_size = def.value_size();
+    u.max_entries = def.max_entries();
+
+    // BPF_MAP_TYPE_PERF_EVENT_ARRAY's max_entries should not exceed the number of
+    // CPUs.
+    //
+    // By default, the newest versions of Aya, libbpf and cilium/ebpf define `max_entries` of
+    // `PerfEventArray` as `0`, with an intention to get it replaced with a correct value
+    // by the loader.
+    //
+    // We allow custom values (potentially coming either from older versions of aya-ebpf or
+    // programs written in C) as long as they don't exceed the number of CPUs.
+    //
+    // Otherwise, when the value is `0` or too large, we set it to the number of CPUs.
+    if def.map_type() == bpf_map_type::BPF_MAP_TYPE_PERF_EVENT_ARRAY as u32 {
+        let ncpus = nr_cpus().map_err(|e| (-1i64, e))? as u32;
+        if u.max_entries == 0 || u.max_entries > ncpus {
+            u.max_entries = ncpus;
+        }
+    };
+
     u.max_entries = def.max_entries();
     u.map_flags = def.map_flags();