简体   繁体   中英

I have a function call in one program and this function is depreciated.Is there any newer version that I can use in my code | perf_buffer__new in ebpf

I have this function which is depreciated. First how one can find the new alternative to functions that are depreciated. the function exist in libbpf library and perf_buffer__new is the exact name. so basically as the name suggest its used to create perf buffer to share info between userspace and kernel. First I like to know is perf buffers are only specific to ebpf filters or not. not means I can use perf buffers in anything. for example if I have some driver code so I just add perf buffer to have info shared between some userspace app and the driver. so some searching on the web I found it specifically link to ebpf, is this true?

So this is my code that uses call to perf_buffer__new but that function is depreciated, this function in libbpf's libbpf.h header file declarations is commented out

So I like to new what is the new alternative that I can use in my code, if there is a change in api then i like to let u know that I am trying share buffer parameter in SEC("kprobe/__x64_sys_recvfrom") to userspace for that I have used PT_REGS_PARM2 and bpf_probe_read_kernel to and included the parameter in map data. So if api is changed then how to accomplish this this is my userspace and ebpf program

Userspace.c

    // 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[90];
        char *buf;
        } *e = data;
        int i=0;
    printf("hello\n");
    
    printf(" _____________________________________________________%d \n________%s\n",e->pid,e->buf);
    i++;


    //printf("received map value = %s\n",e->cookie);
    /*if (e->cookie != 0x12345678) {
        printf("BUG pid %llx cookie %d sized %d\n",
               e->pid, e->cookie, size);
        return;
    }

    cnt++;

    if (cnt == MAX_CNT) {
        printf("recv %lld events per sec\n",
               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("./kprobe_send.o", NULL);
    if (libbpf_get_error(obj)) {
        fprintf(stderr, "ERROR: opening BPF object file failed\n");
        return 0;
    }

    /* load BPF program */
    if (bpf_object__load(obj)) {
        fprintf(stderr, "ERROR: loading BPF object file failed\n");
        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 failed\n");
        goto cleanup;
    }
    printf("before\n");
    prog = bpf_object__find_program_by_name(obj, "bpf_prog1");
    if (libbpf_get_error(prog)) {
        fprintf(stderr, "ERROR: finding a prog in obj file failed\n");
        goto cleanup;
    }
    printf("after\n");

    link = bpf_program__attach(prog);
        printf("after\n");
    if (libbpf_get_error(link)) {
        fprintf(stderr, "ERROR: bpf_program__attach failed\n");
        link = NULL;
        goto cleanup;
    }
    printf("after\n");
    pb_opts.sample_cb = print_bpf_output;
    pb = perf_buffer__new_deprecated(map_fd, 8, &pb_opts);//error
    printf("after\n");
    ret = libbpf_get_error(pb);
    if (ret) {
        printf("failed to setup perf_buffer: %d\n", 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;
}

Kernel.c

#include <linux/ptrace.h>
#include <linux/version.h>
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <string.h>
#include <sys/sendfile.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include </usr/include/bpf/bpf_tracing.h>
#include <linux/seccomp.h>
#define RAND_MAX 0x7fff
#define PERF_SAMPLE_RAW  1U << 0
#define randrange(N) rand() / (RAND_MAX/(N) + 1)
#define MAX 100000000        /* Values will be in the range (1 .. MAX) */


struct {
    __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
    __uint(key_size, sizeof(int));
    __uint(value_size, sizeof(int));
    __uint(max_entries, 100);
} my_map SEC(".maps");

SEC("kprobe/__x64_sys_recvfrom")
int bpf_prog1(struct pt_regs *ctx)
{

    static int vektor[100000000];
    int candidates[MAX];
    int i;
    long key;

    //srand(time(NULL));   /* Seed the random number generator. */

    /*for (i=0; i<MAX; i++)
    candidates[i] = i;

    for (i = 0; i < MAX-1; i++) {
        int c = randrange(MAX-i);
        int t = candidates[i];
        candidates[i] = candidates[i+c];
        candidates[i+c] = t;
    
    }
    
    for (i=0; i<10; i++)
    vektor[i] = candidates[i] + 1;*/
    struct S {
        int pid;
        char cookie[90];
        char *ptr;
        
    } data={1,""};
        //char *ptr =   PT_REGS_PARM2(ctx);
        
        
        struct seccomp_data sd;

    bpf_probe_read_kernel(&sd, sizeof(sd), (void *)PT_REGS_PARM2(ctx));
    if (sd.args[2] > 128 && sd.args[2] <= 1024) {
        char fmt[] = "read(fd=%d, buf=%p, size=%d)\n";
        bpf_trace_printk(fmt, sizeof(fmt),
                 sd.args[0], sd.args[1], sd.args[2]);
        data.ptr=(char *)sd.args[1];         
//      memcpy(data.ptr,sd.args[1],sizeof(char)*220);        
    }

        
        

    //data.pid =count;// bpf_get_current_pid_tgid();
    //if(buf==NULL)
    //memcpy(data.cookie,buf,20);
    //data.ptr=ptr; 
 //     data.cookie[0]=buf[0];
    //bpf_get_current_comm(&data.cookie, sizeof(data.cookie));
    
    //key=vektor[i];
    //bpf_map_update_elem(fd,&key,&data,BPF_ANY);
    //bpf_perf_event_output(ctx, &my_map, 1, &data, sizeof(data));
    
    return 0;
}

char _license[] SEC("license") = "GPL";
int _version SEC("version") = 99;

when I compile and link the program userspace with root@this:/home/ubuntu/Desktop/ebpf/Linux-exFilter-main/pkg/probe/bpf# clang -v trace_output_user.c -o trace -lbpf

I get error that and warning

trace_output_user.c:101:7: warning: 'perf_buffer__new_deprecated' is deprecated: libbpf v0.7+: use new variant of perf_buffer__new() instead [-Wdeprecated-declarations]
        pb = perf_buffer__new_deprecated(map_fd, 8, &pb_opts);
             ^
/usr/include/bpf/libbpf.h:949:12: note: 'perf_buffer__new_deprecated' has been explicitly marked deprecated here
LIBBPF_API LIBBPF_DEPRECATED_SINCE(0, 7, "use new variant of perf_buffer__new() instead")
           ^
/usr/include/bpf/libbpf_common.h:24:4: note: expanded from macro 'LIBBPF_DEPRECATED_SINCE'
                (LIBBPF_DEPRECATED("libbpf v" # major "." # minor "+: " msg))
                 ^
/usr/include/bpf/libbpf_common.h:19:47: note: expanded from macro 'LIBBPF_DEPRECATED'
#define LIBBPF_DEPRECATED(msg) __attribute__((deprecated(msg)))
                                              ^
1 warning generated.
 "/usr/bin/ld" -z relro --hash-style=gnu --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o trace /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crt1.o /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crti.o /usr/bin/../lib/gcc/x86_64-linux-gnu/10/crtbegin.o -L/usr/bin/../lib/gcc/x86_64-linux-gnu/10 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu -L/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../../lib64 -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib64 -L/usr/lib/x86_64-linux-gnu/../../lib64 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../.. -L/usr/lib/llvm-12/bin/../lib -L/lib -L/usr/lib /tmp/trace_output_user-ec780e.o -lbpf -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/bin/../lib/gcc/x86_64-linux-gnu/10/crtend.o /usr/bin/../lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/crtn.o
/usr/bin/ld: /tmp/trace_output_user-ec780e.o: in function `main':
trace_output_user.c:(.text+0x1e2): undefined reference to `perf_buffer__new_deprecated'

some details perf_buffer__new_deprecated and perf_buffer__new are depreciated in latest version of libbpf My kernel version is 5.14.1

1. you are explicitly using perf_buffer__new_deprecated in your code - don't do this : Use perf_buffer_new instead. You should never call a function that already has 'deprecated' in it's name.

2. Take a look in the header: libbpf/libbpf.h

perf_buffer_new is defined like this:

#define perf_buffer__new(...) ___libbpf_overload(___perf_buffer_new, __VA_ARGS__)

#define ___perf_buffer_new6(map_fd, page_cnt, sample_cb, lost_cb, ctx, opts) \
    perf_buffer__new(map_fd, page_cnt, sample_cb, lost_cb, ctx, opts)

#define ___perf_buffer_new3(map_fd, page_cnt, opts) \
    perf_buffer__new_deprecated(map_fd, page_cnt, opts)

So there are 2 functions:

  • Old: pef_buffer_new with 3 arguments
  • New: perf_buffer_new with 6 arguments.

With the macros, libbpf makes old code compile, too, while telling you to change your function call. You are using the old version right now (with 3 arguments). Switch to the new version with 6 arguments, as the 3-arguments-variant will be removed.

The new function (see libbpf/libbpf.h ):

/**
 * @brief **perf_buffer__new()** creates BPF perfbuf manager for a specified
 * BPF_PERF_EVENT_ARRAY map
 * @param map_fd FD of BPF_PERF_EVENT_ARRAY BPF map that will be used by BPF
 * code to send data over to user-space
 * @param page_cnt number of memory pages allocated for each per-CPU buffer
 * @param sample_cb function called on each received data record
 * @param lost_cb function called when record loss has occurred
 * @param ctx user-provided extra context passed into *sample_cb* and *lost_cb*
 * @return a new instance of struct perf_buffer on success, NULL on error with
 * *errno* containing an error code
 */
LIBBPF_API struct perf_buffer *
perf_buffer__new(int map_fd, size_t page_cnt,
         perf_buffer_sample_fn sample_cb, perf_buffer_lost_fn lost_cb, void *ctx,
         const struct perf_buffer_opts *opts);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM