XDP Packet Processing
Program Types, Deep Dive and Debugging
BPF program types, deep dive, and debugging techniques.
BPF Program Types (XDP vs tc)
Source: Cilium BPF Program Types
| XDP | TC | |
|---|---|---|
| Context | xdp_buff | sk_buff |
| Hook point | Driver level | After L2 |
| Speed | Fastest | Slower |
| Direction | Ingress only | Ingress + Egress |
| Actions | XDP_DROP, XDP_PASS, XDP_TX, XDP_REDIRECT, XDP_ABORTED | TC_ACT_OK, TC_ACT_SHOT, TC_ACT_STOLEN, TC_ACT_REDIRECT |
| Modes | Native, Offloaded, Generic | cls_bpf direct-action |
For DDoS Engine: XDP native mode (fastest drop) For DNS Filter: tc egress hook (container policy enforcement)
Inspect in xdp-tutorial: advanced01-xdp-tc-interact - XDP and TC interaction, metadata passing.
Reading: Cilium Network Concepts - XDP and tc integration.
BPF Deep Dive
Source: Cilium BPF Architecture
Read this document after completing the XDP section:
- Instruction Set: 11 registers (r0-r10), 512-byte stack, calling convention
- Helper Functions:
bpf_map_lookup_elem,bpf_xdp_adjust_head, etc. - Maps: All map types (HASH, ARRAY, LPM_TRIE, PROG_ARRAY, etc.)
- Object Pinning:
/sys/fs/bpffilesystem,BPF_OBJ_PIN/BPF_OBJ_GET - Tail Calls: Program chaining,
BPF_MAP_TYPE_PROG_ARRAY - BPF to BPF Calls: Function calls,
always_inlinevs normal - JIT: x86_64, arm64 JIT compiler
- Hardening: JIT constant blinding,
bpf_jit_harden - Offloads: Offload to NIC (Netronome nfp)
- BPF sysctls:
bpf_jit_enable,bpf_jit_harden,unprivileged_bpf_disabled- important: these are the first settings to check when starting with BPF
Debugging and Testing
Source: Cilium BPF Debug & Test
bpftool — inspect loaded programs and maps
# List all loaded BPF programs
$ bpftool prog list
6: xdp name xdp_filter tag 3b185187f1855c4c
loaded_at 2024-01-15T10:30:00+0000 uid 0
xlated 296B jited 184B memlock 4096B
# Dump a map's contents
$ bpftool map dump id 42
key: 0a 00 01 01 value: 00 00 00 05
key: c0 a8 00 01 value: 00 00 00 12
# Show program stats (requires kernel.bpf_stats_enabled=1)
$ bpftool prog profile id 6 duration 5
run_cnt run_time_ns
154231 892041
bpf_printk — debug output from BPF programs
SEC("xdp")
int xdp_debug(struct xdp_md *ctx) {
void *data = (void *)(long)ctx->data;
void *data_end = (void *)(long)ctx->data_end;
struct ethhdr *eth = data;
if (data + sizeof(*eth) > data_end)
return XDP_PASS;
bpf_printk("pkt proto=%x len=%d",
bpf_ntohs(eth->h_proto),
data_end - data);
return XDP_PASS;
}
Read the output:
$ cat /sys/kernel/debug/tracing/trace_pipe
<idle>-0 [001] ..s1 1234.567890: bpf_trace_printk: pkt proto=800 len=74
llvm-objdump — inspect BPF bytecode
$ llvm-objdump -S xdp_prog.o
Disassembly of section xdp:
0000000000000000 <xdp_filter>:
0: r6 = r1 ; save ctx
1: r2 = *(u32 *)(r6 + 0) ; data
2: r3 = *(u32 *)(r6 + 4) ; data_end
3: r4 = r2 + 14 ; data + sizeof(ethhdr)
4: if r4 > r3 goto +8 ; bounds check
When to use: When you hit verifier errors, encounter performance issues, or need to understand program behavior.
Is TC Hook Needed?
No. For DDoS engine and DNS filter, XDP is sufficient.
| XDP | TC | |
|---|---|---|
| Hook point | Driver level | After L2 |
| Speed | Fastest | Slower |
| Direction | Ingress only | Ingress + Egress |
| sk_buff | No | Yes |
Your use case: Drop/pass at ingress - XDP is ideal.