/
anchor.go
137 lines (114 loc) · 3.28 KB
/
anchor.go
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
}