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

XDPTC
Contextxdp_buffsk_buff
Hook pointDriver levelAfter L2
SpeedFastestSlower
DirectionIngress onlyIngress + Egress
ActionsXDP_DROP, XDP_PASS, XDP_TX, XDP_REDIRECT, XDP_ABORTEDTC_ACT_OK, TC_ACT_SHOT, TC_ACT_STOLEN, TC_ACT_REDIRECT
ModesNative, Offloaded, Genericcls_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/bpf filesystem, BPF_OBJ_PIN/BPF_OBJ_GET
  • Tail Calls: Program chaining, BPF_MAP_TYPE_PROG_ARRAY
  • BPF to BPF Calls: Function calls, always_inline vs 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.

XDPTC
Hook pointDriver levelAfter L2
SpeedFastestSlower
DirectionIngress onlyIngress + Egress
sk_buffNoYes

Your use case: Drop/pass at ingress - XDP is ideal.