Skip to content

Commit 8abfdba

Browse files
committed
struct_ops: implement onProgramLoaded() and postLoad()
1. implemented the above functions so that build kern_vdata 2. support "mod_btf" handling for testing 3. fix newProgramWithOptions() so that load structOps programs 4. fix createMap() so that find struct types from mod_btf Signed-off-by: shun159 <[email protected]>
1 parent 4a41b01 commit 8abfdba

File tree

5 files changed

+172
-51
lines changed

5 files changed

+172
-51
lines changed

collection.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions)
309309
}
310310

311311
// load programs to struct_ops maps
312-
if err := loader.stOps.postLoad(loader.maps); err != nil {
312+
if err := loader.stOps.postLoad(loader.maps, loader.programs); err != nil {
313313
return err
314314
}
315315

@@ -595,7 +595,7 @@ func (cl *collectionLoader) loadProgram(progName string) (*Program, error) {
595595
cl.programs[progName] = prog
596596

597597
if prog.Type() == StructOps {
598-
if err := cl.stOps.onProgramLoaded(prog, progSpec, cl.coll); err != nil {
598+
if err := cl.stOps.onProgramLoaded(prog, progSpec); err != nil {
599599
return nil, err
600600
}
601601
}

collection_test.go

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/cilium/ebpf/asm"
1515
"github.com/cilium/ebpf/btf"
1616
"github.com/cilium/ebpf/internal"
17+
"github.com/cilium/ebpf/internal/sys"
1718
"github.com/cilium/ebpf/internal/testutils"
1819
"github.com/cilium/ebpf/internal/testutils/testmain"
1920
)
@@ -776,27 +777,42 @@ func TestStructOpsMapSpecSimpleLoadAndAssign(t *testing.T) {
776777
requireStructOpsDummy(t)
777778

778779
spec := &CollectionSpec{
780+
Programs: map[string]*ProgramSpec{
781+
"dummy_test_1": {
782+
Name: "dummy_test_1",
783+
Type: StructOps,
784+
License: "GPL",
785+
Instructions: asm.Instructions{
786+
asm.Mov.Imm(asm.R0, 0),
787+
asm.Return(),
788+
},
789+
},
790+
},
779791
Maps: map[string]*MapSpec{
780792
// TODO: we should use "bpf_testmod_ops" for this case (tentative test case)
781793
"dummy_ops": {
782794
Name: "dummy_ops",
783795
Type: StructOpsMap,
796+
Flags: sys.BPF_F_LINK,
784797
KeySize: 4,
785-
ValueSize: 128,
798+
ValueSize: 448,
786799
MaxEntries: 1,
787-
Value: &btf.Struct{Name: "bpf_dummy_ops"},
800+
Value: &btf.Struct{Name: "bpf_testmod_ops"},
788801
Contents: []MapKV{
789802
{Key: uint32(0), Value: structOpsMeta{
790-
data: make([]byte, 128),
791-
funcs: []structOpsFunc{},
803+
data: make([]byte, 448),
804+
funcs: []structOpsFunc{
805+
{"test_1", "dummy_test_1"},
806+
},
792807
}},
793808
},
794809
},
795810
},
796811
}
797812

798813
var obj struct {
799-
DummyOps *Map `ebpf:"dummy_ops"`
814+
DummyTest1 *Program `ebpf:"dummy_test_1"`
815+
DummyOps *Map `ebpf:"dummy_ops"`
800816
}
801817

802818
err := spec.LoadAndAssign(&obj, nil)

map.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -569,20 +569,12 @@ func (spec *MapSpec) createMap(inner *sys.FD) (_ *Map, err error) {
569569
return nil, fmt.Errorf("struct type is not specified as Value")
570570
}
571571

572-
userStructTypeName := spec.Value.TypeName()
573-
t, err := s.AnyTypeByName(structOpsValuePrefix + userStructTypeName)
574-
if errors.Is(err, btf.ErrNotFound) {
575-
return nil, fmt.Errorf("struct_ops kernel type %q: %w", userStructTypeName, btf.ErrNotFound)
576-
}
577-
if err != nil {
578-
return nil, fmt.Errorf("lookup kernel type %q: %w", userStructTypeName, err)
579-
}
580-
581-
userStructType, ok := t.(*btf.Struct)
572+
userStType, ok := spec.Value.(*btf.Struct)
582573
if !ok {
583574
return nil, fmt.Errorf("value must be Struct type")
584575
}
585576

577+
userStructType, s, modBtfObjId, err := findStructByNameWithPrefix(s, userStType)
586578
btfValueTypeId, err := s.TypeID(userStructType)
587579
if err != nil {
588580
return nil, fmt.Errorf("lookup type_id: %w", err)
@@ -591,6 +583,16 @@ func (spec *MapSpec) createMap(inner *sys.FD) (_ *Map, err error) {
591583
attr.ValueSize = spec.ValueSize
592584
attr.BtfVmlinuxValueTypeId = btfValueTypeId
593585
attr.BtfFd = uint32(h.FD())
586+
587+
if modBtfObjId != 0 {
588+
attr.MapFlags |= sys.BPF_F_VTYPE_BTF_OBJ_FD
589+
modH, err := btf.NewHandleFromID(btf.ID(modBtfObjId))
590+
if err != nil {
591+
return nil, fmt.Errorf("open module BTF (id=%d): %w", modBtfObjId, err)
592+
}
593+
attr.ValueTypeBtfObjFd = int32(modH.FD())
594+
defer modH.Close()
595+
}
594596
} else {
595597
handle, keyTypeID, valueTypeID, err := btf.MarshalMapKV(spec.Key, spec.Value)
596598
if err != nil && !errors.Is(err, btf.ErrNotSupported) {

prog.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,24 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, c *btf.Cache)
395395
}
396396
}
397397

398+
if spec.Type == StructOps {
399+
if meta, ok := spec.Instructions[0].Metadata.Get(structOpsProgMetaKey{}).(*structOpsProgMeta); ok {
400+
attr.AttachBtfId = sys.TypeID(meta.AttachBtfId)
401+
attr.ExpectedAttachType = meta.AttachType
402+
403+
var modH *btf.Handle
404+
if meta.ModBtfObjID != 0 {
405+
h, err := btf.NewHandleFromID(btf.ID(meta.ModBtfObjID))
406+
if err != nil {
407+
return nil, fmt.Errorf("open module BTF handle (id=%d): %w", meta.ModBtfObjID, err)
408+
}
409+
modH = h
410+
attr.AttachBtfObjFd = uint32(h.FD())
411+
defer modH.Close()
412+
}
413+
}
414+
}
415+
398416
if platform.IsWindows && opts.LogLevel != 0 {
399417
return nil, fmt.Errorf("log level: %w", internal.ErrNotSupportedOnOS)
400418
}

0 commit comments

Comments
 (0)