Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

error: failed to create BPF_MAP_TYPE_ARRAY_OF_MAPS of BPF_MAP_TYPE_RINGBUF #934

Closed
Andreagit97 opened this issue Apr 20, 2024 · 2 comments
Closed

Comments

@Andreagit97
Copy link

Hi all, I was playing with aya library and I faced an error.

Context

In Falco we create an BPF_MAP_TYPE_ARRAY_OF_MAPS of BPF_MAP_TYPE_RINGBUF to send events to userspace since we need to support huge throughputs of events. What we usually do with the libbpf C library is:

  1. create the BPF_MAP_TYPE_ARRAY_OF_MAPS
  2. set an inner map inside it before the loading phase, using the libbpf API bpf_map__set_inner_map_fd
  3. create all the BPF_MAP_TYPE_RINGBUF we need and add them into BPF_MAP_TYPE_ARRAY_OF_MAPS

Issue

I'm not familiar with aya APIs so I tried something very simple to check what is supported.
First I created a simple C file with the ebpf code:

#include "vmlinux.h"
#include <bpf/bpf_helpers.h>

char LICENSE[] SEC("license") = "Dual BSD/GPL";

struct event
{
	char comm[16];
};

struct ringbuf_map
{
	__uint(type, BPF_MAP_TYPE_RINGBUF);
	__uint(max_entries, 8 * 1024 * 1024);
} ringbuf1 SEC(".maps"), ringbuf2 SEC(".maps");

struct
{
	__uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
	__uint(max_entries, 4);
	__type(key, int);
	__array(values, struct ringbuf_map);
} ringbuf_arr SEC(".maps") = {
	.values =
		{
			[0] = &ringbuf1,
			[2] = &ringbuf2,
		},
};

SEC("fexit/security_file_open")
int example(void *ctx)
{
	int cpu_id = 0;
	struct ringbuf_map *rb = (struct ringbuf_map *)bpf_map_lookup_elem(&ringbuf_arr, &cpu_id);
	if(!rb)
	{
		return 0;
	}

	struct event e = {0};
	if(bpf_get_current_comm(&e.comm, 16) < 0)
	{
		bpf_printk("failed to get current comm");
		return 0;
	}

	bpf_ringbuf_output(rb, &e, sizeof(e), BPF_RB_NO_WAKEUP);
	return 0;
}

I compiled it:

clang -O2 -target bpf -c ./ebpf/example.bpf.c -o ./ebpf/build/example.o -g

then i built a very simple loader in Rust to check that everything works:

use aya::Bpf;
fn main() -> Result<(), anyhow::Error> {
    let mut bpf = Bpf::load_file("/home/andrea/Desktop/aya_example/ebpf/build/bpf_map.o")?;
    Ok(())
}

The initial code was bigger but the issue seems in Bpf::load_file. This is the error I faced:

Error: map error: failed to create map `ringbuf_arr` with code -1

Caused by:
    0: failed to create map `ringbuf_arr` with code -1
    1: Invalid argument (os error 22)

Looking around the kernel with bpftrace the error seems related to the value_size of the map to be 0.

sudo bpftrace -e 'fexit:fd_array_map_alloc_check /comm == "aya_example" / { printf("ret value: %ld, attr_value: %d\n", retval, args->attr->value_size); }'

ret value: -22, attr_value: 0

It's the first time that I have used this library so maybe I'm missing something obvious... The same ebpf code I provided here works great with libbpf C library, so the issue seems in the loader.

@alessandrod
Copy link
Collaborator

We support ringbuf but we don't support array/hash of maps yet. We have a PR for it, but it needs to be rebased #70

I need this too exactly for the same purpose (a profiler that sends a lot of ringbuf records), so this is close to the top of my todo list, but feel free to take it from me if you want :)

@Andreagit97
Copy link
Author

Oh, I see, thank you for the quick feedback! I think i can close this :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants