Skip to content

Commit

Permalink
Introduce code change for PR aya-rs#968 in order to verify tests are …
Browse files Browse the repository at this point in the history
…properly working
  • Loading branch information
martinsoees committed Jun 20, 2024
1 parent 37cdf66 commit cd6870f
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 7 deletions.
3 changes: 1 addition & 2 deletions aya-obj/src/relocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -541,9 +541,8 @@ fn insn_is_call(ins: &bpf_insn) -> bool {

#[cfg(test)]
mod test {
use std::os::fd::{AsRawFd, IntoRawFd, RawFd};

use alloc::{string::ToString, vec, vec::Vec};
use std::os::fd::RawFd;

use super::*;
use crate::maps::{BtfMap, LegacyMap};
Expand Down
84 changes: 79 additions & 5 deletions aya/src/bpf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ use thiserror::Error;

use crate::{
generated::{
bpf_map_type, bpf_map_type::*, AYA_PERF_EVENT_IOC_DISABLE, AYA_PERF_EVENT_IOC_ENABLE,
AYA_PERF_EVENT_IOC_SET_BPF,
bpf_map_type::{self, *},
AYA_PERF_EVENT_IOC_DISABLE, AYA_PERF_EVENT_IOC_ENABLE, AYA_PERF_EVENT_IOC_SET_BPF,
},
maps::{Map, MapData, MapError},
obj::{
Expand Down Expand Up @@ -137,6 +137,8 @@ pub struct EbpfLoader<'a> {
extensions: HashSet<&'a str>,
verifier_log_level: VerifierLogLevel,
allow_unsupported_maps: bool,
ignore_maps_by_type: HashSet<bpf_map_type>,
ignore_maps_by_name: &'a [&'a str],
}

/// Builder style API for advanced loading of eBPF programs.
Expand Down Expand Up @@ -175,6 +177,8 @@ impl<'a> EbpfLoader<'a> {
extensions: HashSet::new(),
verifier_log_level: VerifierLogLevel::default(),
allow_unsupported_maps: false,
ignore_maps_by_type: HashSet::new(),
ignore_maps_by_name: &[],
}
}

Expand Down Expand Up @@ -224,6 +228,62 @@ impl<'a> EbpfLoader<'a> {
self
}

/// Allows programs containing unsupported maps for the current kernel to be loaded
/// by skipping map creation and relocation before loading.
///
/// This is useful when you have a single ebpf program containing e.g. a `RingBuf`
/// and a `PerfEventArray` and you decide which one to use before loading the bytecode.
///
/// Must be used with `.set_global()` to signal if the map is supported in the ebpf program.
///
/// # Example
///
/// ```no_run
/// use aya::EbpfLoader;
/// use aya_obj::generated::bpf_map_type;
/// use std::collections::HashSet;
///
/// let ringbuf_supported = 0;
/// let mut set = HashSet::new();
/// set.insert(bpf_map_type::BPF_MAP_TYPE_RINGBUF);
/// let ebpf = EbpfLoader::new()
/// .ignore_maps_by_type(set)
/// .set_global("RINGBUF_SUPPORTED", &ringbuf_supported, true)
/// .load_file("file.o")?;
/// # Ok::<(), aya::EbpfError>(())
/// ```
///
pub fn ignore_maps_by_type(&mut self, set: HashSet<bpf_map_type>) -> &mut Self {
self.ignore_maps_by_type = set;
self
}

/// Allows programs containing unsupported maps for the current kernel to be loaded
/// by skipping map creation and relocation before loading.
///
/// This is useful when you have a single ebpf program containing e.g. a `RingBuf`
/// and a `PerfEventArray` and you decide which one to use before loading the bytecode.
///
/// Must be used with `.set_global()` to signal if the map is supported in the ebpf program.
///
/// # Example
///
/// ```no_run
/// use aya::EbpfLoader;
///
/// let ringbuf_supported = 0;
/// let ebpf = EbpfLoader::new()
/// .ignore_maps_by_name(&["RINGBUF"])
/// .set_global("RINGBUF_SUPPORTED", &ringbuf_supported, true)
/// .load_file("file.o")?;
/// # Ok::<(), aya::EbpfError>(())
/// ```
///
pub fn ignore_maps_by_name(&mut self, name: &'a [&'a str]) -> &mut Self {
self.ignore_maps_by_name = name;
self
}

/// Sets the base directory path for pinned maps.
///
/// Pinned maps will be loaded from `path/MAP_NAME`.
Expand Down Expand Up @@ -394,6 +454,8 @@ impl<'a> EbpfLoader<'a> {
extensions,
verifier_log_level,
allow_unsupported_maps,
ignore_maps_by_type,
ignore_maps_by_name,
} = self;
let mut obj = Object::parse(data)?;
obj.patch_map_data(globals.clone())?;
Expand Down Expand Up @@ -459,12 +521,25 @@ impl<'a> EbpfLoader<'a> {
obj.relocate_btf(btf)?;
}
let mut maps = HashMap::new();
let mut ignored_maps = HashMap::new();

for (name, mut obj) in obj.maps.drain() {
if let (false, EbpfSectionKind::Bss | EbpfSectionKind::Data | EbpfSectionKind::Rodata) =
(FEATURES.bpf_global_data(), obj.section_kind())
{
continue;
}
let map_type: bpf_map_type = obj.map_type().try_into().map_err(MapError::from)?;

if ignore_maps_by_type.contains(&map_type)
|| ignore_maps_by_name.contains(&name.as_str())
{
ignored_maps.insert(name, obj);
// ignore map creation. The map is saved in `ignored_maps` and filtered out
// in `relocate_maps()` later on
continue;
}

let num_cpus = || -> Result<u32, EbpfError> {
Ok(possible_cpus()
.map_err(|error| EbpfError::FileError {
Expand All @@ -473,7 +548,6 @@ impl<'a> EbpfLoader<'a> {
})?
.len() as u32)
};
let map_type: bpf_map_type = obj.map_type().try_into().map_err(MapError::from)?;
if let Some(max_entries) = max_entries_override(
map_type,
max_entries.get(name.as_str()).copied(),
Expand All @@ -498,7 +572,7 @@ impl<'a> EbpfLoader<'a> {
PinningType::ByName => {
// pin maps in /sys/fs/bpf by default to align with libbpf
// behavior https://github.com/libbpf/libbpf/blob/v1.2.2/src/libbpf.c#L2161.
let path = map_pin_path
let path: &Path = map_pin_path
.as_deref()
.unwrap_or_else(|| Path::new("/sys/fs/bpf"));

Expand All @@ -508,7 +582,6 @@ impl<'a> EbpfLoader<'a> {
map.finalize()?;
maps.insert(name, map);
}

let text_sections = obj
.functions
.keys()
Expand All @@ -519,6 +592,7 @@ impl<'a> EbpfLoader<'a> {
maps.iter()
.map(|(s, data)| (s.as_str(), data.fd().as_fd().as_raw_fd(), data.obj())),
&text_sections,
&ignored_maps,
)?;
obj.relocate_calls(&text_sections)?;
obj.sanitize_functions(&FEATURES);
Expand Down

0 comments on commit cd6870f

Please sign in to comment.