搭建centos7 ebpf编译环境

2024-01-04 14:17:35 浏览数 (2)

系统环境:

# uname -r

3.10.0-1160.99.1.el7.x86_64

# cat /etc/centos-release

CentOS Linux release 7.6.1810 (Core)

1. gcc版本升级

代码语言:c复制
#sudo yum install centos-release-scl -y
#sudo yum install devtoolset-7 -y
#sudo yum install devtoolset-8 -y

安装的是 devtoolset-7 和 devtoolset-8, 安装完成后全部文件在/opt/rh目录下:

代码语言:c复制
# ls /opt/rh/
devtoolset-7  devtoolset-8

在所登录的会话生效高版本gcc:

代码语言:c复制
# gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)

# source /opt/rh/devtoolset-8/enable
# gcc --version
gcc (GCC) 8.3.1 20190311 (Red Hat 8.3.1-3)

添加到登录自启动脚本,避免每次登录需要手工执行source /opt/rh/devtoolset-8/enable
echo "source /opt/rh/devtoolset-8/enable" >> ~/.bash_profile

2. cmake升级

代码语言:c复制
#wget https://github.com/Kitware/CMake/releases/download/v3.20.0/cmake-3.20.0.tar.gz
#tar -zxvf cmake-3.20.0.tar.gz
#source /opt/rh/devtoolset-8/enable
#cd cmake-3.20.0
#./bootstrap 
#make 
#make install
重新登录新的会话查看cmake版本:
#cmake --version
cmake version 3.20.0

3. llvm升级:

代码语言:c复制

#git clone https://github.com/llvm/llvm-project.git
#cd llvm-project
#mkdir llvm-build
#cd llvm-build
#source /opt/rh/devtoolset-8/enable
#cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_RTTI=ON -DLLVM_ENABLE_PROJECTS="clang" -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" -G "Unix Makefiles" ../llvm
#make 
#make install

4. 编译bcc以及libbpf-tools

代码语言:c复制
编译bcc的过程会自动下载编译依赖的libbpf和bpftool,因此可以不需要再单独下载编译libbpf和bpftool
#git clone https://github.com/iovisor/bcc.git 
#mkdir bcc/build; cd bcc/build
#cmake ..
#make
#cd ../libbpf-tools/
#make

编译通过后执行bcc中自带的libbpf的工具比如opensnoop会报错,这个是因为bcc.git提供的libbpf-tools工具集实现时使用了BTF相关接口,依赖内核开启CONFIG_DEBUG_INFO_BTF。

代码语言:c复制
# ./opensnoop 
libbpf: failed to find valid kernel BTF
failed to fetch necessary BTF for CO-RE: Operation not supported

5. 写一个不依赖BTF的ebpf测试程序验证centos7运行ebpf程序

代码语言:c复制

       
# cat trace_kfree_skb.bpf.c  //内核态执行的bpf代码

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

struct args_kfree_skb {
        void *regs;
        void *skbaddr;
        void *location;
        unsigned short protocol;
};

SEC("tracepoint/skb/kfree_skb")
int tp_kfree_skb(struct args_kfree_skb *args)
{
        __u32 pid = 0;
        pid = bpf_get_current_pid_tgid();
        bpf_printk("pid:%d,hello test bpf :skbaddr:%llx,location:%llxn", pid,args->skbaddr,args->location);
        return 1;//perf trace -e skb:kfree_skb cannot get any message if here return 0. see kernel function perf_trace_run_bpf_submit()
}
char LICENSE[] SEC("license") = "GPL";


# cat trace_kfree_skb.c    //用户态执行的bpf代码
#include <stdio.h>
#include <unistd.h>
#include <sys/resource.h>
#include <bpf/libbpf.h>
#include "trace_kfree_skb.skel.h"

static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
{
        return vfprintf(stderr, format, args);
}

int main(int argc, char **argv)
{
        struct trace_kfree_skb_bpf *skel;
        int err;
         
         struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
        if (setrlimit(RLIMIT_MEMLOCK, &r)) {
                perror("setrlimit(RLIMIT_MEMLOCK)");
                return 1;
        }

         libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
        /* Set up libbpf errors and debug info callback */
         libbpf_set_print(libbpf_print_fn);

        /* Open BPF application */
        skel = trace_kfree_skb_bpf__open();
        if (!skel) {
                fprintf(stderr, "Failed to open BPF skeletonn");
                return 1;
        }

        /* Load & verify BPF programs */
        err = trace_kfree_skb_bpf__load(skel);
        if (err) {
                fprintf(stderr, "Failed to load and verify BPF skeletonn");
                goto cleanup;
        }
        /* Attach tracepoint handler */
         err = trace_kfree_skb_bpf__attach(skel);
         if (err) {
                 fprintf(stderr, "Failed to attach BPF skeletonn");
                 goto cleanup;
         }

        printf("Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` or run 'bpftool prog tracelog'"
               "to see output of the BPF programs.n");

       for (;;) {
                sleep(60);
        }

cleanup:
        trace_kfree_skb_bpf__destroy(skel);
        return 0;
}

#修改Makefile添加新增的测试代码:
bcc/libbpf-tools目录下的Makefile文件在APPS = 位置添加新的ebpf工具trace_kfree_skb:
APPS = 
        bashreadline 
        ......
        ......
        wakeuptime 
        trace_kfree_skb 
        $(BZ_APPS) 
        #
#执行make编译生成可执行文件trace_kfree_skb
# make
which: no cargo in (/opt/rh/devtoolset-8/root/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin)
  BPF      trace_kfree_skb.bpf.o
  GEN-SKEL trace_kfree_skb.skel.h
  CC       trace_kfree_skb.o
  BINARY   trace_kfree_skb
# ls trace_kfree_skb
trace_kfree_skb      

编译bcc的过程会自动下载编译依赖的libbpf和bpftool,因此可以不需要再单独下载编译libbpf和bpftool,
如果验证程序不是放在bcc/libbpf里一起编译,则需要再单独下载编译安装libbpf和bpftool。


验证在centos7 3.10内核正常运行ebpf程序
# uname -r
3.10.0-1160.99.1.el7.x86_64
# cat /etc/centos-release
CentOS Linux release 7.6.1810 (Core) 
# ./trace_kfree_skb 
libbpf: loading object 'trace_kfree_skb_bpf' from buffer
libbpf: elf: section(3) tracepoint/skb/kfree_skb, size 88, link 0, flags 6, type=1
libbpf: sec 'tracepoint/skb/kfree_skb': found program 'tp_kfree_skb' at insn offset 0 (0 bytes), code size 11 insns (88 bytes)
libbpf: elf: section(4) .reltracepoint/skb/kfree_skb, size 16, link 12, flags 40, type=9
libbpf: elf: section(5) .rodata, size 51, link 0, flags 2, type=1
libbpf: elf: section(6) license, size 4, link 0, flags 3, type=1
libbpf: license of trace_kfree_skb_bpf is GPL
libbpf: elf: section(7) .BTF, size 906, link 0, flags 0, type=1
libbpf: elf: section(9) .BTF.ext, size 128, link 0, flags 0, type=1
libbpf: elf: section(12) .symtab, size 144, link 1, flags 0, type=2
libbpf: looking for externs among 6 symbols...
libbpf: collected 0 externs total
libbpf: map 'trace_kf.rodata' (global data): at sec_idx 5, offset 0, flags 80.
libbpf: map 0 is "trace_kf.rodata"
libbpf: sec '.reltracepoint/skb/kfree_skb': collecting relocation for section(3) 'tracepoint/skb/kfree_skb'
libbpf: sec '.reltracepoint/skb/kfree_skb': relo #0: insn #4 against '.rodata'
libbpf: prog 'tp_kfree_skb': found data map 0 (trace_kf.rodata, sec 5, off 0) for insn 4
libbpf: map 'trace_kf.rodata': created successfully, fd=4
Successfully started! Please run `sudo cat /sys/kernel/debug/tracing/trace_pipe` or run 'bpftool prog tracelog'to see output of the BPF programs.

#新开一个会话执行cat /sys/kernel/debug/tracing/trace_pipe查看测试程序正常运行
       

参考:

https://bitsanddragons.wordpress.com/2022/09/19/error-cmake-3-1-or-higher-is-required-you-are-running-version-on-centos-7-x/

https://blog.csdn.net/yilun/article/details/126588552

0 人点赞