Skip to content

Commit

Permalink
link/perf_event: attach via bpf_link if available
Browse files Browse the repository at this point in the history
Signed-off-by: Mattia Meleleo <mattia.meleleo@elastic.co>
  • Loading branch information
mmat11 committed Feb 11, 2022
1 parent 7816b93 commit 4023616
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 46 deletions.
8 changes: 8 additions & 0 deletions internal/cmd/gentypes/main.go
Expand Up @@ -342,6 +342,14 @@ import (
replace(pointer, "iter_info"),
},
},
{
"LinkCreatePerfEvent", retFd, "link_create", "BPF_LINK_CREATE",
[]patch{
chooseNth(4, 2),
replace(enumTypes["AttachType"], "attach_type"),
flattenAnon,
},
},
{
"LinkUpdate", retError, "link_update", "BPF_LINK_UPDATE",
nil,
Expand Down
127 changes: 85 additions & 42 deletions internal/sys/types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

75 changes: 71 additions & 4 deletions link/perf_event.go
Expand Up @@ -13,6 +13,8 @@ import (
"unsafe"

"github.com/cilium/ebpf"
"github.com/cilium/ebpf/asm"
"github.com/cilium/ebpf/internal"
"github.com/cilium/ebpf/internal/sys"
"github.com/cilium/ebpf/internal/unix"
)
Expand Down Expand Up @@ -82,6 +84,9 @@ type perfEvent struct {
// The event type determines the types of programs that can be attached.
typ perfEventType

// BPF link FD.
bpfLinkFD *sys.FD

fd *sys.FD
}

Expand Down Expand Up @@ -128,6 +133,13 @@ func (pe *perfEvent) Close() error {
return fmt.Errorf("closing perf event fd: %w", err)
}

if pe.bpfLinkFD != nil {
err = pe.bpfLinkFD.Close()
if err != nil {
return fmt.Errorf("closing bpf perf link: %w", err)
}
}

switch pe.typ {
case kprobeEvent, kretprobeEvent:
// Clean up kprobe tracefs entry.
Expand Down Expand Up @@ -175,10 +187,27 @@ func (pe *perfEvent) attach(prog *ebpf.Program) error {

kfd := pe.fd.Int()

// Assign the eBPF program to the perf event.
err := unix.IoctlSetInt(int(kfd), unix.PERF_EVENT_IOC_SET_BPF, prog.FD())
if err != nil {
return fmt.Errorf("setting perf event bpf program: %w", err)
if err := haveBPFLinkPerfEvent(); err == nil {
// Use the bpf api to attach the perf event (BPF_LINK_TYPE_PERF_EVENT, 5.15+).
//
// https://github.com/torvalds/linux/commit/b89fbfbb854c9afc3047e8273cc3a694650b802e
attr := sys.LinkCreatePerfEventAttr{
ProgFd: uint32(prog.FD()),
TargetFd: uint32(kfd),
AttachType: sys.BPF_PERF_EVENT,
}

fd, err := sys.LinkCreatePerfEvent(&attr)
if err != nil {
return fmt.Errorf("cannot create bpf perf link: %v", err)
}
pe.bpfLinkFD = fd
} else {
// Assign the eBPF program to the perf event.
err := unix.IoctlSetInt(int(kfd), unix.PERF_EVENT_IOC_SET_BPF, prog.FD())
if err != nil {
return fmt.Errorf("setting perf event bpf program: %w", err)
}
}

// PERF_EVENT_IOC_ENABLE and _DISABLE ignore their given values.
Expand Down Expand Up @@ -268,3 +297,41 @@ func uint64FromFile(base string, path ...string) (uint64, error) {
et := bytes.TrimSpace(data)
return strconv.ParseUint(string(et), 10, 64)
}

// Probe BPF perf link.
//
// https://elixir.bootlin.com/linux/v5.16.8/source/kernel/bpf/syscall.c#L4307
// https://github.com/torvalds/linux/commit/b89fbfbb854c9afc3047e8273cc3a694650b802e
var haveBPFLinkPerfEvent = internal.FeatureTest("bpf_link_perf_event", "5.15", func() error {
prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
Name: "probe_bpf_perf_link",
Type: ebpf.Kprobe,
Instructions: asm.Instructions{
asm.Mov.Imm(asm.R0, 0),
asm.Return(),
},
License: "MIT",
})
if err != nil {
return err
}

fd, err := sys.NewFD(prog.FD())
if err != nil {
return err
}
defer fd.Close()

attr := sys.LinkCreatePerfEventAttr{
ProgFd: fd.Uint(),
AttachType: sys.BPF_PERF_EVENT,
}
_, err = sys.LinkCreatePerfEvent(&attr)
if errors.Is(err, unix.EINVAL) {
return internal.ErrNotSupported
}
if errors.Is(err, unix.EBADF) {
return nil
}
return err
})
4 changes: 4 additions & 0 deletions link/perf_event_test.go
Expand Up @@ -73,3 +73,7 @@ func TestTraceEventRegex(t *testing.T) {
})
}
}

func TestHaveBPFLinkPerfEvent(t *testing.T) {
testutils.CheckFeatureTest(t, haveBPFLinkPerfEvent)
}

0 comments on commit 4023616

Please sign in to comment.