Search code examples
linuxebpfbcc-bpf

Tried to learn eBPF tail call, fails to attach kprobe


Hi I'm trying to learn how to use eBPF maps so I tried to run the simple code I found on BCC document.

import os
import socket
import time
import logging
import signal
import sys
import zmq
import json
import yaml
import netifaces as ni
from bcc import BPF
from ctypes import *

b = BPF(src_file="tailcall_test.c")
tail_fn = b.load_func("tail_call", BPF.KPROBE)
prog_array = b.get_table("prog_array")
prog_array[c_int(2)] = c_int(tail_fn.fd)
b.attach_kprobe(event="some_kprobe_event", fn_name = "do_tail_call")

and here's the c code that I used which name is :tailcall_test.c :

#include <uapi/linux/ptrace.h>
#include <net/sock.h>
#include <bcc/proto.h>
#include <linux/bpf.h>
#include <linux/kernel.h>
#include <uapi/linux/bpf.h>

BPF_PROG_ARRAY(prog_array, 10);

int tail_call(void *ctx) {
        bpf_trace_printk("tail-call\n");
        return 0;
}

int do_tail_call(void *ctx) {
        bpf_trace_printk("Original program\n");
        prog_array.call(ctx, 2);
        return 0;
}

I wasn't so sure which headers or libraries need to be included so I dumped everything in there.. sorry about the dirty code :(

Anyways, it gives me this error when I try to run it :

cannot attach kprobe, probe entry may not exist
Traceback (most recent call last):
  File "tailcall_test.py", line 18, in <module>
    b.attach_kprobe(event="some_kprobe_event", fn_name = "do_tail_call")
  File "/usr/lib/python2.7/dist-packages/bcc/__init__.py", line 648, in attach_kprobe
    (fn_name, event))
Exception: Failed to attach BPF program do_tail_call to kprobe some_kprobe_event

Any help..? Thank you so much in advance.

Plus, if you guys have any recommendation to check on to learn how to use eBPF tail calls, I would really appreciate it if you guys would share them with me.

Thanks a lot in advance.


Solution

  • So I didn't have time to finish typing my answer before the cause of the issue was found by Roadowl in the comments :). Since there was a second part in the question about references for tail calls, and I have written that bit anyway, I post it just in case it can be helpful.

    • Just for future reference, bcc documentation has a paragraph on tail calls, but by the look of your code you found it already :).

    • If you want to understand how tail calls work, I would suggest having a look at Cilium's documentation, in particular the section on tail calls. Keep in mind that bcc provides some wrappers (such as the .call() function) that won't be covered in Cilium's doc, but it should help you understand what is happening under the hood anyway.

    • bcc itself does not seem to use tail calls a lot, I could only find one networking example that seems to use it (although I did not search thoroughly).

    • You can find some simple example programs using tail calls in the iproute2 repository (a simple one, one that loops). You can also find some in kernel samples or selftests: grep for tail_call.