Search code examples
kernelclangbpfebpf

Compile ebpf _kern.c outside the kernel tree and link stand alone libbpf to _user.c


GOAL: build an ebpf program outside the kernel tree using stand alone libbpf and clang

PROBLEM: I followed these steps

1) Build libbpf

git clone https://github.com/libbpf/libbpf.git
cd src
make

2) Copy bpf_helpers.h from my kernel src /tools/testing/selftests/bpf/bpf_helpers.h

3) Compile with

clang -S -I. -O2 -Wall -Werror -emit-llvm -c mine_kern.c -o - | llc -march=bpf -filetype=obj -o mine_kern.o

But as a result I have a lot of errors all related to the bpf_helpers.h content. e.g

In file included from mine_kern.c:7:
./bpf_helpers.h:75:11: error: use of undeclared identifier
      'BPF_FUNC_sock_ops_cb_flags_set'
        (void *) BPF_FUNC_sock_ops_cb_flags_set;
                 ^

mine_kern.c

#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/ip.h>
#include <linux/in.h>    
#include "bpf_helpers.h"

SEC("socket")
int bpfrog1(struct __sk_buff *skb)
{
        int proto = load_byte(skb, ETH_HLEN + offsetof(struct iphdr, protocol));

        if (proto == IPPROTO_ICMP && skb->pkt_type == PACKET_OUTGOING)
                return -1;
        else
                return 0;

}
char _license[] SEC("license") = "GPL";

QUESTIONS:

The project tree is:

libbpf
  |src
    |libbpf.a
    |libbpf.so
    |...
libbpfebpf
  |bpf_headers.h
  |mine_kern.c
  |mine_user.c

how can I fix the error? After the fix is enough to compile _user.c with gcc and -L../libbpf/src to link libbpf.so ?


Solution

  • What kernel are you running? It looks like the bpf_sock_ops_cb_flags_set() BPF helper is not supported by your kernel (missing from /usr/include/linux/bpf.h). It was added in Linux 4.17, so if your kernel is older than this, remove its definition (and all subsequent helpers) from your bpf_helpers.h. It should not be a problem for compiling your program, unless you intended to use one of those more recent helpers.

    Alternatively, upgrade your kernel.

    And yes, I think it should be enough to pass the -L flag to gcc to tell it where to find the libbpf.