Skip to content

Commit

Permalink
integration-test: Add map pinning coverage
Browse files Browse the repository at this point in the history
Add coverage to the new public api's for
map pinning (pin and unpin) which can be called
on the generic aya::Map type OR explit map types.

Additionally add coverage for the new libbpf
LIBBPF_PIN_BY_NAME behavior.

Signed-off-by: astoycos <astoycos@redhat.com>
  • Loading branch information
astoycos committed Oct 10, 2023
1 parent 7b71c7e commit 8203914
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 10 deletions.
11 changes: 11 additions & 0 deletions test/integration-test/bpf/multimap-btf.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,24 @@ struct {
__uint(max_entries, 1);
} map_2 SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, __u32);
__type(value, __u64);
__uint(max_entries, 1);
__uint(pinning, LIBBPF_PIN_BY_NAME);
} map_pin_by_name SEC(".maps");

SEC("uprobe")
int bpf_prog(void *ctx) {
__u32 key = 0;
__u64 twenty_four = 24;
__u64 forty_two = 42;
__u64 forty_four = 44;

bpf_map_update_elem(&map_1, &key, &twenty_four, BPF_ANY);
bpf_map_update_elem(&map_2, &key, &forty_two, BPF_ANY);
bpf_map_update_elem(&map_pin_by_name, &key, &forty_four, BPF_ANY);
return 0;
}

Expand Down
70 changes: 70 additions & 0 deletions test/integration-test/src/tests/load.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::{
convert::TryInto as _,
fs::remove_file,
path::Path,
thread,
time::{Duration, SystemTime},
};
Expand Down Expand Up @@ -40,6 +42,8 @@ fn multiple_btf_maps() {

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();

let prog: &mut UProbe = bpf.program_mut("bpf_prog").unwrap().try_into().unwrap();
prog.load().unwrap();
Expand All @@ -51,9 +55,75 @@ fn multiple_btf_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 map_pin = Path::new("/sys/fs/bpf/map_pin_by_name");
assert!(&map_pin.exists());

remove_file(map_pin).unwrap();
}

#[test]
fn pin_lifecycle_multiple_btf_maps() {
let mut bpf = Bpf::load(crate::MULTIMAP_BTF).unwrap();

// "map_pin_by_name" should already be pinned, unpin and pin again later
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();

// 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.
if name.contains(".rodata") || name.contains(".bss") {
continue;
}
let map_pin_path = &Path::new("/sys/fs/bpf/").join(i.to_string());

map.pin(map_pin_path).unwrap();

assert!(map_pin_path.exists());
remove_file(map_pin_path).unwrap();
}

let mut map_1: Array<_, u64> = bpf.take_map("map_1").unwrap().try_into().unwrap();
let mut map_2: Array<_, u64> = bpf.take_map("map_2").unwrap().try_into().unwrap();
let mut map_pin_by_name: Array<_, u64> =
bpf.take_map("map_pin_by_name").unwrap().try_into().unwrap();

let prog: &mut UProbe = bpf.program_mut("bpf_prog").unwrap().try_into().unwrap();
prog.load().unwrap();
prog.attach(Some("trigger_bpf_program"), 0, "/proc/self/exe", None)
.unwrap();

trigger_bpf_program();

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 map_1_pin_path = Path::new("/sys/fs/bpf/map_1");
let map_2_pin_path = Path::new("/sys/fs/bpf/map_2");

map_1.pin(map_1_pin_path).unwrap();
map_2.pin(map_2_pin_path).unwrap();
map_pin_by_name.pin(map_pin_by_name_path).unwrap();
assert!(map_1_pin_path.exists());
assert!(map_2_pin_path.exists());
assert!(map_pin_by_name_path.exists());

remove_file(map_1_pin_path).unwrap();
remove_file(map_2_pin_path).unwrap();
remove_file(map_pin_by_name_path).unwrap();
}

#[no_mangle]
Expand Down
24 changes: 14 additions & 10 deletions test/integration-test/src/tests/rbpf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn run_with_rbpf() {
assert_eq!(vm.execute_program().unwrap(), XDP_PASS);
}

static mut MULTIMAP_MAPS: [*mut Vec<u64>; 2] = [null_mut(), null_mut()];
static mut MULTIMAP_MAPS: [*mut Vec<u64>; 3] = [null_mut(); 3];

#[test]
fn use_map_with_rbpf() {
Expand All @@ -47,11 +47,11 @@ fn use_map_with_rbpf() {
);

// Initialize maps:
// - fd: 0xCAFE00 or 0xCAFE01 (the 0xCAFE00 part is used to distinguish fds from indices),
// - fd: Bitwise OR of the map_id with 0xCAFE00 (used to distinguish fds from indices),
// - Note that rbpf does not convert fds into real pointers,
// so we keeps the pointers to our maps in MULTIMAP_MAPS, to be used in helpers.
let mut maps = HashMap::new();
let mut map_instances = vec![vec![0u64], vec![0u64]];
let mut map_instances = vec![vec![0u64], vec![0u64], vec![0u64]];
for (name, map) in object.maps.iter() {
assert_eq!(map.key_size(), size_of::<u32>() as u32);
assert_eq!(map.value_size(), size_of::<u64>() as u32);
Expand All @@ -60,8 +60,14 @@ fn use_map_with_rbpf() {
aya_obj::generated::bpf_map_type::BPF_MAP_TYPE_ARRAY as u32
);

let map_id = if name == "map_1" { 0 } else { 1 };
let fd = map_id as std::os::fd::RawFd | 0xCAFE00;
let map_id = match name.as_str() {
"map_1" => 0,
"map_2" => 1,
"map_pin_by_name" => 2,
n => panic!("Unexpected map: {n}"),
};

let fd = map_id as i32 | 0xCAFE00;
maps.insert(name.to_owned(), (fd, map.clone()));

unsafe {
Expand Down Expand Up @@ -102,18 +108,16 @@ fn use_map_with_rbpf() {
.expect("Helper failed");
assert_eq!(vm.execute_program().unwrap(), 0);

assert_eq!(map_instances[0][0], 24);
assert_eq!(map_instances[1][0], 42);
assert_eq!(map_instances, [[24], [42], [44]]);

unsafe {
MULTIMAP_MAPS[0] = null_mut();
MULTIMAP_MAPS[1] = null_mut();
MULTIMAP_MAPS.iter_mut().for_each(|v| *v = null_mut());
}
}

#[track_caller]
fn bpf_map_update_elem_multimap(map: u64, key: u64, value: u64, _: u64, _: u64) -> u64 {
assert_matches!(map, 0xCAFE00 | 0xCAFE01);
assert_matches!(map, 0xCAFE00 | 0xCAFE01 | 0xCAFE02);
let key = *unsafe { (key as usize as *const u32).as_ref().unwrap() };
let value = *unsafe { (value as usize as *const u64).as_ref().unwrap() };
assert_eq!(key, 0);
Expand Down

0 comments on commit 8203914

Please sign in to comment.