
اكتب برامج BPF الخاصة بك في Go، وليس C. يحوّل gobee مجموعة فرعية من Go إلى BPF C ويولّد روابط cilium/ebpf مكتوبة بأنواع.
اكتب برامج BPF الخاصة بك بلغة Go، وليس بلغة C. يحوّل gobee مجموعة فرعية صارمة من Go إلى BPF C، ويولّد روابط Go مكتوبة الأنواع لجانب مساحة المستخدم، ويقيّم التحميلات مقابل النواة الجارية.
يملك نظام Go البيئي أدوات مساحة مستخدم صلبة لـ BPF. أما الجانب النووي فكان دائمًا ينتهي بعبارة «الآن اكتب برنامجك بلغة C». جلبت Aya دعم eBPF إلى Rust بكتابة خلفية BPF جديدة داخل rustc. يصل gobee إلى ذلك بطريقة مختلفة: عبر التحويل إلى C وإعادة استخدام خلفية clang الناضجة.
نقطة تتبع تدفّق كل execve إلى مساحة المستخدم عبر ringbuf:
| مدخلاتك (Go) | ما يولّده gobee (BPF C) |
|---|---|
|
|
يُنتج gobee translate --bindings-dir ./bpf ./bpf/src كلا الملفين، بالإضافة إلى خريطة مصدر (events.bpf.c.map) بحيث تُرجَع أخطاء المدقق إلى أسطر Go، وملف روابط مكتوب الأنواع (bpf/events_bindings.go) بحيث يكتب برنامج تشغيل مساحة المستخدم objs.Events وobjs.AttachOnExec() ويفكّ ترميز حمولات ringbuf مباشرة إلى bpf.Event (نفس البنية التي تراها أعلاه، معاد نشرها في Go) بدلاً من عمليات البحث النصية coll.Programs["..."].
لغة C قابلة للقراءة عمدًا. إذا أصدر gobee شيئًا غريبًا، يمكنك رؤيته. لدمج tracepoints + kprobes + XDP في ملف ثنائي واحد، راجع example/sysmon/.
إذا كنت تعمل أصلًا ضمن سير عمل C / libbpf، فإن gobee لا يحاول استبداله كليًا. إنه للحالات التي تريد فيها الجانب النووي وجانب مساحة المستخدم وخط البناء كلها داخل وحدة Go واحدة.
راجع docs/status.md للمصفوفة الكاملة (مجموعة فرعية من Go، والعبارات، والتعبيرات، وكل مساعد، وكل نوع خريطة، وكل توجيه). نظرة سريعة:
go/types على مدخلاتك أولاً، بحيث تظهر الاستخدامات الخاطئة عند file:line:col).<Stem>_bindings.go مكتوب الأنواع بجوار .bpf.c: bpf.LoadCounter(spec)، وobjs.PerIface.Lookup(...)، وobjs.AttachAll(ifindex)، بالإضافة إلى أنواع بنى جانب النواة والثوابت معاد نشرها في Go.*ebpf.VerifierError الصادر من LoadAndAssign بمواضع مصدر Go، دون الحاجة لأنبوب يدوي عبر gobee diagnose.Load<Stem> بحيث تفشل النوى القديمة بسرعة مع bpf program needs kernel >= 5.8, host is 5.4.cilium/ebpf. الروابط المولَّدة تقع فوقه.gc، مترجم Go، لا يملك خلفية BPF مبنية على LLVM. إضافة واحدة مشروع مترجم يستغرق سنوات. rustc مبني على LLVM ولهذا تعمل Aya. لذا يُصدر gobee لغة C ويعيد استخدام خلفية clang لـ BPF، مما يمنحنا توليد كود ناضج وBTF وترحيلات CO-RE مجانًا.
go install github.com/boratanrikulu/gobee/cmd/gobee@latest
cd example/helloworld
make build # gobee translate, clang, go build
sudo ./helloworld eth0
ستحتاج إلى clang مع هدف BPF. على Linux، يكون ذلك حزمة التوزيعة؛ وعلى macOS، brew install llvm. المحوِّل نفسه مكتوب بلغة Go خالصة ويعمل في أي مكان.
yourproject/
├── bpf/ # Go package, importable from anywhere in your project
│ ├── embed_amd64.go # //go:embed bin/x86/your.bpf.o
│ ├── embed_arm64.go
│ ├── your_bindings.go # generated by gobee
│ ├── bin/{x86,arm64}/your.bpf.o
│ └── src/ # not a Go package; clang lives here
│ ├── your.go # //go:build ignore: BPF source
│ ├── your.bpf.c # generated
│ ├── Makefile # clang per arch
│ └── vmlinux.h # vendored BTF dump
├── main.go # imports yourproject/bpf
└── Makefile
يحافظ هذا التقسيم على bpf/ كحزمة Go نظيفة قابلة للاستيراد (يرفض Go ملفات .c في الحزم غير cgo). تعيش مصادر النواة ومخرجات clang على مستوى واحد أعمق داخل bpf/src/.
example/helloworld/: عدّاد حزم XDP المعياري، نحو 40 سطرًا من BPF ونحو 80 سطرًا لمساحة المستخدم.example/sysmon/: XDP ونقطتا تتبع وkprobe في ملف ثنائي واحد، تتشارك ringbuf للأحداث. يُظهر سياقات مكتوبة الأنواع لكل استدعاء نظام، ودوال مساعدة معرفة من المستخدم، واختصار AttachAll.يشغّل GitHub Actions أربع طبقات عند كل دفع:
go test وgo vet واختبارات golden للمحوّل//bpf:section مثال واحد على الأقلbpfvetebpf.NewCollectionWithOptions على كل .bpf.o (منفّذ Ubuntu 24.04، نواة 6.x)docs/design.md: العمارة والأساس المنطقيdocs/go-subset.md: صيغة Go المقبولة في ملفات مصدر BPFdocs/directives.md: مرجع //bpf:*docs/status.md: مصفوفة الدعم (المصدر الوحيد للحقيقة).bpf.o تتطلب clang مع هدف BPF. clang المرفق مع Apple لا يتضمن ذلك؛ على macOS استخدم brew install llvm أو ابنِ داخل جهاز افتراضي Linux.MIT. انظر LICENSE.
Copyright (c) 2026 Bora Tanrikulu <[email protected]>
| gobee | C + clang + bpf2go | Aya (Rust) | bpftrace | BCC |
|---|
| لغة الجانب النووي | مجموعة فرعية من Go | C | Rust | DSL | C |
| تكامل مساحة المستخدم | روابط Go مكتوبة الأنواع + cilium/ebpf | bpf2go | aya-runtime | لا شيء | python |
| CO-RE | ✅ عبر clang | ✅ | ✅ عبر LLVM | ✅ | ✅ |
| تغطية المساعدات | 200 غلاف Go مكتوب الأنواع | كاملة (اكتب C) | كاملة | محدودة | كاملة (اكتب C) |
| خطأ المدقق → المصدر | ✅ ملف Go:سطر:عمود | ❌ C خام | ✅ ملف Rust:سطر | ❌ | جزئي |
| بوابة إصدار النواة عند التحميل | ✅ عبر bpfvet | يدوي | يدوي | غير متاح | وقت التشغيل |
| اعتماديات سلسلة الأدوات | Go + clang | clang + bpf2go | rustc + LLVM | bpftrace | python + bcc |
| المخرجات المولَّدة | .bpf.o + ملف ثنائي Go | .bpf.o + ملف ثنائي Go | .bpf.o + ملف ثنائي Rust | JIT | JIT |
| السطح | التغطية |
|---|
| أنواع البرامج (8) | XDP, tracepoint, kprobe / kretprobe, uprobe / uretprobe, sock_ops, TC, cgroup_skb, LSM |
| أنواع الخرائط (19) | array, hash, lru_hash, متغيرات per-CPU، bloom_filter, lpm_trie, ringbuf, perf_event_array, prog_array, queue, stack, مخازن sk/task/inode، devmap/cpumap/xskmap |
| مساعدات BPF | نحو 200 كعب Go مكتوب الأنواع مولّد تلقائيًا من ترويسات libbpf v1.5.0. تلك التي تمارسها example/helloworld/ وexample/sysmon/ مُختبرة في CI بنواة حقيقية؛ أما البقية فغير متحقق منها. افتح issue إذا لم يطابق كعب توقيع النواة |
| CO-RE | ✅ اكتشاف تلقائي. BPF_CORE_READ لحقول البنى الداخلية للنواة (task_struct, sock, inode)؛ وctx->field مباشر لبنى سياق BPF الخاصة بـ UAPI (xdp_md, __sk_buff, bpf_sock_ops). مُختبر على Linux 6.x (CI بنظام Ubuntu 24.04)؛ النوى الأقدم ليست بعد ضمن مصفوفة CI |
| مخرجات جاهزة لـ BTF | ✅ لغة C المُصدرة تتضمن vmlinux.h وتستخدم BPF_CORE_READ لقراءة الحقول الداخلية للنواة، فيحمل BTF الذي يولّده clang من clang -g الترحيلات الصحيحة. يبقى clang نفسه مسؤوليتك (ملفات Makefiles في الأمثلة تُظهر الاستدعاء المعياري) |
| مساعدات معرفة من المستخدم | ✅ دوال Go على المستوى الأعلى التي لا تحمل //bpf:section تُصدر كدوال C من نوع static __always_inline |
| روابط Go مكتوبة الأنواع | ✅ Load<Stem>، وClose، وAttach<Name> لكل برنامج، وAttachAll، بالإضافة إلى أنواع بنى جانب النواة والثوابت معاد نشرها في Go |
| بوابة إصدار النواة | ✅ bpfvet يعمل وقت التحميل. يفشل بسرعة مع bpf program needs kernel >= 5.8, host is 5.4 بدلاً من EINVAL الغامض |
| خطأ المدقق → مصدر Go | ✅ مُعلَّم تلقائيًا داخل Load<Stem>. لا حاجة لأنبوب يدوي إلى gobee diagnose؛ يعود *ebpf.VerifierError مع علامات → counter.go:18:5 |
| خريطة مصدر جانبية | ✅ يُكتب <stem>.bpf.c.map بجوار كل .bpf.c لاستخدام gobee diagnose دون اتصال أيضًا |
| عبر البنى | ✅ Linux arm64 + amd64 |
static __always_inline