I like to know how to create ebpf map with char array value
I tried like this
struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); __uint(key_size, sizeof(int)); __uint(value_size, sizeof(char)*10); __uint(max_entries, 2); } my_map SEC(".maps");
and this is full code for the ebpf program
#include <linux/version.h> #include <linux/bpf.h> #include <bpf/bpf_helpers.h> #include <linux/string.h> struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); __uint(key_size, sizeof(int)); __uint(value_size, sizeof(char)*10); __uint(max_entries, 2); } my_map SEC(".maps"); SEC("kprobe/__x64_sys_write") int bpf_prog1(struct pt_regs *ctx) { struct S { int pid; char cookie[10]; } data; data.pid = bpf_get_current_pid_tgid(); // data.cookie = 0x123; memcpy(data.cookie,"msg fwd",sizeof("msg fwd")); bpf_perf_event_output(ctx, &my_map, 0, &data, sizeof(data)); return 0; } char _license[] SEC("license") = "GPL"; int _version SEC("version") = 99;
and this is my user function I assigned to perf_buffer_opts
static void print_bpf_output(void *ctx, int cpu, void *data, __u32 size) { struct { int pid; char cookie[10]; } *e = data;
and this is the full code. so can anyone please tell what I am doing wrong why is saying invalid argument
libbpf: map 'my_map': failed to create: Invalid argument(-22) libbpf: failed to load object './trace_output_kern.o' ERROR: loading BPF object file failed root@
full userspace code
// SPDX-License-Identifier: GPL-2.0-only #include <stdio.h> #include <fcntl.h> #include <poll.h> #include <time.h> #include <signal.h> #include <bpf/libbpf.h> //create .o file root@this:/home/ubuntu/Desktop/ebpf/kern# clang -I /lib/modules/5.14.1/build -I /usr/include/bpf/ -O2 -Wall -c trace_output_user.c static __u64 time_get_ns(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return ts.tv_sec * 1000000000ull + ts.tv_nsec; } static __u64 start_time; static __u64 cnt; #define MAX_CNT 100000ll static void print_bpf_output(void *ctx, int cpu, void *data, __u32 size) { struct { int pid; char cookie[10]; } *e = data; if (e->cookie != 0x12345678) { printf("BUG pid %llx cookie %s sized %dn", e->pid, e->cookie, size); return; } cnt++; if (cnt == MAX_CNT) { printf("recv %lld events per secn", MAX_CNT * 1000000000ll / (time_get_ns() - start_time)); return; } } int main(int argc, char **argv) { struct perf_buffer_opts pb_opts = {}; struct bpf_link *link = NULL; struct bpf_program *prog; struct perf_buffer *pb; struct bpf_object *obj; int map_fd, ret = 0; char filename[256]; FILE *f; //snprintf(filename, sizeof(filename), "..o", argv[0]); obj = bpf_object__open_file("./trace_output_kern.o", NULL); if (libbpf_get_error(obj)) { fprintf(stderr, "ERROR: opening BPF object file failedn"); return 0; } /* load BPF program */ if (bpf_object__load(obj)) { fprintf(stderr, "ERROR: loading BPF object file failedn"); goto cleanup; } map_fd = bpf_object__find_map_fd_by_name(obj, "my_map"); if (map_fd < 0) { fprintf(stderr, "ERROR: finding a map in obj file failedn"); goto cleanup; } prog = bpf_object__find_program_by_name(obj, "bpf_prog1"); if (libbpf_get_error(prog)) { fprintf(stderr, "ERROR: finding a prog in obj file failedn"); goto cleanup; } link = bpf_program__attach(prog); if (libbpf_get_error(link)) { fprintf(stderr, "ERROR: bpf_program__attach failedn"); link = NULL; goto cleanup; } pb_opts.sample_cb = print_bpf_output; pb = perf_buffer__new(map_fd, 8, &pb_opts); ret = libbpf_get_error(pb); if (ret) { printf("failed to setup perf_buffer: %dn", ret); return 1; } f = popen("taskset 1 dd if=/dev/zero of=/dev/null", "r"); (void) f; start_time = time_get_ns(); while ((ret = perf_buffer__poll(pb, 1000)) >= 0 && cnt < MAX_CNT) { } kill(0, SIGINT); cleanup: bpf_link__destroy(link); bpf_object__close(obj); return ret; }
Advertisement
Answer
The key and value should be __u32
:
struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); __uint(key_size, sizeof(__u32)); __uint(value_size, sizeof(__u32)); } my_map SEC(".maps");
And you can then push your events to that map as usual:
bpf_perf_event_output(ctx, &my_map, 0, &data, sizeof(data));
The bpf_perf_event_output
helper takes the size of events as argument, so it doesn’t need to be a static parameter in the map.