Skip to content

Commit

Permalink
bpf2go: generate assignment structs for Variables and VariableSpecs
Browse files Browse the repository at this point in the history
This commit teaches bpf2go to emit assignment structs for VariableSpecs and
Variables. Similar to maps and programs, the generated bpf_bpfe{b,l}.go have
bpfVariableSpecs embedded in bpfSpecs and bpfVariables in bpfSpecs.

Also fixed a typo in the bpfProgramSpecs comments in output.tpl that emitted
bpfSpecs rather than bpfProgramSpecs.

Signed-off-by: Simone Magnani <simone.magnani@isovalent.com>
  • Loading branch information
smagnani96 authored and ti-mo committed Dec 18, 2024
1 parent c37b7af commit 1e8f079
Show file tree
Hide file tree
Showing 34 changed files with 530 additions and 43 deletions.
17 changes: 17 additions & 0 deletions cmd/bpf2go/gen/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ func (n templateName) MapSpecs() string {
return string(n) + "MapSpecs"
}

func (n templateName) VariableSpecs() string {
return string(n) + "VariableSpecs"
}

func (n templateName) Load() string {
return n.maybeExport("load" + toUpperFirst(string(n)))
}
Expand All @@ -65,6 +69,10 @@ func (n templateName) Maps() string {
return string(n) + "Maps"
}

func (n templateName) Variables() string {
return string(n) + "Variables"
}

func (n templateName) Programs() string {
return string(n) + "Programs"
}
Expand All @@ -82,6 +90,8 @@ type GenerateArgs struct {
Constraints constraint.Expr
// Maps to be emitted.
Maps []string
// Variables to be emitted.
Variables []string
// Programs to be emitted.
Programs []string
// Types to be emitted.
Expand Down Expand Up @@ -121,6 +131,11 @@ func Generate(args GenerateArgs) error {
maps[name] = args.Identifier(name)
}

variables := make(map[string]string)
for _, name := range args.Variables {
variables[name] = args.Identifier(name)
}

programs := make(map[string]string)
for _, name := range args.Programs {
programs[name] = args.Identifier(name)
Expand Down Expand Up @@ -151,6 +166,7 @@ func Generate(args GenerateArgs) error {
Constraints constraint.Expr
Name templateName
Maps map[string]string
Variables map[string]string
Programs map[string]string
Types []btf.Type
TypeNames map[btf.Type]string
Expand All @@ -162,6 +178,7 @@ func Generate(args GenerateArgs) error {
args.Constraints,
templateName(args.Stem),
maps,
variables,
programs,
types,
typeNames,
Expand Down
22 changes: 21 additions & 1 deletion cmd/bpf2go/gen/output.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ func {{ .Name.LoadObjects }}(obj interface{}, opts *ebpf.CollectionOptions) (err
type {{ .Name.Specs }} struct {
{{ .Name.ProgramSpecs }}
{{ .Name.MapSpecs }}
{{ .Name.VariableSpecs }}
}

// {{ .Name.Specs }} contains programs before they are loaded into the kernel.
// {{ .Name.ProgramSpecs }} contains programs before they are loaded into the kernel.
//
// It can be passed ebpf.CollectionSpec.Assign.
type {{ .Name.ProgramSpecs }} struct {
Expand All @@ -74,12 +75,22 @@ type {{ .Name.MapSpecs }} struct {
{{- end }}
}

// {{ .Name.VariableSpecs }} contains global variables before they are loaded into the kernel.
//
// It can be passed ebpf.CollectionSpec.Assign.
type {{ .Name.VariableSpecs }} struct {
{{- range $name, $id := .Variables }}
{{ $id }} *ebpf.VariableSpec `ebpf:"{{ $name }}"`
{{- end }}
}

// {{ .Name.Objects }} contains all objects after they have been loaded into the kernel.
//
// It can be passed to {{ .Name.LoadObjects }} or ebpf.CollectionSpec.LoadAndAssign.
type {{ .Name.Objects }} struct {
{{ .Name.Programs }}
{{ .Name.Maps }}
{{ .Name.Variables }}
}

func (o *{{ .Name.Objects }}) Close() error {
Expand All @@ -106,6 +117,15 @@ func (m *{{ .Name.Maps }}) Close() error {
)
}

// {{ .Name.Variables }} contains all global variables after they have been loaded into the kernel.
//
// It can be passed to {{ .Name.LoadObjects }} or ebpf.CollectionSpec.LoadAndAssign.
type {{ .Name.Variables }} struct {
{{- range $name, $id := .Variables }}
{{ $id }} *ebpf.Variable `ebpf:"{{ $name }}"`
{{- end }}
}

// {{ .Name.Programs }} contains all programs after they have been loaded into the kernel.
//
// It can be passed to {{ .Name.LoadObjects }} or ebpf.CollectionSpec.LoadAndAssign.
Expand Down
24 changes: 24 additions & 0 deletions cmd/bpf2go/gen/output_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,27 @@ func TestCustomIdentifier(t *testing.T) {
qt.Assert(t, qt.IsNil(err))
qt.Assert(t, qt.StringContains(buf.String(), "DO_THING"))
}

func TestObjects(t *testing.T) {
var buf bytes.Buffer
args := GenerateArgs{
Package: "foo",
Stem: "bar",
Maps: []string{"map1"},
Variables: []string{"var_1"},
Programs: []string{"prog_foo_1"},
Output: &buf,
}
err := Generate(args)
qt.Assert(t, qt.IsNil(err))

str := buf.String()

qt.Assert(t, qt.StringContains(str, "Map1 *ebpf.MapSpec `ebpf:\"map1\"`"))
qt.Assert(t, qt.StringContains(str, "Var1 *ebpf.VariableSpec `ebpf:\"var_1\"`"))
qt.Assert(t, qt.StringContains(str, "ProgFoo1 *ebpf.ProgramSpec `ebpf:\"prog_foo_1\"`"))

qt.Assert(t, qt.StringContains(str, "Map1 *ebpf.Map `ebpf:\"map1\"`"))
qt.Assert(t, qt.StringContains(str, "Var1 *ebpf.Variable `ebpf:\"var_1\"`"))
qt.Assert(t, qt.StringContains(str, "ProgFoo1 *ebpf.Program `ebpf:\"prog_foo_1\"`"))
}
6 changes: 6 additions & 0 deletions cmd/bpf2go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,11 @@ func (b2g *bpf2go) convert(tgt gen.Target, goarches gen.GoArches) (err error) {
}
}

var variables []string
for name := range spec.Variables {
variables = append(variables, name)
}

var programs []string
for name := range spec.Programs {
programs = append(programs, name)
Expand Down Expand Up @@ -397,6 +402,7 @@ func (b2g *bpf2go) convert(tgt gen.Target, goarches gen.GoArches) (err error) {
Stem: b2g.identStem,
Constraints: constraints,
Maps: maps,
Variables: variables,
Programs: programs,
Types: types,
ObjectFile: filepath.Base(objFileName),
Expand Down
24 changes: 11 additions & 13 deletions cmd/bpf2go/test/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@ import (
"testing"
"unsafe"

"github.com/go-quicktest/qt"

"github.com/cilium/ebpf/internal/testutils"
)

func TestLoadingSpec(t *testing.T) {
spec, err := loadTest()
testutils.SkipIfNotSupported(t, err)
if err != nil {
t.Fatal("Can't load spec:", err)
}
qt.Assert(t, qt.IsNil(err))

if spec == nil {
t.Fatal("Got a nil spec")
}
qt.Assert(t, qt.Not(qt.IsNil(spec)))
qt.Assert(t, qt.Not(qt.IsNil(spec.Programs)))
qt.Assert(t, qt.Not(qt.IsNil(spec.Maps)))
qt.Assert(t, qt.Not(qt.IsNil(spec.Variables)))
}

func TestLoadingObjects(t *testing.T) {
Expand All @@ -29,13 +30,10 @@ func TestLoadingObjects(t *testing.T) {
}
defer objs.Close()

if objs.Filter == nil {
t.Error("Loading returns an object with nil programs")
}

if objs.Map1 == nil {
t.Error("Loading returns an object with nil maps")
}
qt.Assert(t, qt.Not(qt.IsNil(objs.Filter)))
qt.Assert(t, qt.Not(qt.IsNil(objs.Map1)))
qt.Assert(t, qt.Not(qt.IsNil(objs.MyConstant)))
qt.Assert(t, qt.Not(qt.IsNil(objs.StructConst)))
}

func TestTypes(t *testing.T) {
Expand Down
20 changes: 19 additions & 1 deletion cmd/bpf2go/test/test_bpfeb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 19 additions & 1 deletion cmd/bpf2go/test/test_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 15 additions & 1 deletion docs/examples/getting_started/counter_bpfeb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 15 additions & 1 deletion docs/examples/getting_started/counter_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 1e8f079

Please sign in to comment.