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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
package link
import (
"fmt"
"github.com/cilium/ebpf"
"github.com/cilium/ebpf/internal/sys"
)
const anchorFlags = sys.BPF_F_REPLACE |
sys.BPF_F_BEFORE |
sys.BPF_F_AFTER |
sys.BPF_F_ID |
sys.BPF_F_LINK_MPROG
// Anchor is a reference to a link or program.
//
// It is used to describe where an attachment or detachment should take place
// for link types which support multiple attachment.
type Anchor interface {
// anchor returns an fd or ID and a set of flags.
//
// By default fdOrID is taken to reference a program, but BPF_F_LINK_MPROG
// changes this to refer to a link instead.
//
// BPF_F_BEFORE, BPF_F_AFTER, BPF_F_REPLACE modify where a link or program
// is attached. The default behaviour if none of these flags is specified
// matches BPF_F_AFTER.
anchor() (fdOrID, flags uint32, _ error)
}
type firstAnchor struct{}
func (firstAnchor) anchor() (fdOrID, flags uint32, _ error) {
return 0, sys.BPF_F_BEFORE, nil
}
// Head is the position before all other programs or links.
func Head() Anchor {
return firstAnchor{}
}
type lastAnchor struct{}
func (lastAnchor) anchor() (fdOrID, flags uint32, _ error) {
return 0, sys.BPF_F_AFTER, nil
}
// Tail is the position after all other programs or links.
func Tail() Anchor {
return lastAnchor{}
}
// Before is the position just in front of target.
func BeforeLink(target Link) Anchor {
return anchor{target, sys.BPF_F_BEFORE}
}
// After is the position just after target.
func AfterLink(target Link) Anchor {
return anchor{target, sys.BPF_F_AFTER}
}
// Before is the position just in front of target.
func BeforeLinkByID(target ID) Anchor {
return anchor{target, sys.BPF_F_BEFORE}
}
// After is the position just after target.
func AfterLinkByID(target ID) Anchor {
return anchor{target, sys.BPF_F_AFTER}
}
// Before is the position just in front of target.
func BeforeProgram(target *ebpf.Program) Anchor {
return anchor{target, sys.BPF_F_BEFORE}
}
// After is the position just after target.
func AfterProgram(target *ebpf.Program) Anchor {
return anchor{target, sys.BPF_F_AFTER}
}
// Replace the target itself.
func ReplaceProgram(target *ebpf.Program) Anchor {
return anchor{target, sys.BPF_F_REPLACE}
}
// Before is the position just in front of target.
func BeforeProgramByID(target ebpf.ProgramID) Anchor {
return anchor{target, sys.BPF_F_BEFORE}
}
// After is the position just after target.
func AfterProgramByID(target ebpf.ProgramID) Anchor {
return anchor{target, sys.BPF_F_AFTER}
}
// Replace the target itself.
func ReplaceProgramByID(target ebpf.ProgramID) Anchor {
return anchor{target, sys.BPF_F_REPLACE}
}
type anchor struct {
target any
position uint32
}
func (ap anchor) anchor() (fdOrID, flags uint32, _ error) {
var typeFlag uint32
switch target := ap.target.(type) {
case *ebpf.Program:
fd := target.FD()
if fd < 0 {
return 0, 0, sys.ErrClosedFd
}
fdOrID = uint32(fd)
typeFlag = 0
case ebpf.ProgramID:
fdOrID = uint32(target)
typeFlag = sys.BPF_F_ID
case interface{ FD() int }:
fd := target.FD()
if fd < 0 {
return 0, 0, sys.ErrClosedFd
}
fdOrID = uint32(fd)
typeFlag = sys.BPF_F_LINK_MPROG
case ID:
fdOrID = uint32(target)
typeFlag = sys.BPF_F_LINK_MPROG | sys.BPF_F_ID
default:
return 0, 0, fmt.Errorf("invalid target %T", ap.target)
}
return fdOrID, ap.position | typeFlag, nil
}
|