BPF playground

write eBPF, run it on packets, watch every register

An XDP program in eBPF assembly, run in your browser on sample packets. A small verifier checks bounds and null pointers like the kernel would. Nothing leaves this page.

🐝 Play the eBPF quiz20 questions · 3 easy · 13 medium · 4 hard Play ▶

bytecode

packet

readwrittenproven by bounds check
edit bytes

registers

maps

no maps, declare one with .map name entries

trace_pipe

bpf_trace_printk output shows here
cheat sheet

Registers. r0 return value, r1-r5 helper arguments (clobbered by call), r6-r9 kept across calls, r10 read-only frame pointer, 512 bytes of stack below it. On entry r1 = struct xdp_md *ctx.

ctx+0  data       start of packet
ctx+4  data_end   one past the last byte
ctx+12 ingress_ifindex

return  0 ABORTED  1 DROP  2 PASS  3 TX  4 REDIRECT

packet  eth 0-13 (proto at 12)  ipv4 14-33 (proto at 23)  l4 from 34

Syntax (ubpf style, comments with ;):

mov r0, 2          add r4, 34        mov32 r1, -1     neg r2
ldxb r5, [r2+23]   ldxh  ldxw  ldxdw  load 1/2/4/8 bytes
stxw [r10-4], r5   stb [r10-1], 7     store register / immediate
xadddw [r0+0], r1  xaddw               atomic add
lddw r1, 0x1122334455667788            64-bit immediate
lddw r1, mymap     map reference       be16 r5  le32 r5  byte swap
jeq r5, 1, label   jne jgt jge jlt jle jset jsgt jsge jslt jsle (+32 suffix)
ja label           ja +2               call bpf_map_lookup_elem   exit
.map mymap 16      array map, u32 key -> u64 value

Helpers. 1 bpf_map_lookup_elem(map, &key), 2 bpf_map_update_elem(map, &key, &value, flags), 5 bpf_ktime_get_ns(), 6 bpf_trace_printk(fmt, size, a, b, c), 7 bpf_get_prandom_u32(), 8 bpf_get_smp_processor_id().

Verifier. Every packet read needs a prior check like jgt r4, r3, out where r4 = data + N and r3 = data_end. A map lookup result must be compared with 0 before use. Reading a register or stack slot that was never written is rejected.