std.bpf — eBPF Maps und Programme
import std.bpf;
Wrapper um sys_bpf(321). eBPF (extended Berkeley Packet Filter) ist ein Kernel-Subsystem für sichere, vom Kernel-Verifier geprüfte Programme. Haupteinsatz: Netzwerk-Filterung, Tracing, Performance-Monitoring, XDP.
Achtung: Auf Produktionssystemen erfordert BPF meistCAP_BPFoderCAP_SYS_ADMIN. Beiunprivileged_bpf_disabled=1(Ubuntu-Standard) schlägt selbst das Anlegen einfacher Maps mitEPERMfehl.
→ std.debug · std.net.socket · std.security_ext
BPF-Kommando-Konstanten
| Konstante | Wert | Beschreibung |
|---|---|---|
BPF_MAP_CREATE | 0 | Neue Map anlegen |
BPF_MAP_LOOKUP_ELEM | 1 | Element lesen |
BPF_MAP_UPDATE_ELEM | 2 | Element schreiben/aktualisieren |
BPF_MAP_DELETE_ELEM | 3 | Element löschen |
BPF_MAP_GET_NEXT_KEY | 4 | Iteration: nächster Schlüssel |
BPF_PROG_LOAD | 5 | Programm laden |
Map-Typ-Konstanten
| Konstante | Wert | Beschreibung |
|---|---|---|
BPF_MAP_TYPE_HASH | 1 | Hash-Tabelle (allgemein) |
BPF_MAP_TYPE_ARRAY | 2 | Array mit int-Index |
BPF_MAP_TYPE_PROG_ARRAY | 3 | Tail-Call-Array |
BPF_MAP_TYPE_PERF_EVENT_ARRAY | 4 | Perf-Event-Ringpuffer |
BPF_MAP_TYPE_PERCPU_HASH | 5 | Hash, per-CPU |
BPF_MAP_TYPE_PERCPU_ARRAY | 6 | Array, per-CPU |
BPF_MAP_TYPE_STACK_TRACE | 7 | Stack-Traces |
BPF_MAP_TYPE_QUEUE | 18 | FIFO-Queue |
BPF_MAP_TYPE_STACK | 19 | LIFO-Stack |
BPF_MAP_TYPE_RINGBUF | 27 | Ring-Buffer (Kernel 5.8+) |
Update-Flags
| Konstante | Bedeutung |
|---|---|
BPF_ANY | Anlegen oder ersetzen |
BPF_NOEXIST | Nur anlegen wenn nicht vorhanden |
BPF_EXIST | Nur ersetzen wenn vorhanden |
Programm-Typen
| Konstante | Beschreibung |
|---|---|
BPF_PROG_TYPE_SOCKET_FILTER | Socket-Filter |
BPF_PROG_TYPE_KPROBE | Kernel-Probe |
BPF_PROG_TYPE_SCHED_CLS | TC-Classifier |
BPF_PROG_TYPE_TRACEPOINT | Tracepoint |
BPF_PROG_TYPE_XDP | XDP (eXpress Data Path) |
BPF_PROG_TYPE_PERF_EVENT | Perf-Event |
Instruktions-Encoding
Jede BPF-Instruktion ist 8 Bytes:
| Offset | Typ | Feld | |
|---|---|---|---|
| +0 | uint8 | opcode | |
| +1 | uint8 | dst_reg (Bits 0-3) \ | src_reg (Bits 4-7) |
| +2 | int16 | offset | |
| +4 | int32 | immediate |
Häufige Opcodes:
| Konstante | Wert | Beschreibung |
|---|---|---|
BPF_OP_MOV64_IMM | 0xB7 | r[dst] = imm |
BPF_OP_MOV64_REG | 0xBF | r[dst] = r[src] |
BPF_OP_ADD64_IMM | 0x07 | r[dst] += imm |
BPF_OP_EXIT | 0x95 | Programm beenden |
BPF_OP_CALL | 0x85 | Helper-Funktion aufrufen |
BPF_OP_JEQ_IMM | 0x15 | Jump wenn r[dst] == imm |
Register: BPF_R0 (Rückgabe) bis BPF_R10 (Frame-Pointer, nur-lesen).
Funktionen
Map-Operationen
| Funktion | Signatur | Beschreibung |
|---|---|---|
BpfMapCreate | (mapType: int64, keySize: int64, valSize: int64, maxEntries: int64): int64 | Legt Map an; gibt map_fd oder -errno |
BpfMapLookup | (mapFd: int64, key: int64, valOut: int64): int64 | Liest Wert für Schlüssel |
BpfMapUpdate | (mapFd: int64, key: int64, val: int64, flags: int64): int64 | Schreibt/aktualisiert Eintrag |
BpfMapDelete | (mapFd: int64, key: int64): int64 | Entfernt Eintrag |
Programm laden
| Funktion | Signatur | Beschreibung |
|---|---|---|
BpfProgLoad | (progType: int64, insns: int64, insnCnt: int64, license: pchar, logBuf: int64, logSize: int64): int64 | Lädt BPF-Programm; gibt prog_fd oder -errno |
Instruktions-Helfer
| Funktion | Signatur | Beschreibung |
|---|---|---|
BpfInsn | (code: int64, dst: int64, src: int64, off: int64, imm: int64): int64 | Kodiert eine BPF-Instruktion als int64 |
BpfEmitRaw | (buf: int64, n: int64, insn: int64): int64 | Schreibt Instruktion n in den Puffer |
Verwendung
Array-Map anlegen und befüllen
import std.bpf;
import std.alloc;
fn main(): int64 {
// Array-Map: uint32-Key, uint64-Wert, 256 Einträge
var mapFd: int64 := BpfMapCreate(BPF_MAP_TYPE_ARRAY, 4, 8, 256);
if (mapFd < 0) { return mapFd; }
// Eintrag schreiben: Key = 0, Wert = 42
var key: int64 := alloc(4);
var val: int64 := alloc(8);
poke32(key, 0);
poke64(val, 42);
BpfMapUpdate(mapFd, key, val, BPF_ANY);
// Eintrag lesen
var out: int64 := alloc(8);
var r: int64 := BpfMapLookup(mapFd, key, out);
if (r = 0) {
var v: int64 := peek64(out); // v = 42
}
free(key, 4); free(val, 8); free(out, 8);
close(mapFd);
return 0;
}
Minimales BPF-Programm laden
import std.bpf;
import std.alloc;
fn main(): int64 {
// Minimales Programm: r0 = 0; exit
var insns: int64 := alloc(2 * BPF_INSN_SIZE);
BpfEmitRaw(insns, 0, BpfInsn(BPF_OP_MOV64_IMM, BPF_R0, 0, 0, 0));
BpfEmitRaw(insns, 1, BpfInsn(BPF_OP_EXIT, 0, 0, 0, 0));
var logBuf: int64 := alloc(4096);
var fd: int64 := BpfProgLoad(BPF_PROG_TYPE_SOCKET_FILTER,
insns, 2, "GPL", logBuf, 4096);
if (fd < 0) {
// logBuf enthält Verifier-Fehlermeldung
free(insns, 2 * BPF_INSN_SIZE);
free(logBuf, 4096);
return fd;
}
free(insns, 2 * BPF_INSN_SIZE);
free(logBuf, 4096);
close(fd);
return 0;
}
Hinweise
- CAP_BPF: Auf modernen Systemen (Kernel 5.8+) reicht
CAP_BPF; ältere Kernel benötigenCAP_SYS_ADMIN. Ubuntu sperrt BPF für normale Nutzer standardmäßig. - Verifier-Log: Bei
BpfProgLoad-Fehler enthältlogBufdie genaue Verifier-Fehlermeldung — wichtig für Debugging.logBuf=0undlogSize=0deaktiviert den Log. - Lizenz: Der Lizenz-String beeinflusst welche Kernel-Helper-Funktionen verfügbar sind. GPL-only-Helpers (z.B.
bpf_probe_read) benötigenGPLoder kompatible Lizenz. - Map-FDs: BPF-Map-FDs sind normale Dateideskriptoren und müssen mit
close()freigegeben werden. Maps bleiben solange aktiv wie mindestens ein fd offen ist. - bpf_attr Größe: Alle Funktionen allozieren intern einen 128-Byte-Puffer (
BPF_ATTR_SIZE) für den Syscall.
Letzte Aktualisierung: 2026-06-06
