eBPF_primer

The bpftool

bpftool is a command-line utility in Linux for interacting with eBPF programs and maps. It allows you to perform various operations such as loading and attaching programs, manipulating maps, and retrieving information about eBPF objects.

Here are some common use cases of bpftool:

  1. Listing BPF Programs and Maps: View a list of loaded eBPF programs and maps on your system. It provides information such as program IDs, names, types, and associated maps.

  2. Loading and Unloading BPF Programs: It allows you to load eBPF programs into the kernel. You can specify the program type, source code file, and associated maps. It also provides options to unload and detach programs from the kernel.

  3. Inspecting BPF Objects: Provides detailed information about eBPF programs, maps, and other BPF objects. It allows you to retrieve attributes, statistics, and configuration parameters of these objects.

  4. Managing BPF Maps: Provides functionality to create, update, and delete eBPF maps. You can specify the map type, key size, value size, and other relevant parameters while creating or modifying a map.

  5. Debugging and Tracing: Offers features for debugging and tracing eBPF programs. It enables you to attach to programs and monitor their execution, including printing debug output and tracing events.

These are just a few examples of what we can do with bpftool.

For more information on using bpftool, you can refer to the official documentation or run man bpftool in your terminal.

Installation

To install bpftool on Ubuntu, follow these steps:

  1. Update your system:

    sudo apt update && sudo apt upgrade
    
  2. Install bpftool:

    sudo apt install linux-tools-common linux-tools-generic linux-tools-$(uname -r)
    
  3. Verify the installation:

    bpftool -V
    

The bpftool in Action

Let’s go over a few examples to showcase how the bpftool can be used.

I use flat as the program name to comply with the eBPF program we’re developing. Although flat uses tc and examples below are XDP. This is just for demonstration purposes.

Show Commands

  1. show all the eBPF programs loaded into the kernel at present:

    sudo bpftool prog list
    
  2. Get information about a specific eBPF program; either with id, name or tag:

    sudo bpftool prog show id 72
    sudo bpftool prog show name flat
    sudo bpftool prog show tag f1db4e564ad5219a
    
  3. show the bytecode instructions for eBPF programs:

    sudo bpftool prog dump xlated name flat
    
  4. show a specific eBPF program based on its name. For instance, flat:

    sudo bpftool prog show name flat
    
  5. Display all the network-related eBPF programs by running the following command:

    sudo bpftool net list
    

    The output should be similar to:

    xdp:
    lo(1) generic id 93
    
    tc:
    
    flow_dissector:
    
  6. You can also use the ip command to see that the program is attached to the lo interface:

    ip a show dev lo
    

    The output is similar to:

    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 xdpgeneric/id:135 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host
           valid_lft forever preferred_lft forever
    

    Notice that in the first line of output you see xdpgeneric/id:135 where 135 is the eBPF program ID.

  7. show information of a map:

    sudo bpftool map show id $MAP_ID
    
  8. show the value that corresponds to a particular key in a map:

    Note that you have to specify each of the 8 bytes of the key individually, starting with the least significant. You can use hex notation if you prefer, so all of the following are equivalent:

    sudo bpftool map lookup id $MAP_ID key 100 0 0 0 0 0 0 0
    # or
    sudo bpftool map lookup id $MAP_ID key 100 0 0 0 0 0 0 0
    sudo bpftool map lookup id $MAP_ID key 0x64 0 0 0 0 0 0 0
    sudo bpftool map lookup id $MAP_ID key hex 64 0 0 0 0 0 0 0
    
  9. Here’s the command to run to see any tracing being generated by any eBPF programs:

    (useful if we do not have a frontend program to do it for us)

    sudo bpftool prog trace log
    

eBPF tracing output gets sent to a pseudofile at /sys/kernel/debug/tracing/trace_pipe - an alternative to using bpftool is simply to use cat on this file. Notice that all tracing gets generated to this single location, which is why you would probably use a map to extract output to user space for production applications.

TC Specific Show Commands

  1. Show qdiscs associated with an interface, loopback (lo) in this case:

    sudo tc qdisc show dev lo
    
  2. show qdisc filters attached to an interface, loopback (lo) in this case:

    sudo tc filter show dev lo
    

Load and Attach eBPF TC programs

  1. Create a qdisc for an interface, loopback (lo) in this case:

    sudo tc qdisc add dev lo clsact
    
  2. Attach the eBPF program to ingress, egress or both traffic directions:

    sudo tc filter add dev lo ingress bpf direct-action obj flat.o sec tc
    sudo tc filter add dev lo egress bpf direct-action obj flat.o sec tc
    

TC Hardware Offload

Similar to XDP, tc programs can also be offloaded to the NIC (if the NIC supports hardware offload).

  1. Install ethtool:

    sudo apt install ethtool
    
  2. Enable hardware offloading on a NIC:

    ethtool -K eth0 hw-tc-offload on
    
  3. Create a qdisc for an interface, eth0 in this case:

    sudo tc qdisc add dev eth0 clsact
    
  4. Attach the eBPF program to ingress, egress or both traffic directions and offload to NIC using skip_sw:

    sudo tc filter add dev eth0 ingress bpf skip_sw  direct-action obj flat.o sec tc
    sudo tc filter add dev eth0 egress bpf skip_sw direct-action obj flat.o sec tc
    

Load and Attach eBPF XDP programs

  1. Load the eBPF byte code into the kernel and link it to the filesystem so that it may be identified as /sys/fs/bpf/flat:

    sudo bpftool prog load flat.o /sys/fs/bpf/flat
    
  2. At this point the program is not associated with any events that would trigger it. Associate or attach eBPF program to lo network interface:

    sudo bpftool net attach xdp name flat dev lo
    
  3. Additionally, we can also use the ip command to load our eBPF command:

    sudo ip link set dev lo xdp obj flat.o sec xdp
    

Update Commands

Update a map:

sudo bpftool map update id $MAP_ID key 5 0 0 0 0 0 0 0 value 0 0 0 0 0 0 0 1

Unload and Detach eBPF TC programs

  1. Detach the eBPF program:

    sudo tc filter del dev lo ingress
    sudo tc filter del dev lo egress
    
  2. Delete the qdisc:

    sudo tc qdisc del dev lo clsact
    

Deleting a qdisc will remove its filters as well.

Unload and Detach eBPF XDP programs

  1. Unload the eBPF program:

    sudo rm /sys/fs/bpf/flat
    
  2. Detach the eBPF program:

    sudo bpftool net detach xdp dev lo
    

References

  1. Cilium Development Environment