
Écrivez vos programmes BPF en Go, pas en C. gobee transpile un sous-ensemble de Go en C BPF et génère des liaisons typées cilium/ebpf.
Écrivez vos programmes BPF en Go, pas en C. gobee transpile un sous-ensemble strict de Go en C BPF, génère des bindings Go typés pour le côté espace utilisateur, et vérifie les charges par rapport au noyau en cours d'exécution.
L'écosystème Go dispose d'outils solides pour l'espace utilisateur BPF. Le côté noyau s'est toujours terminé par « maintenant écrivez votre programme en C. » Aya a apporté eBPF à Rust en écrivant un nouveau backend BPF dans rustc. gobee y parvient différemment : en transpilant vers C et en réutilisant le backend mature de clang.
Une tracepoint qui diffuse chaque execve vers l'espace utilisateur via un ringbuf :
| Votre entrée (Go) | Ce que gobee génère (C BPF) |
|---|---|
|
|
gobee translate --bindings-dir ./bpf ./bpf/src produit les deux fichiers, plus une sourcemap (events.bpf.c.map) pour que les erreurs du vérificateur correspondent aux lignes Go, et un fichier de bindings typés (bpf/events_bindings.go) pour que le pilote espace utilisateur écrive objs.Events, objs.AttachOnExec() et décode les payloads du ringbuf directement dans bpf.Event (la même structure que ci-dessus, republiée en Go) au lieu de recherches coll.Programs["..."] basées sur des chaînes.
Le C est intentionnellement lisible. Si gobee émet quelque chose d'étrange, vous pouvez le voir. Pour les tracepoints + kprobes + XDP combinés en un seul binaire, voir example/sysmon/.
| gobee | C + clang + bpf2go | Aya (Rust) | bpftrace | BCC | |
|---|---|---|---|---|---|
| Langage côté noyau | Sous-ensemble Go | C | Rust | DSL | C |
| Intégration espace utilisateur | bindings Go typés + cilium/ebpf | bpf2go | aya-runtime | aucun | python |
| CO-RE | ✅ via clang | ✅ | ✅ via LLVM | ✅ | ✅ |
| Couverture des helpers | 200 wrappers Go typés | complet (écrire en C) | complet | limité | complet (écrire en C) |
| Erreur du vérificateur → source | ✅ fichier Go:ligne:col | ❌ C brut | ✅ fichier Rust:ligne | ❌ | partiel |
| Vérification de version noyau au chargement | ✅ via bpfvet | manuel | manuel | n/a | runtime |
| Dépendances de la toolchain | Go + clang | clang + bpf2go | rustc + LLVM | bpftrace | python + bcc |
| Artefact généré | .bpf.o + binaire Go | .bpf.o + binaire Go | .bpf.o + binaire Rust | JIT | JIT |
Si vous êtes déjà dans un workflow C / libbpf, gobee ne cherche pas à le remplacer entièrement. Il est destiné aux cas où vous voulez le côté noyau, le côté espace utilisateur et le pipeline de construction dans un seul module Go.
Voir docs/status.md pour la matrice complète (sous-ensemble Go, instructions, expressions, chaque helper, chaque type de map, chaque directive). Aperçu rapide :
| Surface | Couverture |
|---|---|
| Types de programmes (8) | XDP, tracepoint, kprobe / kretprobe, uprobe / uretprobe, sock_ops, TC, cgroup_skb, LSM |
| Types de maps (19) | array, hash, lru_hash, variantes per-CPU, bloom_filter, lpm_trie, ringbuf, perf_event_array, prog_array, queue, stack, sk/task/inode storage, devmap/cpumap/xskmap |
| Helpers BPF | ~200 stubs Go typés générés automatiquement à partir des en-têtes libbpf v1.5.0. Ceux utilisés par example/helloworld/ et example/sysmon/ sont testés dans une CI sur noyau réel ; les autres ne sont pas vérifiés. Signalez un problème si un stub ne correspond pas à la signature du noyau |
| CO-RE | ✅ détection automatique. BPF_CORE_READ pour les champs internes du noyau (task_struct, sock, inode) ; ctx->field direct pour les structures de contexte BPF de l'UAPI (xdp_md, __sk_buff, bpf_sock_ops). Testé sur Linux 6.x (CI Ubuntu 24.04) ; les noyaux plus anciens ne sont pas encore dans la matrice CI |
| Sortie compatible BTF | ✅ Le C généré inclut vmlinux.h et utilise BPF_CORE_READ pour les lectures de champs internes du noyau, de sorte que le BTF que clang génère à partir de clang -g porte les bonnes relocalisations. clang lui-même reste votre responsabilité (les Makefiles d'exemple montrent l'invocation canonique) |
| Helpers définis par l'utilisateur | ✅ Les fonctions Go de premier niveau sans //bpf:section sont émises comme des fonctions static __always_inline en C |
| Bindings Go typés | ✅ Load<Stem>, Close, Attach<Name> par programme, AttachAll, plus vos types de structures et constantes côté noyau republiés en Go |
| Vérification de version noyau | ✅ bpfvet s'exécute au chargement. Échec rapide avec « bpf program needs kernel >= 5.8, host is 5.4 » au lieu d'un EINVAL opaque |
| Erreur du vérificateur → source Go | ✅ annoté automatiquement dans Load<Stem>. Pas de pipe manuel vers gobee diagnose ; *ebpf.VerifierError revient avec des marqueurs → counter.go:18:5 |
| Fichier sourcemap | ✅ <stem>.bpf.c.map écrit à côté de chaque .bpf.c pour une utilisation hors ligne de gobee diagnose |
| Multi-architecture | ✅ Linux arm64 + amd64 |
go/types sur votre entrée, de sorte que les mauvaises utilisations apparaissent à fichier:ligne:col).<Stem>_bindings.go typé à côté du .bpf.c : bpf.LoadCounter(spec), objs.PerIface.Lookup(...), objs.AttachAll(ifindex), plus vos types de structures et constantes côté noyau republiés en Go.*ebpf.VerifierError de LoadAndAssign avec des positions source Go, sans nécessiter de pipe manuel gobee diagnose.Load<Stem> pour que les anciens noyaux échouent rapidement avec « bpf program needs kernel >= 5.8, host is 5.4 ».static __always_inline.cilium/ebpf. Les bindings générés reposent dessus.