Setting Up eBPF on Linux

Setting up eBPF on your Linux system opens up a world of possibilities for networking, performance monitoring, security, and more. In this guide, we’ll walk through the essential steps to get eBPF running smoothly on your machine. Let’s dive right in!

Step 1: Ensure Your Kernel Supports eBPF

Before anything else, you should verify that your Linux kernel supports eBPF. As of Linux version 4.1 and later, eBPF features are available, but it's best to work with a later version for better performance and functionality.

To check your kernel version, open the terminal and run:

uname -r

If you're running a kernel older than 4.1, consider upgrading to a more recent version.

Step 2: Install Required Packages

To effectively use eBPF, you will need several tools and libraries. Here’s a list of the essential packages you should install. Depending on your Linux distribution (Ubuntu, CentOS, etc.), you may need to adjust the commands slightly.

For Debian-based systems (like Ubuntu), run:

sudo apt-get update
sudo apt-get install clang llvm libelf-dev linux-headers-$(uname -r) build-essential bpftrace

For Red Hat-based systems (like CentOS), use the following:

sudo yum install clang llvm elfutils-libelf-devel kernel-devel bpftrace

Breaking down these installations:

  • clang and llvm: Compilers and tools for working with eBPF.
  • libelf-dev: Libraries for ELF (Executable and Linkable Format) files, which are important for eBPF.
  • linux-headers: Kernel headers for building modules and accessing kernel features.
  • bpftrace: A high-level tracing language for eBPF, making it easier to write eBPF programs.

Step 3: Verify Installation

It’s essential to verify that all necessary packages have been installed correctly. You can confirm bpftrace installation by checking its version:

bpftrace -v

If you see the version number, you are good to go!

Step 4: Write Your First eBPF Program

Now that you have installed the necessary tools, let’s write a simple eBPF program that traces specific kernel functions. We'll create a basic program that traces the execve system call.

  1. Create a new file named trace_execve.bt:
nano trace_execve.bt
  1. Insert the following code into the file:
tracepoint:syscalls:sys_enter_execve {
    printf("execve called: pid=%d, command=%s\n", pid, str(args->filename));
}
  1. Save and close the file (in nano, you can do this with CTRL + O, Enter, then CTRL + X).

This program will print a message every time the execve() system call is executed, displaying the process ID and the command being executed.

Step 5: Run Your eBPF Program

To run the eBPF program, execute the following command in your terminal:

sudo bpftrace trace_execve.bt

Make sure to run this command in a terminal that has superuser privileges, as bpftrace requires elevated permissions to attach to kernel tracepoints.

Now, open another terminal window and run any command on your system, such as:

ls

You should see the output of the execve trace, indicating the command was executed.

Step 6: Setting Up a More Complex eBPF Program

After successfully setting up your basic eBPF program, you might want to explore more complex capabilities. For instance, monitoring network traffic can be done with tc (traffic control). Here’s a basic setup to track packets in your network.

  1. Set up a new file named trace_network.bt:
nano trace_network.bt
  1. Add the following code:
kprobe:__netif_receive_skb {
    @(pid):count++;
}

END {
    printf("Packet counts:\n");
    print(@count);
}
  1. Save and close the file.

This eBPF program uses a kernel probe to count packets received on all network interfaces.

Step 7: Running the Network Trace Program

To run this program, use:

sudo bpftrace trace_network.bt

Like before, it’s crucial to run the command with sudo.

While the program is running, generate some network traffic. You can continually ping a website or download a file. After a while, stop the eBPF script by pressing Ctrl + C. The program will output the count of packets received.

Step 8: Understanding eBPF Maps

eBPF maps are crucial for storing data such as counters, histograms, and arrays. Using maps can enhance the efficiency and gather more complex analytics in your eBPF programs.

Here’s a simple modification to the trace_network.bt to use a map:

  1. Update trace_network.bt:
#pragma rlicense Kolkata

BEGIN {
    printf("Tracing network packets... Press Ctrl+C to end.\n");
}

kprobe:__netif_receive_skb {
    @packet_count[comm] = count();
}

END {
    printf("Packet counts:\n");
    print(@packet_count);
}

In this code, we create a map called @packet_count where the key is the process name and the value is the count of packets for that process.

Step 9: Running the Enhanced Network Trace

Once you’ve made the changes, run it again using:

sudo bpftrace trace_network.bt

As before, produce some traffic then terminate the script. The output will reflect the number of packets received by applications, organized by process.

Conclusion

By following these steps, you’ve successfully set up eBPF on your Linux system and created your own eBPF programs! The potential of eBPF is vast, offering powerful capabilities for tracing, monitoring, and enhancing performance. With this foundation, you can explore more complex use cases and contributions to the Linux kernel.

Continue experimenting with different eBPF programs, and don’t hesitate to dive deeper into the many libraries and tools available for working with eBPF. Happy coding!