What is eBPF?
eBPF (extended Berkeley Packet Filter) is a revolutionary Linux kernel technology that allows programs to run in kernel space without requiring kernel modules or modifications. Originally designed for packet filtering, eBPF has evolved into a general-purpose execution engine for safe, efficient kernel instrumentation.The eBPF Event Interceptor uses eBPF to monitor TCP and UDP network activity with minimal overhead and no kernel modifications.
Why eBPF for Network Monitoring?
Traditional Approaches vs eBPF
Kernel Modules
Risks:
- Can crash entire system
- No safety verification
- Complex to maintain
- Security vulnerabilities
- Full kernel access
- Maximum flexibility
eBPF Programs
Benefits:
- Verified safe before loading
- Cannot crash kernel
- Sandboxed execution
- No recompilation needed
- Limited instruction set
- Stack size limits
- Bounded loops only
Key Advantages
- Safety: eBPF verifier ensures programs terminate and don’t crash the kernel
- Performance: Runs in kernel context without context switching
- Flexibility: Load/unload programs dynamically without rebooting
- Observability: Zero application code changes required
- Security: Cannot access arbitrary kernel memory
BCC: BPF Compiler Collection
This project uses BCC (BPF Compiler Collection) to simplify eBPF program development.BCC version is displayed at startup:
BCC Components
BCC API Usage
1. Initialize BPF Program:Kprobes: Dynamic Kernel Instrumentation
What are Kprobes?
Kprobes allow eBPF programs to execute when specific kernel functions are called. Two types exist:- kprobe: Executes at function entry (before function runs)
- kretprobe: Executes at function return (after function completes)
TCP Kprobes
The TCP interceptor attaches to a single critical function:tcp_set_state?
This function is called whenever a TCP connection changes state (SYN_SENT → ESTABLISHED → FIN_WAIT1 → etc.). It provides:
- Connection establishment events
- Connection teardown events
- Access to
struct sock*containing all connection metadata
UDP Kprobes
UDP is connectionless, so the interceptor tracks operations across multiple functions:UDP Send/Receive Pattern
UDP Send/Receive Pattern
Send Operation:Receive Operation (Return Probe):
Kprobe Attachment Process
FromsetupBPF() in udpTracer.cc:394-471:
eBPF Program Structure
TCP eBPF Program
The TCP eBPF code is loaded from external source (passed tosetupBPF()). Key elements:
UDP eBPF Program
The UDP program is embedded directly in udpTracer.cc:58-386:The UDP program uses BPF hash maps (
BPF_HASH) to maintain state across multiple kprobe invocations, tracking per-socket statistics.eBPF Helper Functions
eBPF programs can only call approved helper functions:Context Helpers
Memory Access Helpers
Perf Buffer Helpers
Map Operations
Safety and Verification
eBPF Verifier Checks
Before loading, the kernel’s eBPF verifier ensures:- Bounded Execution: All loops have maximum iteration limits
- Memory Safety: All memory accesses are validated
- Null Pointer Checks: Pointers verified before dereferencing
- Stack Limits: Stack usage < 512 bytes
- Instruction Limits: Program < 1 million instructions
- No Infinite Loops: All code paths reach exit
If verification fails,
bpf.init() returns an error with the verifier’s detailed analysis.What eBPF Cannot Do
- ❌ Modify kernel code or data structures
- ❌ Call arbitrary kernel functions
- ❌ Access user space memory directly
- ❌ Use floating point operations
- ❌ Create unbounded loops
- ❌ Allocate dynamic memory
What eBPF Can Do
- ✅ Read kernel structures (read-only)
- ✅ Write to maps and perf buffers
- ✅ Call approved helper functions
- ✅ Make bounded decisions
- ✅ Aggregate statistics
- ✅ Filter events
Performance Characteristics
Overhead Analysis
Kprobe Overhead
- Entry: ~1-2μs
- Return: ~2-3μs
- Per packet cost: minimal
CPU Impact
- Idle system: < 0.1%
- Busy system: 1-3%
- No network slowdown
Memory Usage
- eBPF maps: ~100KB
- Perf buffers: ~2MB
- Queue: ~1MB (1024 events)
JIT Compilation
Modern kernels compile eBPF bytecode to native machine code:Loading and Attaching eBPF Programs
Complete Initialization Flow
Error Handling
Every BCC operation returns a status object:Memory Cleanup
Freeing BCC Resources
From event.cc:206-210:free_bcc_memory() releases LLVM compiler resources (~50-100MB) after program loading. This is safe because the compiled eBPF bytecode is already in the kernel.Next Steps
Event Collection
Learn about event data structures and collection mechanics
Architecture
Review the complete system architecture