An Introduction to eBPF: Concepts, Use Cases, and Practical Examples
This article provides a comprehensive overview of eBPF, explaining its origins, core concepts, comparison with SystemTap and DTrace, common use cases such as network monitoring, security filtering, and performance analysis, and includes step‑by‑step Python examples with BCC for tracing and latency measurement.
The author, a senior architect, introduces eBPF (extended Berkeley Packet Filter) as a powerful Linux kernel technology that enables users to run custom programs in the kernel without modifying its source.
eBPF originated from the classic BPF network filter and was extended to provide DTrace‑like capabilities. It first appeared in Linux 3.18 (2014) and requires kernel 4.4+ for full functionality.
Compared with SystemTap and DTrace, eBPF offers broader applicability (network monitoring, security filtering, performance analysis), dynamic loading of bytecode, and a JIT compiler for efficient execution.
Common Use Cases
Network monitoring – capture and analyze packets.
Security filtering – block or alert on malicious traffic.
Performance analysis – collect kernel metrics and visualize bottlenecks.
Virtualization – monitor VM performance and balance loads.
How eBPF Works
eBPF programs are loaded from user space via system calls, compiled by Clang/LLVM into bytecode, JIT‑compiled to native instructions, attached to kernel hooks (e.g., syscalls, network events), and verified by the kernel security checker before execution.
Below is a simple architecture diagram (image omitted).
Step‑by‑step Example 1: Counting TCP Packets
#!/usr/bin/python3
from bcc import BPF
from time import sleep
# Define eBPF program
bpf_text = """
#include
BPF_HASH(stats, u32);
int count(struct pt_regs *ctx) {
u32 key = 0;
u64 *val, zero = 0;
val = stats.lookup_or_init(&key, &zero);
(*val)++;
return 0;
}
"""
# Compile and load
b = BPF(text=bpf_text, cflags=["-Wno-macro-redefined"])
b.attach_kprobe(event="tcp_sendmsg", fn_name="count")
name = {0: "tcp_sendmsg"}
while True:
try:
for k, v in b["stats"].items():
print("{}: {}".format(name[k.value], v.value))
sleep(1)
except KeyboardInterrupt:
exit()This program creates a BPF hash map to count how many times the tcp_sendmsg kernel function is called, printing the count every second.
Installation Commands
sudo apt install python3-bpfccFor Ubuntu 20.10+ it is recommended to build BCC from source:
apt purge bpfcc-tools libbpfcc python3-bpfcc
wget https://github.com/iovisor/bcc/releases/download/v0.25.0/bcc-src-with-submodule.tar.gz
tar xf bcc-src-with-submodule.tar.gz
cd bcc
apt install -y python-is-python3
apt install -y bison build-essential cmake flex git libedit-dev libllvm11 llvm-11-dev libclang-11-dev zlib1g-dev libelf-dev libfl-dev python3-distutils
apt install -y checkinstall
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr -DPYTHON_CMD=python3 ..
make
checkinstallStep‑by‑step Example 2: Measuring TCP Latency
#!/usr/bin/python3
from bcc import BPF
import time
# Define eBPF program
bpf_text = """
#include
#include
#include
#include
struct packet_t {
u64 ts, size;
u32 pid;
u32 saddr, daddr;
u16 sport, dport;
};
BPF_HASH(packets, u64, struct packet_t);
int on_send(struct pt_regs *ctx, struct sock *sk, struct msghdr *msg, size_t size) {
u64 id = bpf_get_current_pid_tgid();
u32 pid = id;
struct packet_t pkt = {};
pkt.ts = bpf_ktime_get_ns();
pkt.size = size;
pkt.pid = pid;
pkt.saddr = sk->__sk_common.skc_rcv_saddr;
pkt.daddr = sk->__sk_common.skc_daddr;
struct inet_sock *sockp = (struct inet_sock *)sk;
pkt.sport = sockp->inet_sport;
pkt.dport = sk->__sk_common.skc_dport;
packets.update(&id, &pkt);
return 0;
}
int on_recv(struct pt_regs *ctx, struct sock *sk) {
u64 id = bpf_get_current_pid_tgid();
struct packet_t *pkt = packets.lookup(&id);
if (!pkt) { return 0; }
u64 delta = bpf_ktime_get_ns() - pkt->ts;
bpf_trace_printk("tcp_time: %llu.%llums, size: %llu\n", delta/1000, delta%1000%100, pkt->size);
packets.delete(&id);
return 0;
}
"""
# Compile and attach
b = BPF(text=bpf_text, cflags=["-Wno-macro-redefined"])
b.attach_kprobe(event="tcp_sendmsg", fn_name="on_send")
b.attach_kprobe(event="tcp_v4_do_rcv", fn_name="on_recv")
print("Tracing TCP latency... Hit Ctrl-C to end.")
while True:
try:
(task, pid, cpu, flags, ts, msg) = b.trace_fields()
print("%-18.9f %-16s %-6d %s" % (ts, task, pid, msg))
except KeyboardInterrupt:
exit()This program records timestamps when a TCP packet is sent and when it is received, then prints the latency.
The article also lists many BCC tools (bcc‑tools, bpftrace, tcptop, execsnoop, etc.) and provides extended reading links to books, official docs, and community resources.
In a reflective “Easter egg” section, the author criticizes the reliability of AI‑generated content, noting that ChatGPT produced inaccurate references and code, and emphasizes the need for careful review.
Finally, the author’s bio is given (Chen Hao, former senior architect at Alibaba Cloud, now founder of MegaEase) and several promotional calls‑to‑action are included.
Top Architect
Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.