github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/link/netkit.go (about) 1 package link 2 3 import ( 4 "fmt" 5 "runtime" 6 7 "github.com/cilium/ebpf" 8 "github.com/cilium/ebpf/internal/sys" 9 ) 10 11 type NetkitOptions struct { 12 // Index of the interface to attach to. 13 Interface int 14 // Program to attach. 15 Program *ebpf.Program 16 // One of the AttachNetkit* constants. 17 Attach ebpf.AttachType 18 // Attach relative to an anchor. Optional. 19 Anchor Anchor 20 // Only attach if the expected revision matches. 21 ExpectedRevision uint64 22 // Flags control the attach behaviour. Specify an Anchor instead of 23 // F_LINK, F_ID, F_BEFORE, F_AFTER and R_REPLACE. Optional. 24 Flags uint32 25 } 26 27 func AttachNetkit(opts NetkitOptions) (Link, error) { 28 if opts.Interface < 0 { 29 return nil, fmt.Errorf("interface %d is out of bounds", opts.Interface) 30 } 31 32 if opts.Flags&anchorFlags != 0 { 33 return nil, fmt.Errorf("disallowed flags: use Anchor to specify attach target") 34 } 35 36 attr := sys.LinkCreateNetkitAttr{ 37 ProgFd: uint32(opts.Program.FD()), 38 AttachType: sys.AttachType(opts.Attach), 39 TargetIfindex: uint32(opts.Interface), 40 ExpectedRevision: opts.ExpectedRevision, 41 Flags: opts.Flags, 42 } 43 44 if opts.Anchor != nil { 45 fdOrID, flags, err := opts.Anchor.anchor() 46 if err != nil { 47 return nil, fmt.Errorf("attach netkit link: %w", err) 48 } 49 50 attr.RelativeFdOrId = fdOrID 51 attr.Flags |= flags 52 } 53 54 fd, err := sys.LinkCreateNetkit(&attr) 55 runtime.KeepAlive(opts.Program) 56 runtime.KeepAlive(opts.Anchor) 57 if err != nil { 58 if haveFeatErr := haveNetkit(); haveFeatErr != nil { 59 return nil, haveFeatErr 60 } 61 return nil, fmt.Errorf("attach netkit link: %w", err) 62 } 63 64 return &netkitLink{RawLink{fd, ""}}, nil 65 } 66 67 type netkitLink struct { 68 RawLink 69 } 70 71 var _ Link = (*netkitLink)(nil)