github.com/cilium/ebpf@v0.15.1-0.20240517100537-8079b37aa138/link/anchor.go (about) 1 package link 2 3 import ( 4 "fmt" 5 6 "github.com/cilium/ebpf" 7 "github.com/cilium/ebpf/internal/sys" 8 ) 9 10 const anchorFlags = sys.BPF_F_REPLACE | 11 sys.BPF_F_BEFORE | 12 sys.BPF_F_AFTER | 13 sys.BPF_F_ID | 14 sys.BPF_F_LINK_MPROG 15 16 // Anchor is a reference to a link or program. 17 // 18 // It is used to describe where an attachment or detachment should take place 19 // for link types which support multiple attachment. 20 type Anchor interface { 21 // anchor returns an fd or ID and a set of flags. 22 // 23 // By default fdOrID is taken to reference a program, but BPF_F_LINK_MPROG 24 // changes this to refer to a link instead. 25 // 26 // BPF_F_BEFORE, BPF_F_AFTER, BPF_F_REPLACE modify where a link or program 27 // is attached. The default behaviour if none of these flags is specified 28 // matches BPF_F_AFTER. 29 anchor() (fdOrID, flags uint32, _ error) 30 } 31 32 type firstAnchor struct{} 33 34 func (firstAnchor) anchor() (fdOrID, flags uint32, _ error) { 35 return 0, sys.BPF_F_BEFORE, nil 36 } 37 38 // Head is the position before all other programs or links. 39 func Head() Anchor { 40 return firstAnchor{} 41 } 42 43 type lastAnchor struct{} 44 45 func (lastAnchor) anchor() (fdOrID, flags uint32, _ error) { 46 return 0, sys.BPF_F_AFTER, nil 47 } 48 49 // Tail is the position after all other programs or links. 50 func Tail() Anchor { 51 return lastAnchor{} 52 } 53 54 // Before is the position just in front of target. 55 func BeforeLink(target Link) Anchor { 56 return anchor{target, sys.BPF_F_BEFORE} 57 } 58 59 // After is the position just after target. 60 func AfterLink(target Link) Anchor { 61 return anchor{target, sys.BPF_F_AFTER} 62 } 63 64 // Before is the position just in front of target. 65 func BeforeLinkByID(target ID) Anchor { 66 return anchor{target, sys.BPF_F_BEFORE} 67 } 68 69 // After is the position just after target. 70 func AfterLinkByID(target ID) Anchor { 71 return anchor{target, sys.BPF_F_AFTER} 72 } 73 74 // Before is the position just in front of target. 75 func BeforeProgram(target *ebpf.Program) Anchor { 76 return anchor{target, sys.BPF_F_BEFORE} 77 } 78 79 // After is the position just after target. 80 func AfterProgram(target *ebpf.Program) Anchor { 81 return anchor{target, sys.BPF_F_AFTER} 82 } 83 84 // Replace the target itself. 85 func ReplaceProgram(target *ebpf.Program) Anchor { 86 return anchor{target, sys.BPF_F_REPLACE} 87 } 88 89 // Before is the position just in front of target. 90 func BeforeProgramByID(target ebpf.ProgramID) Anchor { 91 return anchor{target, sys.BPF_F_BEFORE} 92 } 93 94 // After is the position just after target. 95 func AfterProgramByID(target ebpf.ProgramID) Anchor { 96 return anchor{target, sys.BPF_F_AFTER} 97 } 98 99 // Replace the target itself. 100 func ReplaceProgramByID(target ebpf.ProgramID) Anchor { 101 return anchor{target, sys.BPF_F_REPLACE} 102 } 103 104 type anchor struct { 105 target any 106 position uint32 107 } 108 109 func (ap anchor) anchor() (fdOrID, flags uint32, _ error) { 110 var typeFlag uint32 111 switch target := ap.target.(type) { 112 case *ebpf.Program: 113 fd := target.FD() 114 if fd < 0 { 115 return 0, 0, sys.ErrClosedFd 116 } 117 fdOrID = uint32(fd) 118 typeFlag = 0 119 case ebpf.ProgramID: 120 fdOrID = uint32(target) 121 typeFlag = sys.BPF_F_ID 122 case interface{ FD() int }: 123 fd := target.FD() 124 if fd < 0 { 125 return 0, 0, sys.ErrClosedFd 126 } 127 fdOrID = uint32(fd) 128 typeFlag = sys.BPF_F_LINK_MPROG 129 case ID: 130 fdOrID = uint32(target) 131 typeFlag = sys.BPF_F_LINK_MPROG | sys.BPF_F_ID 132 default: 133 return 0, 0, fmt.Errorf("invalid target %T", ap.target) 134 } 135 136 return fdOrID, ap.position | typeFlag, nil 137 }