File: ebpf_example_test.go

package info (click to toggle)
golang-github-cloudflare-cbpfc 0.0~git20231012.992ed75-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 232 kB
  • sloc: makefile: 4
file content (68 lines) | stat: -rw-r--r-- 1,676 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package cbpfc

import (
	"github.com/cilium/ebpf/asm"
	"github.com/pkg/errors"
	"golang.org/x/net/bpf"
)

// ExampleToEBPF demonstrates how to use ToEBPF() to embed a cBPF filter
// in an eBPF assembly program.
func ExampleToEBPF() {
	// simple cBPF filter that matches all packets
	filter := []bpf.Instruction{
		bpf.RetConstant{Val: 1},
	}

	prog, err := buildEBPF(filter)
	if err != nil {
		panic(err)
	}

	// Prog can be loaded directly using cilium/ebpf,
	// or converted to a '[]struct bpf_insn' for libbpf
	_ = prog
}

// buildEBPF compiles a cBPF filter to eBPF, and embeds it an eBPF program.
// The XDP program XDP_DROP's incoming packets that match the filter.
// Returns the eBPF program instructions
func buildEBPF(filter []bpf.Instruction) (asm.Instructions, error) {
	ebpfFilter, err := ToEBPF(filter, EBPFOpts{
		// Pass packet start and end pointers in these registers
		PacketStart: asm.R2,
		PacketEnd:   asm.R3,
		// Result of filter
		Result:      asm.R4,
		ResultLabel: "result",
		// Registers used by generated code
		Working:     [4]asm.Register{asm.R4, asm.R5, asm.R6, asm.R7},
		LabelPrefix: "filter",
	})
	if err != nil {
		return nil, errors.Wrap(err, "converting filter to eBPF")
	}

	prog := asm.Instructions{
		// R1 holds XDP context

		// Packet start
		asm.LoadMem(asm.R2, asm.R1, 0, asm.Word),

		// Packet end
		asm.LoadMem(asm.R3, asm.R1, 4, asm.Word),

		// Fall through to filter
	}

	prog = append(prog, ebpfFilter...)

	prog = append(prog,
		asm.Mov.Imm(asm.R0, 2).WithSymbol("result"), // XDP_PASS
		asm.JEq.Imm(asm.R4, 0, "return"),
		asm.Mov.Imm(asm.R0, 1), // XDP_DROP
		asm.Return().WithSymbol("return"),
	)

	return prog, nil
}