0

GOAL: compile samples/bpf, compile bpf/bpftool and use them.

PROBLEM: on a VM with Ubuntu 18.04 bionic with a kernel 4.18.0-25-generic I've installed kernel src code executing apt install linux-source-4.18.0. Now I cd into /usr/src/linux-source-4.18.0/linux-source-4.18.0/samples/bpf and I run make and the result is

make -C ../../ /usr/src/linux-source-4.18.0/linux-source-4.18.0/samples/bpf/ BPF_SAMPLES_PATH=/usr/src/linux-source-4.18.0/linux-source-4.18.0/samples/bpf
make[1]: Entering directory '/usr/src/linux-source-4.18.0/linux-source-4.18.0'
scripts/kconfig/conf  --syncconfig Kconfig
***
*** Configuration file ".config" not found!
***
*** Please run some configurator (e.g. "make oldconfig" or
*** "make menuconfig" or "make xconfig").
***
scripts/kconfig/Makefile:40: recipe for target 'syncconfig' failed
make[3]: *** [syncconfig] Error 1
Makefile:562: recipe for target 'syncconfig' failed
make[2]: *** [syncconfig] Error 2
make[1]: *** No rule to make target 'include/config/auto.conf', needed by 'include/config/kernel.release'.  Stop.
make[1]: Leaving directory '/usr/src/linux-source-4.18.0/linux-source-4.18.0'
Makefile:203: recipe for target 'all' failed
make: *** [all] Error 2

If I cd into ../samples/bpf and I run sudo make the result is

Auto-detecting system features:
...                        libbfd: [ OFF ]
...        disassembler-four-args: [ OFF ]

  CC       map_perf_ring.o
  CC       xlated_dumper.o
  CC       perf.o
  CC       cfg.o
  CC       common.o
  CC       cgroup.o
  CC       main.o
main.c:36:10: fatal error: bfd.h: No such file or directory
 #include <bfd.h>
          ^~~~~~~
compilation terminated.
Makefile:92: recipe for target 'main.o' failed
make: *** [main.o] Error 1

QUESTIONS: what am I missing? After I compile them if I want to write a program which, for example, needs to use bpftool I have to write the program inside the source kernel directory or I can write it everywhere?

Maicake
  • 1,046
  • 10
  • 34

1 Answers1

3

Build errors

The first case (Makefile:562: recipe for target 'syncconfig' failed) fails because you run make from the top of the linux kernel repository, and before trying to compile the samples, the build system tries to load a config file to use for your system (but does not find one).

Before trying to build the samples (make -C samples/bpf), you can create a .config file from your current kernel configuration like this:

$ cp /usr/src/linux-headers-$(uname -r)/.config <path to repo>/.config
$ make olddefconfig

Or even simply generate a default config file from scratch:

$ make defconfig

See make help from top directory to see the available make options.

Your second error, regarding bfd.h not found, is that you miss a library. Libbfd on Ubuntu comes with binutils-dev, so apt install binutils-dev should do the trick.

Compiling the programs

Finally, regarding your question on compiling the programs:

  • You can write and build program from the kernel repository, just by creating a new sample and reusing the existing Makefiles.
  • You can also write and compile programs outside of the kernel tree. The basic clang (v4.0 or above, if possible v6.0 or above) command to compile them usually looks something like this:
$ clang -O2 -emit-llvm -c my_bpf_prog.c -o - | \
          llc -march=bpf -filetype=obj -o my_bpf_prog.o

You can find examples of programs compiled out of the kernel tree in that repository (disclaimer: by my company) or in the XDP tutorial repo.

Qeole
  • 8,284
  • 1
  • 24
  • 52
  • Thanks again, now the building goes further but I'm still getting a lot of errors. Like this /usr/src/linux-source-4.18.0/linux-source-4.18.0/samples/bpf/bpf_load.c:90:15: error: ‘BPF_PROG_TYPE_RAW_TRACEPOINT’ undeclared (first use in this function); did you mean ‘BPF_PROG_TYPE_TRACEPOINT’? prog_type = BPF_PROG_TYPE_RAW_TRACEPOINT; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ BPF_PROG_TYPE_TRACEPOINT and before also I got one "redefinition error" and one "missing type definition error" which I solved modifying the code as reported here https://lkml.org/lkml/2019/5/17/783 – Maicake Jul 31 '19 at 10:10
  • 1
    I didn't execute sudo make headers_install. After I did it, sudo make -C samples/bpf worked. – Maicake Jul 31 '19 at 10:18
  • 1
    Yep, you need to install the headers. Latest kernels tell you to do so if you haven't already, but that might not be the case for 4.18 yet. Glad you managed to compile the samples! :) – Qeole Jul 31 '19 at 10:33
  • thanks for the help :).Now I want to write this same program https://stackoverflow.com/questions/57219423/why-im-forced-to-use-raw-socket-to-write-ebpf-programs-with-bcc?noredirect=1#comment101036837_57219423 but using C also for the frontend. So, correct me if I'm wrong,1)I can reuse the C code for _kern.c and I have to write _user.c part like one of the example to load the ebpf program with bpf_prog_load helper function, then run sudo make -C samples/bpf. 2)Or I can clang and load the ELF with bpftool.. but I don't understand how can I refer to the ebpf loaded program inside user code. – Maicake Jul 31 '19 at 10:53
  • 1
    Yes for 1). For 2), depends on your hook: You can load the prog with bpftool, but it [doesn't support attaching the program yet](https://lore.kernel.org/netdev/20190731112818.79e767e4@carbon/T/#m3dcae86c6eb00bde1d6fb84e9c6404baf190ef8d). Loading for XDP requires `ip link`, for TC requires `tc qdisc/tc filter`, for a socket requires some C app with `setsockopt()`. `ip link`/`tc` work from the object file (.o) directly. For socket you need a FD you can get from program id or pinned path (with libbpf). For bpftool also look [at this thread](https://twitter.com/qeole/status/1101450782841466880). – Qeole Jul 31 '19 at 11:18
  • 1
    E.g. typically for a socket, `man 7 socket` tells you `SO_ATTACH_BPF` for `setsockopt()` needs a file descriptor. Once your program has been loaded on the system (e.g. `bpftool prog load my_prog.o /sys/fs/bpf/foo`), you can see its id (`bpftool prog list`) and use it to get a FD (libbpf: `bpf_prog_get_fd_by_id()`). Or use the pinned path (`/sys/fs/bpf/foo`) to get the same FD (libbpf: `bpf_obj_get()`). Or if you used libbpf to load your program in the first place (no `bpftool` involved), you automatically retrieve a FD from `bpf_object__load()`, if I remember correctly. – Qeole Jul 31 '19 at 11:27
  • I'm trying the first approach and I'm already struggling XD. https://stackoverflow.com/questions/57291946/why-ebpf-program-inside-samples-bpf-doesnt-work why it's so damn hard. – Maicake Jul 31 '19 at 13:29