1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
package link
import (
"fmt"
"runtime"
"github.com/cilium/ebpf"
"github.com/cilium/ebpf/internal/sys"
)
type RawAttachProgramOptions struct {
// Target to query. This is usually a file descriptor but may refer to
// something else based on the attach type.
Target int
// Program to attach.
Program *ebpf.Program
// Attach must match the attach type of Program.
Attach ebpf.AttachType
// Attach relative to an anchor. Optional.
Anchor Anchor
// Flags control the attach behaviour. Specify an Anchor instead of
// F_LINK, F_ID, F_BEFORE, F_AFTER and F_REPLACE. Optional.
Flags uint32
// Only attach if the internal revision matches the given value.
ExpectedRevision uint64
}
// RawAttachProgram is a low level wrapper around BPF_PROG_ATTACH.
//
// You should use one of the higher level abstractions available in this
// package if possible.
func RawAttachProgram(opts RawAttachProgramOptions) error {
if opts.Flags&anchorFlags != 0 {
return fmt.Errorf("disallowed flags: use Anchor to specify attach target")
}
attr := sys.ProgAttachAttr{
TargetFdOrIfindex: uint32(opts.Target),
AttachBpfFd: uint32(opts.Program.FD()),
AttachType: uint32(opts.Attach),
AttachFlags: uint32(opts.Flags),
ExpectedRevision: opts.ExpectedRevision,
}
if opts.Anchor != nil {
fdOrID, flags, err := opts.Anchor.anchor()
if err != nil {
return fmt.Errorf("attach program: %w", err)
}
if flags == sys.BPF_F_REPLACE {
// Ensure that replacing a program works on old kernels.
attr.ReplaceBpfFd = fdOrID
} else {
attr.RelativeFdOrId = fdOrID
attr.AttachFlags |= flags
}
}
if err := sys.ProgAttach(&attr); err != nil {
if haveFeatErr := haveProgAttach(); haveFeatErr != nil {
return haveFeatErr
}
return fmt.Errorf("attach program: %w", err)
}
runtime.KeepAlive(opts.Program)
return nil
}
type RawDetachProgramOptions RawAttachProgramOptions
// RawDetachProgram is a low level wrapper around BPF_PROG_DETACH.
//
// You should use one of the higher level abstractions available in this
// package if possible.
func RawDetachProgram(opts RawDetachProgramOptions) error {
if opts.Flags&anchorFlags != 0 {
return fmt.Errorf("disallowed flags: use Anchor to specify attach target")
}
attr := sys.ProgDetachAttr{
TargetFdOrIfindex: uint32(opts.Target),
AttachBpfFd: uint32(opts.Program.FD()),
AttachType: uint32(opts.Attach),
ExpectedRevision: opts.ExpectedRevision,
}
if opts.Anchor != nil {
fdOrID, flags, err := opts.Anchor.anchor()
if err != nil {
return fmt.Errorf("detach program: %w", err)
}
attr.RelativeFdOrId = fdOrID
attr.AttachFlags |= flags
}
if err := sys.ProgDetach(&attr); err != nil {
if haveFeatErr := haveProgAttach(); haveFeatErr != nil {
return haveFeatErr
}
return fmt.Errorf("can't detach program: %w", err)
}
return nil
}
|