Skip to content

Commit

Permalink
link: Add Info interface support for perf event kprobe link
Browse files Browse the repository at this point in the history
Implementing Info function (Link interface) for perf event
kprobe link, it's now possibe to retrieve link's info with:

  info, err := link.Info()
  if err != nil {
    return err
  }
  pevent := info.PerfEvent()
  kp := pevent.Kprobe()

At the moment we support/return only Addr and Missed fields.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
  • Loading branch information
olsajiri committed Mar 28, 2024
1 parent bc04a0d commit 53e95f9
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 2 deletions.
4 changes: 4 additions & 0 deletions internal/sys/syscall.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ func (i *KprobeMultiLinkInfo) info() (unsafe.Pointer, uint32) {
return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i))
}

func (i *KprobeLinkInfo) info() (unsafe.Pointer, uint32) {
return unsafe.Pointer(i), uint32(unsafe.Sizeof(*i))
}

var _ Info = (*BtfInfo)(nil)

func (i *BtfInfo) info() (unsafe.Pointer, uint32) {
Expand Down
50 changes: 48 additions & 2 deletions link/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,16 @@ type KprobeMultiInfo struct {
Missed uint64
}

type PerfEventInfo struct {
PerfEventType sys.PerfEventType
extra interface{}
}

type KprobeInfo struct {
Addr uint64
Missed uint64
}

// Tracing returns tracing type-specific link info.
//
// Returns nil if the type-specific link info isn't available.
Expand Down Expand Up @@ -264,6 +274,19 @@ func (r Info) KprobeMulti() *KprobeMultiInfo {
return e
}

// PerfEvent returns perf-event type-specific link info.
//
// Returns nil if the type-specific link info isn't available.
func (r Info) PerfEvent() *PerfEventInfo {
e, _ := r.extra.(*PerfEventInfo)
return e
}

func (r *PerfEventInfo) Kprobe() *KprobeInfo {
e, _ := r.extra.(*KprobeInfo)
return e
}

// RawLink is the low-level API to bpf_link.
//
// You should consider using the higher level interfaces in this
Expand Down Expand Up @@ -439,8 +462,7 @@ func (l *RawLink) Info() (*Info, error) {
extra = &XDPInfo{
Ifindex: xdpInfo.Ifindex,
}
case RawTracepointType, IterType,
PerfEventType, UprobeMultiType:
case RawTracepointType, IterType, UprobeMultiType:
// Extra metadata not supported.
case TCXType:
var tcxInfo sys.TcxLinkInfo
Expand Down Expand Up @@ -487,6 +509,30 @@ func (l *RawLink) Info() (*Info, error) {
Flags: kprobeMultiInfo.Flags,
Missed: kprobeMultiInfo.Missed,
}
case PerfEventType:
var kprobeInfo sys.KprobeLinkInfo
if err := sys.ObjInfo(l.fd, &kprobeInfo); err != nil {
return nil, fmt.Errorf("kprobe multi link info: %s", err)
}
var extra2 interface{}

switch kprobeInfo.PerfEventType {
case KprobePerfEventInfoType, KretprobePerfEventInfoType:
// There's a gap between when perf link got introduced and
// when it supported link info interface. We can detect that
// with kprobe specific Addr field being zero.
if kprobeInfo.Addr == 0 {
return nil, fmt.Errorf("perf event link info: %w", ErrNotSupported)
}
extra2 = &KprobeInfo{
Addr: kprobeInfo.Addr,
Missed: kprobeInfo.Missed,
}
}
extra = &PerfEventInfo{
PerfEventType: kprobeInfo.PerfEventType,
extra: extra2,
}
default:
return nil, fmt.Errorf("unknown link info type: %d", info.Type)
}
Expand Down
10 changes: 10 additions & 0 deletions link/link_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,16 @@ func testLink(t *testing.T, link Link, prog *ebpf.Program) {
if kmulti.Count == 0 {
t.Fatalf("Failed to get link KprobeMulti extra info")
}
case sys.BPF_LINK_TYPE_PERF_EVENT:
// test default Info data
pevent := info.PerfEvent()
switch pevent.PerfEventType {
case KprobePerfEventInfoType, KretprobePerfEventInfoType:
kp := pevent.Kprobe()
if kp.Addr == 0 {
t.Fatalf("Failed to get link Kprobe extra info")
}
}
}
})

Expand Down

0 comments on commit 53e95f9

Please sign in to comment.