Skip to content

Commit 513d0ef

Browse files
committed
struct_ops: switch to AttachTo for program binding
Replace use of structOpsProgMeta metadata with ProgramSpec.AttachTo (e.g. "bpf_testmod_ops:test_1") to encode attach target, and drop structOpsProgMeta, adjust tests accordingly. Signed-off-by: shun159 <[email protected]>
1 parent ba0845c commit 513d0ef

File tree

4 files changed

+72
-35
lines changed

4 files changed

+72
-35
lines changed

collection.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -839,12 +839,8 @@ func (cl *collectionLoader) copyDataMember(
839839
structOps.progAttachType[ps.Name] = attachType
840840
cl.stOpsProgsToMap[ps.Name] = ms.Name
841841

842-
// seed program with attach metadata (checked at load time)
843-
ps.Instructions[0].Metadata.Set(structOpsProgMetaKey{}, &structOpsProgMeta{
844-
attachBtfId: kern.typeID,
845-
attachType: attachType,
846-
modBtfObjID: kern.modBtfObjId,
847-
})
842+
// set `AttachTo` for struct_ops prog; e.g. "bpf_testmod_ops:test_1"
843+
ps.AttachTo = fmt.Sprintf("%s:%s", kern.typ.Name, memberName)
848844
}
849845

850846
// Handle data member. copy data members from the user-defined struct to the kernel data buffer.

collection_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -778,8 +778,8 @@ func TestStructOpsMapSpecSimpleLoadAndAssign(t *testing.T) {
778778

779779
spec := &CollectionSpec{
780780
Programs: map[string]*ProgramSpec{
781-
"test_func_1": {
782-
Name: "test_func_1",
781+
"test_1": {
782+
Name: "test_1",
783783
Type: StructOps,
784784
License: "GPL",
785785
Instructions: asm.Instructions{
@@ -801,7 +801,7 @@ func TestStructOpsMapSpecSimpleLoadAndAssign(t *testing.T) {
801801
{Key: uint32(0), Value: structOpsMeta{
802802
data: make([]byte, 448),
803803
funcs: []structOpsFunc{
804-
{"test_1", "test_func_1"},
804+
{"test_1", "test_1"},
805805
},
806806
}},
807807
},

prog.go

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"math"
99
"path/filepath"
1010
"runtime"
11+
"strings"
1112
"time"
1213

1314
"github.com/cilium/ebpf/asm"
@@ -381,38 +382,66 @@ func newProgramWithOptions(spec *ProgramSpec, opts ProgramOptions, c *btf.Cache)
381382
attr.AttachBtfObjFd = uint32(spec.AttachTarget.FD())
382383
defer runtime.KeepAlive(spec.AttachTarget)
383384
} else if spec.AttachTo != "" {
384-
module, targetID, err := findProgramTargetInKernel(spec.AttachTo, spec.Type, spec.AttachType)
385+
var targetMember string
386+
var ok bool
387+
attachTo := spec.AttachTo
388+
389+
if spec.Type == StructOps {
390+
attachTo, targetMember, ok = strings.Cut(attachTo, ":")
391+
if !ok || attachTo == "" || targetMember == "" {
392+
return nil, fmt.Errorf("invalid AttachTo for StructOps (type:member): %q", spec.AttachTo)
393+
}
394+
}
395+
396+
module, targetID, err := findProgramTargetInKernel(attachTo, spec.Type, spec.AttachType)
385397
if err != nil && !errors.Is(err, errUnrecognizedAttachType) {
386398
// We ignore errUnrecognizedAttachType since AttachTo may be non-empty
387399
// for programs that don't attach anywhere.
388400
return nil, fmt.Errorf("attach %s/%s: %w", spec.Type, spec.AttachType, err)
389401
}
390402

391403
attr.AttachBtfId = targetID
392-
if module != nil {
393-
attr.AttachBtfObjFd = uint32(module.FD())
394-
defer module.Close()
395-
}
396-
}
404+
if spec.Type == StructOps {
405+
// we need to resolve `target` here, load the kernel spec
406+
s, err := btf.LoadKernelSpec()
407+
if err != nil {
408+
return nil, fmt.Errorf("load vmlinux BTF: %w", err)
409+
}
397410

398-
if spec.Type == StructOps {
399-
if meta, ok := spec.Instructions[0].Metadata.Get(structOpsProgMetaKey{}).(*structOpsProgMeta); ok {
400-
// set AttachBtfId / ExpectedAttachType from metadata
401-
attr.AttachBtfId = sys.TypeID(meta.attachBtfId)
402-
attr.ExpectedAttachType = meta.attachType
411+
st, spec2, modBtfObjID, err := doFindStructTypeByName(s, attachTo)
412+
fmt.Println("hogehogehogheoge", st, err)
413+
if err != nil {
414+
return nil, err
415+
}
403416

404-
var modH *btf.Handle
405-
if meta.modBtfObjID != 0 {
406-
h, err := btf.NewHandleFromID(btf.ID(meta.modBtfObjID))
417+
tid, err := spec2.TypeID(st)
418+
if err != nil {
419+
return nil, fmt.Errorf("type id for %s: %w", st.TypeName(), err)
420+
}
421+
attr.AttachBtfId = sys.TypeID(tid)
422+
423+
idx := getStructMemberIndexByName(st, targetMember)
424+
fmt.Println(idx, "hogehogehoge")
425+
if idx < 0 {
426+
return nil, fmt.Errorf("member %q not found in %s", targetMember, st.Name)
427+
}
428+
429+
attr.ExpectedAttachType = sys.AttachType(idx)
430+
431+
if modBtfObjID != 0 {
432+
h, err := btf.NewHandleFromID(btf.ID(modBtfObjID))
407433
if err != nil {
408-
return nil, fmt.Errorf("open module BTF handle (id=%d): %w", meta.modBtfObjID, err)
434+
return nil, fmt.Errorf("open module BTF handle (id=%d): %w", modBtfObjID, err)
409435
}
410-
modH = h
411-
// set AttachBtfObjFd if the type comes from a module
436+
defer h.Close()
412437
attr.AttachBtfObjFd = uint32(h.FD())
413-
defer modH.Close()
414438
}
415439
}
440+
441+
if module != nil {
442+
attr.AttachBtfObjFd = uint32(module.FD())
443+
defer module.Close()
444+
}
416445
}
417446

418447
if platform.IsWindows && opts.LogLevel != 0 {
@@ -1059,6 +1088,10 @@ func findProgramTargetInKernel(name string, progType ProgramType, attachType Att
10591088
)
10601089

10611090
switch (match{progType, attachType}) {
1091+
case match{StructOps, AttachStructOps}:
1092+
typeName = name
1093+
featureName = "struct_ops " + name
1094+
target = (*btf.Struct)(nil)
10621095
case match{LSM, AttachLSMMac}:
10631096
typeName = "bpf_lsm_" + name
10641097
featureName = name + " LSM hook"

struct_ops.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,6 @@ import (
1010

1111
const structOpsValuePrefix = "bpf_struct_ops_"
1212

13-
// TODO: Doc
14-
type structOpsProgMetaKey struct{}
15-
type structOpsProgMeta struct {
16-
attachBtfId btf.TypeID
17-
attachType sys.AttachType
18-
modBtfObjID uint32
19-
}
20-
2113
// structOpsKernTypes groups all kernel-side BTF artefacts that belong to a
2214
// resolved struct_ops.
2315
type structOpsKernTypes struct {
@@ -161,6 +153,10 @@ func findStructTypeByName(s *btf.Spec, typ *btf.Struct) (*btf.Struct, *btf.Spec,
161153
return doFindStructTypeByName(s, typ.TypeName())
162154
}
163155

156+
func findStructTypeByName2(s *btf.Spec, name string) (*btf.Struct, *btf.Spec, uint32, error) {
157+
return doFindStructTypeByName(s, name)
158+
}
159+
164160
// doFindStructTypeByName looks up a struct type with the exact name in the
165161
// provided base BTF spec, and falls back to scanning all loaded module BTFs
166162
// if it is not present in vmlinux.
@@ -221,6 +217,7 @@ func findStructTypeByNameFromModule(base *btf.Spec, name string) (*btf.Struct, *
221217
if errors.Is(err, btf.ErrNotFound) {
222218
continue
223219
}
220+
224221
if err != nil {
225222
return nil, nil, 0, fmt.Errorf("lookup type in module %s: %w", info.Name, err)
226223
}
@@ -332,6 +329,17 @@ func getStructMemberIndexOf(s *btf.Struct, member btf.Member) int {
332329
return -1
333330
}
334331

332+
// getStructMemberIndexByName returns the index of `member` within struct `s` by
333+
// comparing the member name.
334+
func getStructMemberIndexByName(s *btf.Struct, name string) int {
335+
for idx, m := range s.Members {
336+
if m.Name == name {
337+
return idx
338+
}
339+
}
340+
return -1
341+
}
342+
335343
// check if the buffer is filled with 0
336344
func isMemoryZero(p []byte) bool {
337345
for _, b := range p {

0 commit comments

Comments
 (0)