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
|
package link
import (
"fmt"
"runtime"
"github.com/cilium/ebpf"
"github.com/cilium/ebpf/internal/sys"
)
type TCXOptions struct {
// Index of the interface to attach to.
Interface int
// Program to attach.
Program *ebpf.Program
// One of the AttachTCX* constants.
Attach ebpf.AttachType
// Attach relative to an anchor. Optional.
Anchor Anchor
// Only attach if the expected revision matches.
ExpectedRevision uint64
// Flags control the attach behaviour. Specify an Anchor instead of
// F_LINK, F_ID, F_BEFORE, F_AFTER and R_REPLACE. Optional.
Flags uint32
}
func AttachTCX(opts TCXOptions) (Link, error) {
if opts.Interface < 0 {
return nil, fmt.Errorf("interface %d is out of bounds", opts.Interface)
}
if opts.Flags&anchorFlags != 0 {
return nil, fmt.Errorf("disallowed flags: use Anchor to specify attach target")
}
attr := sys.LinkCreateTcxAttr{
ProgFd: uint32(opts.Program.FD()),
AttachType: sys.AttachType(opts.Attach),
TargetIfindex: uint32(opts.Interface),
ExpectedRevision: opts.ExpectedRevision,
Flags: opts.Flags,
}
if opts.Anchor != nil {
fdOrID, flags, err := opts.Anchor.anchor()
if err != nil {
return nil, fmt.Errorf("attach tcx link: %w", err)
}
attr.RelativeFdOrId = fdOrID
attr.Flags |= flags
}
fd, err := sys.LinkCreateTcx(&attr)
runtime.KeepAlive(opts.Program)
runtime.KeepAlive(opts.Anchor)
if err != nil {
if haveFeatErr := haveTCX(); haveFeatErr != nil {
return nil, haveFeatErr
}
return nil, fmt.Errorf("attach tcx link: %w", err)
}
return &tcxLink{RawLink{fd, ""}}, nil
}
type tcxLink struct {
RawLink
}
var _ Link = (*tcxLink)(nil)
func (tcx *tcxLink) Info() (*Info, error) {
var info sys.TcxLinkInfo
if err := sys.ObjInfo(tcx.fd, &info); err != nil {
return nil, fmt.Errorf("tcx link info: %s", err)
}
extra := &TCXInfo{
Ifindex: info.Ifindex,
AttachType: info.AttachType,
}
return &Info{
info.Type,
info.Id,
ebpf.ProgramID(info.ProgId),
extra,
}, nil
}
|