Skip to content

Commit e5c623f

Browse files
committed
windows: deal with removal of XDP_TEST from efW
The upstream efW removed the XDP_TEST program type from the repository. We rely on this type for our unit tests. Switch tests to the SAMPLE program type, which is a separate driver but also distributed as part of the efW runtime. On Windows, running a SAMPLE program requires providing a (possibly empty) context. To avoid having to change a lot of tests over and over we introduce a new mustRun helper. See: microsoft/ebpf-for-windows#4662 Signed-off-by: Lorenz Bauer <[email protected]>
1 parent c41a50a commit e5c623f

File tree

13 files changed

+133
-165
lines changed

13 files changed

+133
-165
lines changed

collection_test.go

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313

1414
"github.com/cilium/ebpf/asm"
1515
"github.com/cilium/ebpf/btf"
16-
"github.com/cilium/ebpf/internal"
1716
"github.com/cilium/ebpf/internal/testutils"
1817
"github.com/cilium/ebpf/internal/testutils/testmain"
1918
)
@@ -161,11 +160,7 @@ func TestCollectionSpecRewriteMaps(t *testing.T) {
161160

162161
coll := mustNewCollection(t, cs, nil)
163162

164-
ret, _, err := coll.Programs["test-prog"].Test(internal.EmptyBPFContext)
165-
testutils.SkipIfNotSupported(t, err)
166-
if err != nil {
167-
t.Fatal(err)
168-
}
163+
ret := mustRun(t, coll.Programs["test-prog"], nil)
169164

170165
if ret != 2 {
171166
t.Fatal("new / override map not used")
@@ -201,11 +196,7 @@ func TestCollectionSpecMapReplacements(t *testing.T) {
201196
},
202197
})
203198

204-
ret, _, err := coll.Programs["test-prog"].Test(internal.EmptyBPFContext)
205-
testutils.SkipIfNotSupported(t, err)
206-
if err != nil {
207-
t.Fatal(err)
208-
}
199+
ret := mustRun(t, coll.Programs["test-prog"], nil)
209200

210201
if ret != 2 {
211202
t.Fatal("new / override map not used")

elf_reader_test.go

Lines changed: 11 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -287,14 +287,8 @@ func TestLoadCollectionSpec(t *testing.T) {
287287
t.Fatal(err)
288288
}
289289

290-
ret, _, err := coll.Programs["xdp_prog"].Test(internal.EmptyBPFContext)
291-
if err != nil {
292-
t.Fatal("Can't run program:", err)
293-
}
294-
295-
if ret != 7 {
296-
t.Error("Unexpected return value:", ret)
297-
}
290+
ret := mustRun(t, coll.Programs["xdp_prog"], nil)
291+
qt.Assert(t, qt.Equals(ret, 7))
298292
})
299293
}
300294

@@ -322,11 +316,7 @@ func TestDataSections(t *testing.T) {
322316
mustLoadAndAssign(t, coll, &obj, nil)
323317
defer obj.Program.Close()
324318

325-
ret, _, err := obj.Program.Test(internal.EmptyBPFContext)
326-
if err != nil {
327-
t.Fatal(err)
328-
}
329-
319+
ret := mustRun(t, obj.Program, nil)
330320
if ret != 0 {
331321
t.Error("BPF assertion failed on line", ret)
332322
}
@@ -636,11 +626,7 @@ func TestTailCall(t *testing.T) {
636626
defer obj.Tail.Close()
637627
defer obj.ProgArray.Close()
638628

639-
ret, _, err := obj.TailMain.Test(internal.EmptyBPFContext)
640-
testutils.SkipIfNotSupported(t, err)
641-
if err != nil {
642-
t.Fatal(err)
643-
}
629+
ret := mustRun(t, obj.Tail, nil)
644630

645631
// Expect the tail_1 tail call to be taken, returning value 42.
646632
if ret != 42 {
@@ -666,12 +652,7 @@ func TestKconfig(t *testing.T) {
666652
}
667653
defer obj.Main.Close()
668654

669-
ret, _, err := obj.Main.Test(internal.EmptyBPFContext)
670-
testutils.SkipIfNotSupported(t, err)
671-
if err != nil {
672-
t.Fatal(err)
673-
}
674-
655+
ret := mustRun(t, obj.Main, nil)
675656
qt.Assert(t, qt.Equals(ret, 0), qt.Commentf("Failed assertion at line %d in testdata/kconfig.c", ret))
676657
}
677658

@@ -691,9 +672,7 @@ func TestKsym(t *testing.T) {
691672
defer obj.Main.Close()
692673
defer obj.ArrayMap.Close()
693674

694-
_, _, err = obj.Main.Test(internal.EmptyBPFContext)
695-
testutils.SkipIfNotSupported(t, err)
696-
qt.Assert(t, qt.IsNil(err))
675+
mustRun(t, obj.Main, nil)
697676

698677
ksyms := map[string]uint64{
699678
"bpf_init": 0,
@@ -726,10 +705,8 @@ func TestKsymWeakMissing(t *testing.T) {
726705
qt.Assert(t, qt.IsNil(err))
727706
defer obj.Main.Close()
728707

729-
res, _, err := obj.Main.Test(internal.EmptyBPFContext)
730-
testutils.SkipIfNotSupported(t, err)
731-
qt.Assert(t, qt.IsNil(err))
732-
qt.Assert(t, qt.Equals(res, 1))
708+
ret := mustRun(t, obj.Main, nil)
709+
qt.Assert(t, qt.Equals(ret, 1))
733710
}
734711

735712
func TestKfunc(t *testing.T) {
@@ -751,11 +728,7 @@ func TestKfunc(t *testing.T) {
751728
}
752729
defer obj.Main.Close()
753730

754-
ret, _, err := obj.Main.Test(internal.EmptyBPFContext)
755-
testutils.SkipIfNotSupported(t, err)
756-
if err != nil {
757-
t.Fatal(err)
758-
}
731+
ret := mustRun(t, obj.Main, nil)
759732

760733
if ret != 1 {
761734
t.Fatalf("Expected kfunc to return value 1, got %d", ret)
@@ -822,11 +795,7 @@ func TestKfuncKmod(t *testing.T) {
822795
}
823796
defer obj.Main.Close()
824797

825-
ret, _, err := obj.Main.Test(internal.EmptyBPFContext)
826-
testutils.SkipIfNotSupported(t, err)
827-
if err != nil {
828-
t.Fatal(err)
829-
}
798+
ret := mustRun(t, obj.Main, nil)
830799

831800
if ret != 1 {
832801
t.Fatalf("Expected kfunc to return value 1, got %d", ret)
@@ -855,11 +824,7 @@ func TestSubprogRelocation(t *testing.T) {
855824
defer obj.Main.Close()
856825
defer obj.HashMap.Close()
857826

858-
ret, _, err := obj.Main.Test(internal.EmptyBPFContext)
859-
testutils.SkipIfNotSupported(t, err)
860-
if err != nil {
861-
t.Fatal(err)
862-
}
827+
ret := mustRun(t, obj.Main, nil)
863828

864829
if ret != 42 {
865830
t.Fatalf("Expected subprog reloc to return value 42, got %d", ret)

helpers_test.go

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/cilium/ebpf/asm"
1111
"github.com/cilium/ebpf/btf"
12+
"github.com/cilium/ebpf/internal"
1213
"github.com/cilium/ebpf/internal/platform"
1314
"github.com/cilium/ebpf/internal/testutils"
1415
)
@@ -195,6 +196,33 @@ func mustLoadAndAssign(tb testing.TB, spec *CollectionSpec, to any, opts *Collec
195196
qt.Assert(tb, qt.IsNil(loadAndAssign(tb, spec, to, opts)))
196197
}
197198

199+
func mustRun(tb testing.TB, prog *Program, opts *RunOptions) (retval uint32) {
200+
tb.Helper()
201+
202+
if opts == nil {
203+
opts = &RunOptions{}
204+
}
205+
if platform.IsLinux && opts.Data == nil {
206+
opts.Data = internal.EmptyBPFContext
207+
}
208+
if platform.IsWindows {
209+
switch prog.Type() {
210+
case WindowsSample:
211+
const minSampleContextLen = 32
212+
213+
if opts.Context == nil {
214+
opts.Context = make([]byte, minSampleContextLen)
215+
}
216+
}
217+
}
218+
219+
ret, err := prog.Run(opts)
220+
testutils.SkipIfNotSupported(tb, err)
221+
qt.Assert(tb, qt.IsNil(err))
222+
223+
return ret
224+
}
225+
198226
// The functions below translate Linux types to their Windows equivalents, if
199227
// possible. This allows running most tests on Windows without modification.
200228

@@ -256,9 +284,9 @@ func fixupProgramType(typ ProgramType) ProgramType {
256284

257285
switch typ {
258286
case SocketFilter:
259-
return WindowsXDPTest
287+
return WindowsSample
260288
case XDP:
261-
return WindowsXDPTest
289+
return WindowsSample
262290
default:
263291
return typ
264292
}

info_test.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -461,9 +461,7 @@ func testStats(tb testing.TB, prog *Program) error {
461461

462462
// Program execution with runtime statistics enabled.
463463
// Should increase both runtime and run counter.
464-
if _, _, err := prog.Test(in); err != nil {
465-
return fmt.Errorf("failed to trigger program: %w", err)
466-
}
464+
mustRun(tb, prog, &RunOptions{Data: in})
467465

468466
s1, err := prog.Stats()
469467
qt.Assert(tb, qt.IsNil(err))
@@ -475,9 +473,7 @@ func testStats(tb testing.TB, prog *Program) error {
475473

476474
// Second program execution, with runtime statistics gathering disabled.
477475
// Total runtime and run counters are not expected to increase.
478-
if _, _, err := prog.Test(in); err != nil {
479-
return fmt.Errorf("failed to trigger program: %w", err)
480-
}
476+
mustRun(tb, prog, &RunOptions{Data: in})
481477

482478
s2, err := prog.Stats()
483479
qt.Assert(tb, qt.IsNil(err))

internal/efw/proc_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func TestNewProc(t *testing.T) {
1616
func TestCall(t *testing.T) {
1717
var err error
1818
allocs := testing.AllocsPerRun(10, func() {
19-
_, err = EbpfGetEbpfAttachType(1)
19+
_, err = EbpfGetEbpfAttachType(2)
2020
})
2121
qt.Assert(t, qt.IsNil(err))
2222
qt.Assert(t, qt.Equals(allocs, 0))

internal/testutils/bpffs_windows_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func TestTempBPFFS(t *testing.T) {
3030
qt.Assert(t, qt.IsNil(err))
3131

3232
progFd, err := sys.ProgLoad(&sys.ProgLoadAttr{
33-
ProgType: 998, // XDP_TEST
33+
ProgType: 999, // SAMPLE
3434
License: sys.NewStringPointer(""),
3535
InsnCnt: uint32(buffer.Len() / asm.InstructionSize),
3636
Insns: sys.SlicePointer(buffer.Bytes()),

linker_test.go

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66

77
"github.com/cilium/ebpf/asm"
88
"github.com/cilium/ebpf/btf"
9-
"github.com/cilium/ebpf/internal"
109
"github.com/cilium/ebpf/internal/testutils"
1110

1211
"github.com/go-quicktest/qt"
@@ -45,10 +44,7 @@ func TestFindReferences(t *testing.T) {
4544
testutils.SkipIfNotSupported(t, err)
4645
qt.Assert(t, qt.IsNil(err))
4746

48-
ret, _, err := prog.Test(internal.EmptyBPFContext)
49-
if err != nil {
50-
t.Fatal(err)
51-
}
47+
ret := mustRun(t, prog, nil)
5248

5349
if ret != 1337 {
5450
t.Errorf("Expected return code 1337, got %d", ret)
@@ -91,10 +87,8 @@ func TestForwardFunctionDeclaration(t *testing.T) {
9187
testutils.SkipIfNotSupported(t, err)
9288
qt.Assert(t, qt.IsNil(err))
9389

94-
ret, _, err := prog.Test(internal.EmptyBPFContext)
95-
if err != nil {
96-
t.Fatal("Running program:", err)
97-
}
90+
ret := mustRun(t, prog, nil)
91+
9892
if ret != 23 {
9993
t.Fatalf("Expected 23, got %d", ret)
10094
}

pin/load_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func mustPinnedProgram(t *testing.T, path string) *ebpf.Program {
1818

1919
typ := ebpf.SocketFilter
2020
if platform.IsWindows {
21-
typ = ebpf.WindowsXDPTest
21+
typ = ebpf.WindowsSample
2222
}
2323

2424
spec := &ebpf.ProgramSpec{

prog_test.go

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -79,36 +79,33 @@ func TestProgramRun(t *testing.T) {
7979
prog.Close()
8080
prog = p2
8181

82-
ret, out, err := prog.Test(buf)
83-
testutils.SkipIfNotSupported(t, err)
84-
if err != nil {
85-
t.Fatal(err)
86-
}
87-
88-
if ret != 42 {
89-
t.Error("Expected return value to be 42, got", ret)
90-
}
91-
92-
if !bytes.Equal(out[:len(pat)], pat) {
93-
t.Errorf("Expected %v, got %v", pat, out)
94-
}
82+
out := make([]byte, len(buf))
83+
ret := mustRun(t, prog, &RunOptions{Data: buf, DataOut: out})
84+
qt.Assert(t, qt.Equals(ret, 42))
85+
qt.Assert(t, qt.DeepEquals(out[:len(pat)], pat))
9586
}
9687

9788
func TestProgramRunWithOptions(t *testing.T) {
9889
testutils.SkipOnOldKernel(t, "5.15", "XDP ctx_in/ctx_out")
9990

100-
prog := createProgram(t, XDP, int64(sys.XDP_ABORTED))
101-
10291
buf := internal.EmptyBPFContext
92+
var prog *Program
10393
var in, out any
10494
if platform.IsWindows {
105-
type winXdpMd struct {
106-
Data, DataEnd, DataMeta uint64
107-
Ifindex uint32
95+
type winSampleProgramContext struct {
96+
_ uint64 // data_start (currently leaks kernel pointer)
97+
_ uint64 // data_end (currently leaks kernel pointer)
98+
Uint32Data uint32
99+
Uint16Data uint16
100+
_ uint16
101+
HelperData1 uint32
102+
HelperData2 uint32
108103
}
109-
in = &winXdpMd{Data: 0, DataEnd: uint64(len(buf))}
110-
out = &winXdpMd{}
104+
prog = createProgram(t, WindowsSample, 0)
105+
in = &winSampleProgramContext{Uint32Data: 23, HelperData2: 42}
106+
out = &winSampleProgramContext{Uint32Data: 23, HelperData2: 42}
111107
} else {
108+
prog = createProgram(t, XDP, int64(sys.XDP_ABORTED))
112109
in = &sys.XdpMd{Data: 0, DataEnd: uint32(len(buf))}
113110
out = &sys.XdpMd{}
114111
}
@@ -155,6 +152,10 @@ func TestProgramRunEmptyData(t *testing.T) {
155152
}
156153

157154
func TestProgramBenchmark(t *testing.T) {
155+
if platform.IsWindows {
156+
t.Skip("BPF_PROG_TEST_RUN requires providing context on Windows")
157+
}
158+
158159
prog := createBasicProgram(t)
159160

160161
ret, duration, err := prog.Benchmark(internal.EmptyBPFContext, 1, nil)

ringbuf/helper_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package ringbuf
2+
3+
import (
4+
"testing"
5+
6+
"github.com/go-quicktest/qt"
7+
8+
"github.com/cilium/ebpf"
9+
"github.com/cilium/ebpf/internal"
10+
"github.com/cilium/ebpf/internal/platform"
11+
"github.com/cilium/ebpf/internal/testutils"
12+
)
13+
14+
func mustRun(tb testing.TB, prog *ebpf.Program) {
15+
tb.Helper()
16+
17+
opts := &ebpf.RunOptions{
18+
Data: internal.EmptyBPFContext,
19+
}
20+
if platform.IsWindows {
21+
opts.Context = make([]byte, 32)
22+
}
23+
24+
ret, err := prog.Run(opts)
25+
testutils.SkipIfNotSupported(tb, err)
26+
qt.Assert(tb, qt.IsNil(err))
27+
28+
qt.Assert(tb, qt.Equals(ret, uint32(0)))
29+
}

0 commit comments

Comments
 (0)