|
@@ -1,4 +1,10 @@
|
|
|
-use std::{convert::TryInto as _, fs::remove_file, path::Path, thread, time::Duration};
|
|
|
+use std::{
|
|
|
+ convert::TryInto as _,
|
|
|
+ fs::{create_dir, remove_dir_all, remove_file},
|
|
|
+ path::Path,
|
|
|
+ thread,
|
|
|
+ time::Duration,
|
|
|
+};
|
|
|
|
|
|
use aya::{
|
|
|
maps::Array,
|
|
@@ -7,7 +13,7 @@ use aya::{
|
|
|
loaded_links, loaded_programs, KProbe, TracePoint, UProbe, Xdp, XdpFlags,
|
|
|
},
|
|
|
util::KernelVersion,
|
|
|
- Ebpf,
|
|
|
+ Ebpf, EbpfLoader,
|
|
|
};
|
|
|
use aya_obj::programs::XdpAttachType;
|
|
|
use test_log::test;
|
|
@@ -73,7 +79,7 @@ fn pin_lifecycle_multiple_btf_maps() {
|
|
|
|
|
|
// pin and unpin all maps before casting to explicit types
|
|
|
for (i, (name, map)) in bpf.maps_mut().enumerate() {
|
|
|
- // Don't pin system maps or the map that's already pinned by name.
|
|
|
+ // Don't pin system maps.
|
|
|
if name.contains(".rodata") || name.contains(".bss") {
|
|
|
continue;
|
|
|
}
|
|
@@ -121,6 +127,83 @@ fn pin_lifecycle_multiple_btf_maps() {
|
|
|
remove_file(map_pin_by_name_path).unwrap();
|
|
|
}
|
|
|
|
|
|
+#[test]
|
|
|
+fn pin_lifecycle_sharing_btf_maps() {
|
|
|
+ let map_pin_path = Path::new("/sys/fs/bpf/map-sharing-test");
|
|
|
+ if map_pin_path.exists() {
|
|
|
+ remove_dir_all(map_pin_path).unwrap();
|
|
|
+ }
|
|
|
+ create_dir(map_pin_path).unwrap();
|
|
|
+
|
|
|
+ let mut loader = EbpfLoader::new();
|
|
|
+
|
|
|
+ let mut bpf = loader.load(crate::MULTIMAP_BTF).unwrap();
|
|
|
+
|
|
|
+ // "map_pin_by_name" should already be pinned at the default bpffs.
|
|
|
+ let map_pin_by_name_path = Path::new("/sys/fs/bpf/map_pin_by_name");
|
|
|
+
|
|
|
+ assert!(map_pin_by_name_path.exists());
|
|
|
+ remove_file(map_pin_by_name_path).unwrap();
|
|
|
+
|
|
|
+ for (name, map) in bpf.maps_mut() {
|
|
|
+ // Don't pin system maps.
|
|
|
+ if name.contains(".rodata") || name.contains(".bss") {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Pin the map by it's name.
|
|
|
+ map.pin(map_pin_path.join(name)).unwrap();
|
|
|
+ assert!(map_pin_path.exists());
|
|
|
+ }
|
|
|
+
|
|
|
+ // Load the same program using the existing maps at map_pin_path.
|
|
|
+ let mut bpf1 = loader
|
|
|
+ .map_pin_path(map_pin_path)
|
|
|
+ .load(crate::MULTIMAP_BTF)
|
|
|
+ .unwrap();
|
|
|
+
|
|
|
+ // Get the maps from the first program.
|
|
|
+ let map_1: Array<_, u64> = bpf.take_map("map_1").unwrap().try_into().unwrap();
|
|
|
+ let map_2: Array<_, u64> = bpf.take_map("map_2").unwrap().try_into().unwrap();
|
|
|
+ let map_pin_by_name: Array<_, u64> =
|
|
|
+ bpf.take_map("map_pin_by_name").unwrap().try_into().unwrap();
|
|
|
+
|
|
|
+ // Attach both programs so they can be triggered.
|
|
|
+ let prog: &mut UProbe = bpf.program_mut("bpf_prog").unwrap().try_into().unwrap();
|
|
|
+ prog.load().unwrap();
|
|
|
+ prog.attach("trigger_bpf_program", "/proc/self/exe", None, None)
|
|
|
+ .unwrap();
|
|
|
+
|
|
|
+ let prog1: &mut UProbe = bpf1.program_mut("bpf_prog1").unwrap().try_into().unwrap();
|
|
|
+ prog1.load().unwrap();
|
|
|
+ prog1
|
|
|
+ .attach("trigger_bpf_program", "/proc/self/exe", None, None)
|
|
|
+ .unwrap();
|
|
|
+
|
|
|
+ trigger_bpf_program();
|
|
|
+
|
|
|
+ // Ensure both program's updated the same maps.
|
|
|
+ let key = 0;
|
|
|
+ let val_1 = map_1.get(&key, 0).unwrap();
|
|
|
+ let val_2 = map_2.get(&key, 0).unwrap();
|
|
|
+ let val_3 = map_pin_by_name.get(&key, 0).unwrap();
|
|
|
+
|
|
|
+ assert_eq!(val_1, 24);
|
|
|
+ assert_eq!(val_2, 42);
|
|
|
+ assert_eq!(val_3, 44);
|
|
|
+
|
|
|
+ let key = 1;
|
|
|
+ let val_1 = map_1.get(&key, 0).unwrap();
|
|
|
+ let val_2 = map_2.get(&key, 0).unwrap();
|
|
|
+ let val_3 = map_pin_by_name.get(&key, 0).unwrap();
|
|
|
+
|
|
|
+ assert_eq!(val_1, 35);
|
|
|
+ assert_eq!(val_2, 53);
|
|
|
+ assert_eq!(val_3, 55);
|
|
|
+
|
|
|
+ remove_dir_all(map_pin_path).unwrap()
|
|
|
+}
|
|
|
+
|
|
|
#[no_mangle]
|
|
|
#[inline(never)]
|
|
|
pub extern "C" fn trigger_bpf_program() {
|