Skip to content

Commit c2f2792

Browse files
committed
struct_ops: implement preLoad()
Signed-off-by: shun159 <[email protected]>
1 parent 86f162b commit c2f2792

File tree

4 files changed

+486
-52
lines changed

4 files changed

+486
-52
lines changed

collection_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -777,16 +777,18 @@ func TestStructOpsMapSpecSimpleLoadAndAssign(t *testing.T) {
777777

778778
spec := &CollectionSpec{
779779
Maps: map[string]*MapSpec{
780+
// TODO: we should use "bpf_testmod_ops" for this case (tentative test case)
780781
"dummy_ops": {
781782
Name: "dummy_ops",
782783
Type: StructOpsMap,
783784
KeySize: 4,
784785
ValueSize: 128,
785786
MaxEntries: 1,
787+
Value: &btf.Struct{Name: "bpf_dummy_ops"},
786788
Contents: []MapKV{
787789
{Key: uint32(0), Value: structOpsMeta{
788-
userTypeName: "bpf_dummy_ops",
789-
kernTypeName: "bpf_struct_ops_bpf_dummy_ops",
790+
data: make([]byte, 128),
791+
funcs: []structOpsFunc{},
790792
}},
791793
},
792794
},

map.go

Lines changed: 50 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -547,60 +547,65 @@ func (spec *MapSpec) createMap(inner *sys.FD) (_ *Map, err error) {
547547
}
548548

549549
if spec.Key != nil || spec.Value != nil {
550-
handle, keyTypeID, valueTypeID, err := btf.MarshalMapKV(spec.Key, spec.Value)
551-
if err != nil && !errors.Is(err, btf.ErrNotSupported) {
552-
return nil, fmt.Errorf("load BTF: %w", err)
553-
}
550+
if spec.Type == StructOpsMap {
551+
// we need drop meta entry here
552+
if len(spec.Contents) > 0 {
553+
spec.Contents = spec.Contents[1:]
554+
}
554555

555-
if handle != nil {
556-
defer handle.Close()
556+
var b btf.Builder
557+
h, err := btf.NewHandle(&b)
558+
if err != nil {
559+
return nil, err
560+
}
561+
defer h.Close()
557562

558-
// Use BTF k/v during map creation.
559-
attr.BtfFd = uint32(handle.FD())
560-
attr.BtfKeyTypeId = keyTypeID
561-
attr.BtfValueTypeId = valueTypeID
562-
}
563-
}
563+
s, err := btf.LoadKernelSpec()
564+
if err != nil {
565+
return nil, fmt.Errorf("open vmlinux BTF: %w", err)
566+
}
564567

565-
if spec.Type == StructOpsMap {
566-
meta, err := extractStructOpsMeta(spec.Contents)
567-
if err != nil {
568-
return nil, err
569-
}
568+
if spec.Value == nil {
569+
return nil, fmt.Errorf("Struct type is not specified as Value")
570+
}
570571

571-
// we need drop meta entry here
572-
if len(spec.Contents) > 0 {
573-
spec.Contents = spec.Contents[1:]
574-
}
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+
}
575580

576-
var b btf.Builder
577-
h, err := btf.NewHandle(&b)
578-
if err != nil {
579-
return nil, err
580-
}
581-
defer h.Close()
581+
userStructType, ok := t.(*btf.Struct)
582+
if !ok {
583+
return nil, fmt.Errorf("Value must be Struct type")
584+
}
582585

583-
s, err := btf.LoadKernelSpec()
584-
if err != nil {
585-
return nil, fmt.Errorf("open vmlinux BTF: %w", err)
586-
}
586+
btfValueTypeId, err := s.TypeID(userStructType)
587+
if err != nil {
588+
return nil, fmt.Errorf("lookup type_id: %w", err)
589+
}
587590

588-
typeSpec, err := s.AnyTypeByName(meta.kernTypeName)
589-
if errors.Is(err, btf.ErrNotFound) {
590-
return nil, fmt.Errorf("struct_ops kernel type %q: %w", meta.kernTypeName, ErrNotSupported)
591-
}
592-
if err != nil {
593-
return nil, fmt.Errorf("lookup kernel type %q: %w", meta.kernTypeName, err)
594-
}
591+
attr.ValueSize = spec.ValueSize
592+
attr.BtfVmlinuxValueTypeId = btfValueTypeId
593+
attr.BtfFd = uint32(h.FD())
594+
} else {
595+
handle, keyTypeID, valueTypeID, err := btf.MarshalMapKV(spec.Key, spec.Value)
596+
if err != nil && !errors.Is(err, btf.ErrNotSupported) {
597+
return nil, fmt.Errorf("load BTF: %w", err)
598+
}
595599

596-
btfValueTypeId, err := s.TypeID(typeSpec)
597-
if err != nil {
598-
return nil, fmt.Errorf("lookup type_id of %s: %w", typeSpec.TypeName(), err)
599-
}
600+
if handle != nil {
601+
defer handle.Close()
600602

601-
attr.ValueSize = spec.ValueSize
602-
attr.BtfVmlinuxValueTypeId = btfValueTypeId
603-
attr.BtfFd = uint32(h.FD())
603+
// Use BTF k/v during map creation.
604+
attr.BtfFd = uint32(handle.FD())
605+
attr.BtfKeyTypeId = keyTypeID
606+
attr.BtfValueTypeId = valueTypeID
607+
}
608+
}
604609
}
605610

606611
fd, err := sys.MapCreate(&attr)

0 commit comments

Comments
 (0)