You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
use anyhow::Context;
use aya::programs::{Xdp, XdpFlags};
use aya::maps::bloom_filter::BloomFilter;
use aya::{include_bytes_aligned, Bpf};
use aya_log::BpfLogger;
use clap::Parser;
use log::{info, warn, debug};
use tokio::signal;
#[derive(Debug, Parser)]
struct Opt {
#[clap(short, long, default_value = "enp2s0")]
iface: String,
}
#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
let opt = Opt::parse();
env_logger::init();
// Bump the memlock rlimit. This is needed for older kernels that don't use the
// new memcg based accounting, see https://lwn.net/Articles/837122/
let rlim = libc::rlimit {
rlim_cur: libc::RLIM_INFINITY,
rlim_max: libc::RLIM_INFINITY,
};
let ret = unsafe { libc::setrlimit(libc::RLIMIT_MEMLOCK, &rlim) };
if ret != 0 {
debug!("remove limit on locked memory failed, ret is: {}", ret);
}
// This will include your eBPF object file as raw bytes at compile-time and load it at
// runtime. This approach is recommended for most real-world use cases. If you would
// like to specify the eBPF program at runtime rather than at compile-time, you can
// reach for `Bpf::load_file` instead.
#[cfg(debug_assertions)]
let mut bpf = Bpf::load(include_bytes_aligned!(
"../../target/bpfel-unknown-none/debug/myapp"
))?;
#[cfg(not(debug_assertions))]
let mut bpf = Bpf::load(include_bytes_aligned!(
"../../target/bpfel-unknown-none/release/myapp"
))?;
if let Err(e) = BpfLogger::init(&mut bpf) {
// This can happen if you remove all log statements from your eBPF program.
warn!("failed to initialize eBPF logger: {}", e);
}
let program: &mut Xdp = bpf.program_mut("myapp").unwrap().try_into()?;
program.load()?;
program.attach(&opt.iface, XdpFlags::default())
.context("failed to attach the XDP program with default flags - try changing XdpFlags::default() to XdpFlags::SKB_MODE")?;
info!("Loading bloom filter");
let mut bloom_filter = BloomFilter::try_from(bpf.map_mut("MYFILTER").unwrap())?;
bloom_filter.insert(1,0)?;
assert!(bloom_filter.contains(&1, 0).is_ok());
info!("Waiting for Ctrl-C...");
signal::ctrl_c().await?;
info!("Exiting...");
Ok(())
}
What I figured out so far is that the kernel does not read the correct value from the provided user space address. I have no idea why this is happening..
I also tested to add a value from the ebpf-program to the bloom filter and check from the userspace if the value is present which worked! Also inserting from userspace and checking from the ebpf-program if the value is present works as well. The only combination that did not work is inserting from userspace and calling contains from userspace.
I found a temporary work-around for me by adding a second version of bpf_map_lookup_elem_ptr function and adjusting the bloom_filter contains function.
// In aya/src/sys/bpf.rs
pub(crate) fn bpf_map_lookup_elem_ptr1<K: Pod, V>(
fd: BorrowedFd<'_>,
key: Option<&K>,
value: *const V, // Note the const here - the only difference to the original function
flags: u64,
) -> SysResult<Option<()>> {
let mut attr = unsafe { mem::zeroed::<bpf_attr>() };
let u = unsafe { &mut attr.__bindgen_anon_2 };
u.map_fd = fd.as_raw_fd() as u32;
if let Some(key) = key {
u.key = key as *const _ as u64;
}
u.__bindgen_anon_1.value = value as u64;
u.flags = flags;
match sys_bpf(bpf_cmd::BPF_MAP_LOOKUP_ELEM, &mut attr) {
Ok(_) => Ok(Some(())),
Err((_, io_error)) if io_error.raw_os_error() == Some(ENOENT) => Ok(None),
Err(e) => Err(e),
}
}
// In aya/src/maps/bloom_filter.rs
pub fn contains(&self, value: impl Borrow<V>, flags: u64) -> Result<(), MapError> {
let fd = self.inner.borrow().fd().as_fd();
bpf_map_lookup_elem_ptr1::<u32, _>(fd, None, value.borrow(), flags)
.map_err(|(_, io_error)| SyscallError {
call: "bpf_map_lookup_elem",
io_error,
})?.ok_or(MapError::ElementNotFound)?;
Ok(())
}
I would be grateful if someone could confirm this bug or point out what I am doing wrong.
Also any ideas how to fix this or how to debug it are very welcome!
Thanks a lot <3
The text was updated successfully, but these errors were encountered:
Hi,
I am having trouble to successfully execute the example code of the bloom_filter map:
The assert states that the item is not found. I want to use the bloom_filter it in an XDP program.
Steps to reproduce:
eBPF program:
Userspace program:
What I figured out so far is that the kernel does not read the correct value from the provided user space address. I have no idea why this is happening..
I also tested to add a value from the ebpf-program to the bloom filter and check from the userspace if the value is present which worked! Also inserting from userspace and checking from the ebpf-program if the value is present works as well. The only combination that did not work is inserting from userspace and calling contains from userspace.
I found a temporary work-around for me by adding a second version of
bpf_map_lookup_elem_ptr
function and adjusting the bloom_filter contains function.I would be grateful if someone could confirm this bug or point out what I am doing wrong.
Also any ideas how to fix this or how to debug it are very welcome!
Thanks a lot <3
The text was updated successfully, but these errors were encountered: