mirror of
https://github.com/daeuniverse/dae.git
synced 2025-01-07 05:51:20 +07:00
438c05cbd6
Co-authored-by: mzz <2017@duck.com>
168 lines
4.2 KiB
Go
168 lines
4.2 KiB
Go
/*
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
* Copyright (c) 2022-2024, daeuniverse Organization <dae@v2raya.org>
|
|
*/
|
|
|
|
package tests
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/cilium/ebpf"
|
|
"github.com/vishvananda/netlink/nl"
|
|
)
|
|
|
|
//go:generate go run -mod=mod github.com/cilium/ebpf/cmd/bpf2go -cc "$BPF_CLANG" "$BPF_STRIP_FLAG" -cflags "$BPF_CFLAGS" -target "$BPF_TARGET" bpftest ./bpf_test.c -- -I../headers -I.
|
|
|
|
type programSet struct {
|
|
id string
|
|
pktgen *ebpf.Program
|
|
setup *ebpf.Program
|
|
check *ebpf.Program
|
|
}
|
|
|
|
func runBpfProgram(prog *ebpf.Program, data, ctx []byte) (statusCode uint32, dataOut, ctxOut []byte, err error) {
|
|
dataOut = make([]byte, len(data))
|
|
if len(dataOut) > 0 {
|
|
// See comments at https://github.com/cilium/ebpf/blob/20c4d8896bdde990ce6b80d59a4262aa3ccb891d/prog.go#L563-L567
|
|
dataOut = make([]byte, len(data)+256+2)
|
|
}
|
|
ctxOut = make([]byte, len(ctx))
|
|
opts := &ebpf.RunOptions{
|
|
Data: data,
|
|
DataOut: dataOut,
|
|
Context: ctx,
|
|
ContextOut: ctxOut,
|
|
Repeat: 1,
|
|
}
|
|
ret, err := prog.Run(opts)
|
|
return ret, opts.DataOut, ctxOut, err
|
|
}
|
|
|
|
func collectPrograms(t *testing.T) (progset []programSet, err error) {
|
|
obj := &bpftestObjects{}
|
|
pinPath := "/sys/fs/bpf/dae"
|
|
if err = os.MkdirAll(pinPath, 0755); err != nil && !os.IsExist(err) {
|
|
return
|
|
}
|
|
|
|
if err = loadBpftestObjects(obj,
|
|
&ebpf.CollectionOptions{
|
|
Maps: ebpf.MapOptions{
|
|
PinPath: pinPath,
|
|
},
|
|
Programs: ebpf.ProgramOptions{
|
|
LogSize: ebpf.DefaultVerifierLogSize * 10,
|
|
},
|
|
},
|
|
); err != nil {
|
|
var (
|
|
ve *ebpf.VerifierError
|
|
verifierLog string
|
|
)
|
|
if errors.As(err, &ve) {
|
|
verifierLog = fmt.Sprintf("Verifier error: %+v\n", ve)
|
|
}
|
|
|
|
t.Fatalf("Failed to load objects: %s\n%+v", verifierLog, err)
|
|
|
|
return nil, err
|
|
}
|
|
|
|
if err = obj.LpmArrayMap.Update(uint32(0), obj.UnusedLpmType, ebpf.UpdateAny); err != nil {
|
|
t.Fatalf("Failed to update LpmArrayMap: %s", err)
|
|
return
|
|
}
|
|
|
|
v := reflect.ValueOf(obj.bpftestPrograms)
|
|
typeOfV := v.Type()
|
|
for i := 0; i < v.NumField(); i++ {
|
|
progname := typeOfV.Field(i).Name
|
|
if strings.HasPrefix(progname, "Testsetup") {
|
|
progid := strings.TrimPrefix(progname, "Testsetup")
|
|
progset = append(progset, programSet{
|
|
id: progid,
|
|
pktgen: v.FieldByName("Testpktgen" + progid).Interface().(*ebpf.Program),
|
|
setup: v.FieldByName("Testsetup" + progid).Interface().(*ebpf.Program),
|
|
check: v.FieldByName("Testcheck" + progid).Interface().(*ebpf.Program),
|
|
})
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func consumeBpfDebugLog(t *testing.T) {
|
|
readBpfDebugLog(t)
|
|
}
|
|
|
|
func printBpfDebugLog(t *testing.T) {
|
|
fmt.Print(readBpfDebugLog(t))
|
|
}
|
|
|
|
func readBpfDebugLog(t *testing.T) string {
|
|
file, err := os.Open("/sys/kernel/tracing/trace_pipe")
|
|
if err != nil {
|
|
t.Fatalf("Failed to open trace_pipe: %v", err)
|
|
}
|
|
defer file.Close()
|
|
|
|
buffer := make([]byte, 1024*64)
|
|
n, err := file.Read(buffer)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read from trace_pipe: %v", err)
|
|
}
|
|
|
|
return string(buffer[:n])
|
|
}
|
|
|
|
func Test(t *testing.T) {
|
|
progsets, err := collectPrograms(t)
|
|
if err != nil {
|
|
t.Fatalf("error while collecting programs: %s", err)
|
|
}
|
|
|
|
for _, progset := range progsets {
|
|
t.Logf("Running test: %s\n", progset.id)
|
|
// create ctx with the max allowed size(4k - head room - tailroom)
|
|
data := make([]byte, 4096-256-320)
|
|
|
|
// sizeof(struct __sk_buff) < 256, let's make it 256
|
|
ctx := make([]byte, 256)
|
|
|
|
statusCode, data, ctx, err := runBpfProgram(progset.pktgen, data, ctx)
|
|
if err != nil {
|
|
t.Fatalf("error while running pktgen prog: %s", err)
|
|
}
|
|
if statusCode != 0 {
|
|
printBpfDebugLog(t)
|
|
t.Fatalf("error while running pktgen program: unexpected status code: %d", statusCode)
|
|
}
|
|
|
|
statusCode, data, ctx, err = runBpfProgram(progset.setup, data, ctx)
|
|
if err != nil {
|
|
printBpfDebugLog(t)
|
|
t.Fatalf("error while running setup prog: %s", err)
|
|
}
|
|
|
|
status := make([]byte, 4)
|
|
nl.NativeEndian().PutUint32(status, statusCode)
|
|
data = append(status, data...)
|
|
|
|
statusCode, data, ctx, err = runBpfProgram(progset.check, data, ctx)
|
|
if err != nil {
|
|
t.Fatalf("error while running check program: %+v", err)
|
|
}
|
|
if statusCode != 0 {
|
|
printBpfDebugLog(t)
|
|
t.Fatalf("error while running check program: unexpected status code: %d", statusCode)
|
|
}
|
|
|
|
consumeBpfDebugLog(t)
|
|
}
|
|
}
|